PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwutil.c
Go to the documentation of this file.
1/**********************************************************************
2 *
3 * PostGIS - Spatial Types for PostgreSQL
4 * http://postgis.net
5 *
6 * PostGIS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * PostGIS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **********************************************************************
20 *
21 * Copyright (C) 2004-2015 Sandro Santilli <strk@kbt.io>
22 * Copyright (C) 2006 Mark Leslie <mark.leslie@lisasoft.com>
23 * Copyright (C) 2008-2009 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
24 * Copyright (C) 2009-2015 Paul Ramsey <pramsey@cleverelephant.ca>
25 * Copyright (C) 2010 Olivier Courtin <olivier.courtin@camptocamp.com>
26 *
27 **********************************************************************/
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdarg.h>
32#include <string.h>
33#include <ctype.h> /* for tolower */
34
35/* Global variables */
36#include "../postgis_config.h"
37#include "liblwgeom_internal.h"
38#include "lwgeom_log.h"
39
40/* Default allocators */
41static void * default_allocator(size_t size);
42static void default_freeor(void *mem);
43static void * default_reallocator(void *mem, size_t size);
47
48/* Default reporters */
49static void default_noticereporter(const char *fmt, va_list ap);
50static void default_errorreporter(const char *fmt, va_list ap);
53
54/* Default logger */
55static void default_debuglogger(int level, const char *fmt, va_list ap);
57
58#define LW_MSG_MAXLEN 256
59
60static char *lwgeomTypeName[] =
61{
62 "Unknown",
63 "Point",
64 "LineString",
65 "Polygon",
66 "MultiPoint",
67 "MultiLineString",
68 "MultiPolygon",
69 "GeometryCollection",
70 "CircularString",
71 "CompoundCurve",
72 "CurvePolygon",
73 "MultiCurve",
74 "MultiSurface",
75 "PolyhedralSurface",
76 "Triangle",
77 "Tin"
78};
79
80/*
81 * Default allocators
82 *
83 * We include some default allocators that use malloc/free/realloc
84 * along with stdout/stderr since this is the most common use case
85 *
86 */
87
88static void *
90{
91 void *mem = malloc(size);
92 return mem;
93}
94
95static void
97{
98 free(mem);
99}
100
101static void *
102default_reallocator(void *mem, size_t size)
103{
104 void *ret = realloc(mem, size);
105 return ret;
106}
107
108/*
109 * Default lwnotice/lwerror handlers
110 *
111 * Since variadic functions cannot pass their parameters directly, we need
112 * wrappers for these functions to convert the arguments into a va_list
113 * structure.
114 */
115
116static void
117default_noticereporter(const char *fmt, va_list ap)
118{
119 char msg[LW_MSG_MAXLEN+1];
120 vsnprintf (msg, LW_MSG_MAXLEN, fmt, ap);
121 msg[LW_MSG_MAXLEN]='\0';
122 fprintf(stderr, "%s\n", msg);
123}
124
125static void
126default_debuglogger(int level, const char *fmt, va_list ap)
127{
128 char msg[LW_MSG_MAXLEN+1];
129 if ( POSTGIS_DEBUG_LEVEL >= level )
130 {
131 /* Space pad the debug output */
132 int i;
133 for ( i = 0; i < level; i++ )
134 msg[i] = ' ';
135 vsnprintf(msg+i, LW_MSG_MAXLEN-i, fmt, ap);
136 msg[LW_MSG_MAXLEN]='\0';
137 fprintf(stderr, "%s\n", msg);
138 }
139}
140
141static void
142default_errorreporter(const char *fmt, va_list ap)
143{
144 char msg[LW_MSG_MAXLEN+1];
145 vsnprintf (msg, LW_MSG_MAXLEN, fmt, ap);
146 msg[LW_MSG_MAXLEN]='\0';
147 fprintf(stderr, "%s\n", msg);
148 exit(1);
149}
150
157void
159 lwfreeor freeor, lwreporter errorreporter,
160 lwreporter noticereporter) {
161
162 if ( allocator ) lwalloc_var = allocator;
163 if ( reallocator ) lwrealloc_var = reallocator;
164 if ( freeor ) lwfree_var = freeor;
165
166 if ( errorreporter ) lwerror_var = errorreporter;
167 if ( noticereporter ) lwnotice_var = noticereporter;
168}
169
170void
172
173 if ( debuglogger ) lwdebug_var = debuglogger;
174}
175
176void
177lwnotice(const char *fmt, ...)
178{
179 va_list ap;
180
181 va_start(ap, fmt);
182
183 /* Call the supplied function */
184 (*lwnotice_var)(fmt, ap);
185
186 va_end(ap);
187}
188
189void
190lwerror(const char *fmt, ...)
191{
192 va_list ap;
193
194 va_start(ap, fmt);
195
196 /* Call the supplied function */
197 (*lwerror_var)(fmt, ap);
198
199 va_end(ap);
200}
201
202void
203lwdebug(int level, const char *fmt, ...)
204{
205 va_list ap;
206
207 va_start(ap, fmt);
208
209 /* Call the supplied function */
210 (*lwdebug_var)(level, fmt, ap);
211
212 va_end(ap);
213}
214
215const char*
216lwtype_name(uint8_t type)
217{
218 if ( type > 15 )
219 {
220 /* assert(0); */
221 return "Invalid type";
222 }
223 return lwgeomTypeName[(int ) type];
224}
225
226void *
227lwalloc(size_t size)
228{
229 void *mem = lwalloc_var(size);
230 LWDEBUGF(5, "lwalloc: %d@%p", size, mem);
231 return mem;
232}
233
234void *
235lwrealloc(void *mem, size_t size)
236{
237 LWDEBUGF(5, "lwrealloc: %d@%p", size, mem);
238 return lwrealloc_var(mem, size);
239}
240
241void
242lwfree(void *mem)
243{
244 lwfree_var(mem);
245}
246
247char *
248lwstrdup(const char* a)
249{
250 size_t l = strlen(a)+1;
251 char *b = lwalloc(l);
252 strncpy(b, a, l);
253 return b;
254}
255
256/*
257 * Returns a new string which contains a maximum of maxlength characters starting
258 * from startpos and finishing at endpos (0-based indexing). If the string is
259 * truncated then the first or last characters are replaced by "..." as
260 * appropriate.
261 *
262 * The caller should specify start or end truncation by setting the truncdirection
263 * parameter as follows:
264 * 0 - start truncation (i.e. characters are removed from the beginning)
265 * 1 - end truncation (i.e. characters are removed from the end)
266 */
267
268char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
269{
270 char *output;
271 char *outstart;
272
273 /* Allocate space for new string */
274 output = lwalloc(maxlength + 4);
275 output[0] = '\0';
276
277 /* Start truncation */
278 if (truncdirection == 0)
279 {
280 /* Calculate the start position */
281 if (endpos - startpos < maxlength)
282 {
283 outstart = str + startpos;
284 strncat(output, outstart, endpos - startpos + 1);
285 }
286 else
287 {
288 if (maxlength >= 3)
289 {
290 /* Add "..." prefix */
291 outstart = str + endpos + 1 - maxlength + 3;
292 strncat(output, "...", 4);
293 strncat(output, outstart, maxlength - 3);
294 }
295 else
296 {
297 /* maxlength is too small; just output "..." */
298 strncat(output, "...", 4);
299 }
300 }
301 }
302
303 /* End truncation */
304 if (truncdirection == 1)
305 {
306 /* Calculate the end position */
307 if (endpos - startpos < maxlength)
308 {
309 outstart = str + startpos;
310 strncat(output, outstart, endpos - startpos + 1);
311 }
312 else
313 {
314 if (maxlength >= 3)
315 {
316 /* Add "..." suffix */
317 outstart = str + startpos;
318 strncat(output, outstart, maxlength - 3);
319 strncat(output, "...", 4);
320 }
321 else
322 {
323 /* maxlength is too small; just output "..." */
324 strncat(output, "...", 4);
325 }
326 }
327 }
328
329 return output;
330}
331
332int32_t
333clamp_srid(int32_t srid)
334{
335 int newsrid = srid;
336
337 if ( newsrid <= 0 ) {
338 if ( newsrid != SRID_UNKNOWN ) {
339 newsrid = SRID_UNKNOWN;
340 lwnotice("SRID value %d converted to the officially unknown SRID value %d", srid, newsrid);
341 }
342 } else if ( srid > SRID_MAXIMUM ) {
343 newsrid = SRID_USER_MAXIMUM + 1 +
344 /* -1 is to reduce likelyhood of clashes */
345 /* NOTE: must match implementation in postgis_restore.pl */
346 ( srid % ( SRID_MAXIMUM - SRID_USER_MAXIMUM - 1 ) );
347 lwnotice("SRID value %d > SRID_MAXIMUM converted to %d", srid, newsrid);
348 }
349
350 return newsrid;
351}
352
353
354
355
356/* Structure for the type array */
358{
359 char *typename;
360 int type;
361 int z;
362 int m;
363};
364
365/* Type array. Note that the order of this array is important in
366 that any typename in the list must *NOT* occur within an entry
367 before it. Otherwise if we search for "POINT" at the top of the
368 list we would also match MULTIPOINT, for example. */
369
371{
372 { "GEOMETRYCOLLECTIONZM", COLLECTIONTYPE, 1, 1 },
373 { "GEOMETRYCOLLECTIONZ", COLLECTIONTYPE, 1, 0 },
374 { "GEOMETRYCOLLECTIONM", COLLECTIONTYPE, 0, 1 },
375 { "GEOMETRYCOLLECTION", COLLECTIONTYPE, 0, 0 },
376
377 { "GEOMETRYZM", 0, 1, 1 },
378 { "GEOMETRYZ", 0, 1, 0 },
379 { "GEOMETRYM", 0, 0, 1 },
380 { "GEOMETRY", 0, 0, 0 },
381
382 { "POLYHEDRALSURFACEZM", POLYHEDRALSURFACETYPE, 1, 1 },
383 { "POLYHEDRALSURFACEZ", POLYHEDRALSURFACETYPE, 1, 0 },
384 { "POLYHEDRALSURFACEM", POLYHEDRALSURFACETYPE, 0, 1 },
385 { "POLYHEDRALSURFACE", POLYHEDRALSURFACETYPE, 0, 0 },
386
387 { "TINZM", TINTYPE, 1, 1 },
388 { "TINZ", TINTYPE, 1, 0 },
389 { "TINM", TINTYPE, 0, 1 },
390 { "TIN", TINTYPE, 0, 0 },
391
392 { "CIRCULARSTRINGZM", CIRCSTRINGTYPE, 1, 1 },
393 { "CIRCULARSTRINGZ", CIRCSTRINGTYPE, 1, 0 },
394 { "CIRCULARSTRINGM", CIRCSTRINGTYPE, 0, 1 },
395 { "CIRCULARSTRING", CIRCSTRINGTYPE, 0, 0 },
396
397 { "COMPOUNDCURVEZM", COMPOUNDTYPE, 1, 1 },
398 { "COMPOUNDCURVEZ", COMPOUNDTYPE, 1, 0 },
399 { "COMPOUNDCURVEM", COMPOUNDTYPE, 0, 1 },
400 { "COMPOUNDCURVE", COMPOUNDTYPE, 0, 0 },
401
402 { "CURVEPOLYGONZM", CURVEPOLYTYPE, 1, 1 },
403 { "CURVEPOLYGONZ", CURVEPOLYTYPE, 1, 0 },
404 { "CURVEPOLYGONM", CURVEPOLYTYPE, 0, 1 },
405 { "CURVEPOLYGON", CURVEPOLYTYPE, 0, 0 },
406
407 { "MULTICURVEZM", MULTICURVETYPE, 1, 1 },
408 { "MULTICURVEZ", MULTICURVETYPE, 1, 0 },
409 { "MULTICURVEM", MULTICURVETYPE, 0, 1 },
410 { "MULTICURVE", MULTICURVETYPE, 0, 0 },
411
412 { "MULTISURFACEZM", MULTISURFACETYPE, 1, 1 },
413 { "MULTISURFACEZ", MULTISURFACETYPE, 1, 0 },
414 { "MULTISURFACEM", MULTISURFACETYPE, 0, 1 },
415 { "MULTISURFACE", MULTISURFACETYPE, 0, 0 },
416
417 { "MULTILINESTRINGZM", MULTILINETYPE, 1, 1 },
418 { "MULTILINESTRINGZ", MULTILINETYPE, 1, 0 },
419 { "MULTILINESTRINGM", MULTILINETYPE, 0, 1 },
420 { "MULTILINESTRING", MULTILINETYPE, 0, 0 },
421
422 { "MULTIPOLYGONZM", MULTIPOLYGONTYPE, 1, 1 },
423 { "MULTIPOLYGONZ", MULTIPOLYGONTYPE, 1, 0 },
424 { "MULTIPOLYGONM", MULTIPOLYGONTYPE, 0, 1 },
425 { "MULTIPOLYGON", MULTIPOLYGONTYPE, 0, 0 },
426
427 { "MULTIPOINTZM", MULTIPOINTTYPE, 1, 1 },
428 { "MULTIPOINTZ", MULTIPOINTTYPE, 1, 0 },
429 { "MULTIPOINTM", MULTIPOINTTYPE, 0, 1 },
430 { "MULTIPOINT", MULTIPOINTTYPE, 0, 0 },
431
432 { "LINESTRINGZM", LINETYPE, 1, 1 },
433 { "LINESTRINGZ", LINETYPE, 1, 0 },
434 { "LINESTRINGM", LINETYPE, 0, 1 },
435 { "LINESTRING", LINETYPE, 0, 0 },
436
437 { "TRIANGLEZM", TRIANGLETYPE, 1, 1 },
438 { "TRIANGLEZ", TRIANGLETYPE, 1, 0 },
439 { "TRIANGLEM", TRIANGLETYPE, 0, 1 },
440 { "TRIANGLE", TRIANGLETYPE, 0, 0 },
441
442 { "POLYGONZM", POLYGONTYPE, 1, 1 },
443 { "POLYGONZ", POLYGONTYPE, 1, 0 },
444 { "POLYGONM", POLYGONTYPE, 0, 1 },
445 { "POLYGON", POLYGONTYPE, 0, 0 },
446
447 { "POINTZM", POINTTYPE, 1, 1 },
448 { "POINTZ", POINTTYPE, 1, 0 },
449 { "POINTM", POINTTYPE, 0, 1 },
450 { "POINT", POINTTYPE, 0, 0 }
451
452};
453#define GEOMTYPE_STRUCT_ARRAY_LEN (sizeof geomtype_struct_array/sizeof(struct geomtype_struct))
454
455/*
456* We use a very simple upper case mapper here, because the system toupper() function
457* is locale dependent and may have trouble mapping lower case strings to the upper
458* case ones we expect (see, the "Turkisk I", http://www.i18nguy.com/unicode/turkish-i18n.html)
459* We could also count on PgSQL sending us *lower* case inputs, as it seems to do that
460* regardless of the case the user provides for the type arguments.
461*/
462const char dumb_upper_map[128] = "................................................0123456789.......ABCDEFGHIJKLMNOPQRSTUVWXYZ......ABCDEFGHIJKLMNOPQRSTUVWXYZ.....";
463
464static char dumb_toupper(int in)
465{
466 if ( in < 0 || in > 127 )
467 return '.';
468 return dumb_upper_map[in];
469}
470
471lwflags_t lwflags(int hasz, int hasm, int geodetic)
472{
473 lwflags_t flags = 0;
474 if (hasz)
475 FLAGS_SET_Z(flags, 1);
476 if (hasm)
477 FLAGS_SET_M(flags, 1);
478 if (geodetic)
479 FLAGS_SET_GEODETIC(flags, 1);
480 return flags;
481}
482
489int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
490{
491 char *tmpstr;
492 size_t tmpstartpos, tmpendpos;
493 size_t i;
494
495 assert(str);
496 assert(type);
497 assert(z);
498 assert(m);
499
500 /* Initialize. */
501 *type = 0;
502 *z = 0;
503 *m = 0;
504
505 /* Locate any leading/trailing spaces */
506 tmpstartpos = 0;
507 for (i = 0; i < strlen(str); i++)
508 {
509 if (str[i] != ' ')
510 {
511 tmpstartpos = i;
512 break;
513 }
514 }
515
516 tmpendpos = strlen(str) - 1;
517 for (i = strlen(str) - 1; i != 0; i--)
518 {
519 if (str[i] != ' ')
520 {
521 tmpendpos = i;
522 break;
523 }
524 }
525
526 /* Copy and convert to upper case for comparison */
527 tmpstr = lwalloc(tmpendpos - tmpstartpos + 2);
528 for (i = tmpstartpos; i <= tmpendpos; i++)
529 tmpstr[i - tmpstartpos] = dumb_toupper(str[i]);
530
531 /* Add NULL to terminate */
532 tmpstr[i - tmpstartpos] = '\0';
533
534 /* Now check for the type */
535 for (i = 0; i < GEOMTYPE_STRUCT_ARRAY_LEN; i++)
536 {
537 if (!strcmp(tmpstr, geomtype_struct_array[i].typename))
538 {
542
543 lwfree(tmpstr);
544
545 return LW_SUCCESS;
546 }
547
548 }
549
550 lwfree(tmpstr);
551
552 return LW_FAILURE;
553}
554
555
556
557
558
559
#define COLLECTIONTYPE
Definition liblwgeom.h:122
#define COMPOUNDTYPE
Definition liblwgeom.h:124
void(*) typedef void(*) voi lwgeom_set_handlers)(lwallocator allocator, lwreallocator reallocator, lwfreeor freeor, lwreporter errorreporter, lwreporter noticereporter)
Install custom memory management and error handling functions you want your application to use.
void(*) typedef void(* lwdebuglogger)(int level, const char *fmt, va_list ap) __attribute__((format(printf
Definition liblwgeom.h:261
#define LW_FAILURE
Definition liblwgeom.h:110
#define CURVEPOLYTYPE
Definition liblwgeom.h:125
#define MULTILINETYPE
Definition liblwgeom.h:120
void(* lwfreeor)(void *mem)
Definition liblwgeom.h:258
#define SRID_USER_MAXIMUM
Maximum valid SRID value for the user We reserve 1000 values for internal use.
Definition liblwgeom.h:226
#define MULTISURFACETYPE
Definition liblwgeom.h:127
#define LINETYPE
Definition liblwgeom.h:117
void *(* lwallocator)(size_t size)
Global functions for memory/logging handlers.
Definition liblwgeom.h:256
#define LW_SUCCESS
Definition liblwgeom.h:111
uint16_t lwflags_t
Definition liblwgeom.h:313
#define MULTIPOINTTYPE
Definition liblwgeom.h:119
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:116
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition liblwgeom.h:220
void(* lwreporter)(const char *fmt, va_list ap) __attribute__((format(printf
Definition liblwgeom.h:259
#define TINTYPE
Definition liblwgeom.h:130
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:121
#define POLYGONTYPE
Definition liblwgeom.h:118
void *(* lwreallocator)(void *mem, size_t size)
Definition liblwgeom.h:257
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:128
#define CIRCSTRINGTYPE
Definition liblwgeom.h:123
#define MULTICURVETYPE
Definition liblwgeom.h:126
#define TRIANGLETYPE
Definition liblwgeom.h:129
#define FLAGS_SET_GEODETIC(flags, value)
Definition liblwgeom.h:189
#define FLAGS_SET_M(flags, value)
Definition liblwgeom.h:187
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
#define FLAGS_SET_Z(flags, value)
Definition liblwgeom.h:186
#define str(s)
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:88
void * malloc(YYSIZE_T)
void free(void *)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
static char dumb_toupper(int in)
Definition lwutil.c:464
static void default_noticereporter(const char *fmt, va_list ap)
Definition lwutil.c:117
void * lwrealloc(void *mem, size_t size)
Definition lwutil.c:235
lwreporter lwerror_var
Definition lwutil.c:52
static char * lwgeomTypeName[]
Definition lwutil.c:60
void lwgeom_set_debuglogger(lwdebuglogger debuglogger)
Definition lwutil.c:171
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition lwutil.c:177
char * lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
Definition lwutil.c:268
lwallocator lwalloc_var
Definition lwutil.c:44
static void * default_allocator(size_t size)
Definition lwutil.c:89
static void default_errorreporter(const char *fmt, va_list ap)
Definition lwutil.c:142
int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
Calculate type integer and dimensional flags from string input.
Definition lwutil.c:489
void * lwalloc(size_t size)
Definition lwutil.c:227
const char dumb_upper_map[128]
Definition lwutil.c:462
static void * default_reallocator(void *mem, size_t size)
Definition lwutil.c:102
void lwfree(void *mem)
Definition lwutil.c:242
lwdebuglogger lwdebug_var
Definition lwutil.c:56
char * lwstrdup(const char *a)
Definition lwutil.c:248
#define GEOMTYPE_STRUCT_ARRAY_LEN
Definition lwutil.c:453
lwreporter lwnotice_var
Definition lwutil.c:51
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
Definition lwutil.c:471
#define LW_MSG_MAXLEN
Definition lwutil.c:58
void lwdebug(int level, const char *fmt,...)
Write a debug message out.
Definition lwutil.c:203
lwfreeor lwfree_var
Definition lwutil.c:46
static void default_freeor(void *mem)
Definition lwutil.c:96
lwreallocator lwrealloc_var
Definition lwutil.c:45
struct geomtype_struct geomtype_struct_array[]
Definition lwutil.c:370
static void default_debuglogger(int level, const char *fmt, va_list ap)
Definition lwutil.c:126
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition lwutil.c:333