PostGIS 3.7.0dev-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) __attribute__ ((format (printf, 1, 0)));
50static void default_errorreporter(const char *fmt, va_list ap) __attribute__ ((format (printf, 1, 0)));
53
54/* Default logger */
55static void default_debuglogger(int level, const char *fmt, va_list ap) __attribute__ ((format (printf, 2, 0)));
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 return mem;
231}
232
233void *
234lwalloc0(size_t size)
235{
236 void *mem = lwalloc_var(size);
237 memset(mem, 0, size);
238 return mem;
239}
240
241void *
242lwrealloc(void *mem, size_t size)
243{
244 return lwrealloc_var(mem, size);
245}
246
247void
248lwfree(void *mem)
249{
250 lwfree_var(mem);
251}
252
253char *
254lwstrdup(const char* a)
255{
256 size_t l = strlen(a)+1;
257 char *b = lwalloc(l);
258 strncpy(b, a, l);
259 return b;
260}
261
262/*
263 * Returns a new string which contains a maximum of maxlength characters starting
264 * from startpos and finishing at endpos (0-based indexing). If the string is
265 * truncated then the first or last characters are replaced by "..." as
266 * appropriate.
267 *
268 * The caller should specify start or end truncation by setting the truncdirection
269 * parameter as follows:
270 * 0 - start truncation (i.e. characters are removed from the beginning)
271 * 1 - end truncation (i.e. characters are removed from the end)
272 */
273
274char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
275{
276 char *output;
277 char *outstart;
278
279 /* Allocate space for new string */
280 output = lwalloc(maxlength + 4);
281 output[0] = '\0';
282
283 /* Start truncation */
284 if (truncdirection == 0)
285 {
286 /* Calculate the start position */
287 if (endpos - startpos < maxlength)
288 {
289 outstart = str + startpos;
290 strncat(output, outstart, endpos - startpos + 1);
291 }
292 else
293 {
294 if (maxlength >= 3)
295 {
296 /* Add "..." prefix */
297 outstart = str + endpos + 1 - maxlength + 3;
298 strncat(output, "...", 4);
299 strncat(output, outstart, maxlength - 3);
300 }
301 else
302 {
303 /* maxlength is too small; just output "..." */
304 strncat(output, "...", 4);
305 }
306 }
307 }
308
309 /* End truncation */
310 if (truncdirection == 1)
311 {
312 /* Calculate the end position */
313 if (endpos - startpos < maxlength)
314 {
315 outstart = str + startpos;
316 strncat(output, outstart, endpos - startpos + 1);
317 }
318 else
319 {
320 if (maxlength >= 3)
321 {
322 /* Add "..." suffix */
323 outstart = str + startpos;
324 strncat(output, outstart, maxlength - 3);
325 strncat(output, "...", 4);
326 }
327 else
328 {
329 /* maxlength is too small; just output "..." */
330 strncat(output, "...", 4);
331 }
332 }
333 }
334
335 return output;
336}
337
338int32_t
339clamp_srid(int32_t srid)
340{
341 int newsrid = srid;
342
343 if ( newsrid <= 0 ) {
344 if ( newsrid != SRID_UNKNOWN ) {
345 newsrid = SRID_UNKNOWN;
346 lwnotice("SRID value %d converted to the officially unknown SRID value %d", srid, newsrid);
347 }
348 } else if ( srid > SRID_MAXIMUM ) {
349 newsrid = SRID_USER_MAXIMUM + 1 +
350 /* -1 is to reduce likelihood of clashes */
351 /* NOTE: must match implementation in postgis_restore.pl */
352 ( srid % ( SRID_MAXIMUM - SRID_USER_MAXIMUM - 1 ) );
353 lwnotice("SRID value %d > SRID_MAXIMUM converted to %d", srid, newsrid);
354 }
355
356 return newsrid;
357}
358
359
360
361
362/* Structure for the type array */
364{
365 char *typename;
366 int type;
367 int z;
368 int m;
369};
370
371/* Type array. Note that the order of this array is important in
372 that any typename in the list must *NOT* occur within an entry
373 before it. Otherwise if we search for "POINT" at the top of the
374 list we would also match MULTIPOINT, for example. */
375
377{
378 { "GEOMETRYCOLLECTIONZM", COLLECTIONTYPE, 1, 1 },
379 { "GEOMETRYCOLLECTIONZ", COLLECTIONTYPE, 1, 0 },
380 { "GEOMETRYCOLLECTIONM", COLLECTIONTYPE, 0, 1 },
381 { "GEOMETRYCOLLECTION", COLLECTIONTYPE, 0, 0 },
382
383 { "GEOMETRYZM", 0, 1, 1 },
384 { "GEOMETRYZ", 0, 1, 0 },
385 { "GEOMETRYM", 0, 0, 1 },
386 { "GEOMETRY", 0, 0, 0 },
387
388 { "POLYHEDRALSURFACEZM", POLYHEDRALSURFACETYPE, 1, 1 },
389 { "POLYHEDRALSURFACEZ", POLYHEDRALSURFACETYPE, 1, 0 },
390 { "POLYHEDRALSURFACEM", POLYHEDRALSURFACETYPE, 0, 1 },
391 { "POLYHEDRALSURFACE", POLYHEDRALSURFACETYPE, 0, 0 },
392
393 { "TINZM", TINTYPE, 1, 1 },
394 { "TINZ", TINTYPE, 1, 0 },
395 { "TINM", TINTYPE, 0, 1 },
396 { "TIN", TINTYPE, 0, 0 },
397
398 { "CIRCULARSTRINGZM", CIRCSTRINGTYPE, 1, 1 },
399 { "CIRCULARSTRINGZ", CIRCSTRINGTYPE, 1, 0 },
400 { "CIRCULARSTRINGM", CIRCSTRINGTYPE, 0, 1 },
401 { "CIRCULARSTRING", CIRCSTRINGTYPE, 0, 0 },
402
403 { "COMPOUNDCURVEZM", COMPOUNDTYPE, 1, 1 },
404 { "COMPOUNDCURVEZ", COMPOUNDTYPE, 1, 0 },
405 { "COMPOUNDCURVEM", COMPOUNDTYPE, 0, 1 },
406 { "COMPOUNDCURVE", COMPOUNDTYPE, 0, 0 },
407
408 { "CURVEPOLYGONZM", CURVEPOLYTYPE, 1, 1 },
409 { "CURVEPOLYGONZ", CURVEPOLYTYPE, 1, 0 },
410 { "CURVEPOLYGONM", CURVEPOLYTYPE, 0, 1 },
411 { "CURVEPOLYGON", CURVEPOLYTYPE, 0, 0 },
412
413 { "MULTICURVEZM", MULTICURVETYPE, 1, 1 },
414 { "MULTICURVEZ", MULTICURVETYPE, 1, 0 },
415 { "MULTICURVEM", MULTICURVETYPE, 0, 1 },
416 { "MULTICURVE", MULTICURVETYPE, 0, 0 },
417
418 { "MULTISURFACEZM", MULTISURFACETYPE, 1, 1 },
419 { "MULTISURFACEZ", MULTISURFACETYPE, 1, 0 },
420 { "MULTISURFACEM", MULTISURFACETYPE, 0, 1 },
421 { "MULTISURFACE", MULTISURFACETYPE, 0, 0 },
422
423 { "MULTILINESTRINGZM", MULTILINETYPE, 1, 1 },
424 { "MULTILINESTRINGZ", MULTILINETYPE, 1, 0 },
425 { "MULTILINESTRINGM", MULTILINETYPE, 0, 1 },
426 { "MULTILINESTRING", MULTILINETYPE, 0, 0 },
427
428 { "MULTIPOLYGONZM", MULTIPOLYGONTYPE, 1, 1 },
429 { "MULTIPOLYGONZ", MULTIPOLYGONTYPE, 1, 0 },
430 { "MULTIPOLYGONM", MULTIPOLYGONTYPE, 0, 1 },
431 { "MULTIPOLYGON", MULTIPOLYGONTYPE, 0, 0 },
432
433 { "MULTIPOINTZM", MULTIPOINTTYPE, 1, 1 },
434 { "MULTIPOINTZ", MULTIPOINTTYPE, 1, 0 },
435 { "MULTIPOINTM", MULTIPOINTTYPE, 0, 1 },
436 { "MULTIPOINT", MULTIPOINTTYPE, 0, 0 },
437
438 { "LINESTRINGZM", LINETYPE, 1, 1 },
439 { "LINESTRINGZ", LINETYPE, 1, 0 },
440 { "LINESTRINGM", LINETYPE, 0, 1 },
441 { "LINESTRING", LINETYPE, 0, 0 },
442
443 { "TRIANGLEZM", TRIANGLETYPE, 1, 1 },
444 { "TRIANGLEZ", TRIANGLETYPE, 1, 0 },
445 { "TRIANGLEM", TRIANGLETYPE, 0, 1 },
446 { "TRIANGLE", TRIANGLETYPE, 0, 0 },
447
448 { "POLYGONZM", POLYGONTYPE, 1, 1 },
449 { "POLYGONZ", POLYGONTYPE, 1, 0 },
450 { "POLYGONM", POLYGONTYPE, 0, 1 },
451 { "POLYGON", POLYGONTYPE, 0, 0 },
452
453 { "POINTZM", POINTTYPE, 1, 1 },
454 { "POINTZ", POINTTYPE, 1, 0 },
455 { "POINTM", POINTTYPE, 0, 1 },
456 { "POINT", POINTTYPE, 0, 0 }
457
458};
459#define GEOMTYPE_STRUCT_ARRAY_LEN (sizeof geomtype_struct_array/sizeof(struct geomtype_struct))
460
461/*
462* We use a very simple upper case mapper here, because the system toupper() function
463* is locale dependent and may have trouble mapping lower case strings to the upper
464* case ones we expect (see, the "Turkisk I", http://www.i18nguy.com/unicode/turkish-i18n.html)
465* We could also count on PgSQL sending us *lower* case inputs, as it seems to do that
466* regardless of the case the user provides for the type arguments.
467*/
468const char dumb_upper_map[128] = "................................................0123456789.......ABCDEFGHIJKLMNOPQRSTUVWXYZ......ABCDEFGHIJKLMNOPQRSTUVWXYZ.....";
469
470static char dumb_toupper(int in)
471{
472 if ( in < 0 || in > 127 )
473 return '.';
474 return dumb_upper_map[in];
475}
476
477lwflags_t lwflags(int hasz, int hasm, int geodetic)
478{
479 lwflags_t flags = 0;
480 if (hasz)
481 FLAGS_SET_Z(flags, 1);
482 if (hasm)
483 FLAGS_SET_M(flags, 1);
484 if (geodetic)
485 FLAGS_SET_GEODETIC(flags, 1);
486 return flags;
487}
488
495int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
496{
497 char *tmpstr;
498 size_t tmpstartpos, tmpendpos;
499 size_t i;
500
501 assert(str);
502 assert(type);
503 assert(z);
504 assert(m);
505
506 /* Initialize. */
507 *type = 0;
508 *z = 0;
509 *m = 0;
510
511 /* Locate any leading/trailing spaces */
512 tmpstartpos = 0;
513 for (i = 0; i < strlen(str); i++)
514 {
515 if (str[i] != ' ')
516 {
517 tmpstartpos = i;
518 break;
519 }
520 }
521
522 tmpendpos = strlen(str) - 1;
523 for (i = strlen(str) - 1; i != 0; i--)
524 {
525 if (str[i] != ' ')
526 {
527 tmpendpos = i;
528 break;
529 }
530 }
531
532 /* Copy and convert to upper case for comparison */
533 tmpstr = lwalloc(tmpendpos - tmpstartpos + 2);
534 for (i = tmpstartpos; i <= tmpendpos; i++)
535 tmpstr[i - tmpstartpos] = dumb_toupper(str[i]);
536
537 /* Add NULL to terminate */
538 tmpstr[i - tmpstartpos] = '\0';
539
540 /* Now check for the type */
541 for (i = 0; i < GEOMTYPE_STRUCT_ARRAY_LEN; i++)
542 {
543 if (!strcmp(tmpstr, geomtype_struct_array[i].typename))
544 {
548
549 lwfree(tmpstr);
550
551 return LW_SUCCESS;
552 }
553
554 }
555
556 lwfree(tmpstr);
557
558 return LW_FAILURE;
559}
560
561
562
563
564
565
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define COMPOUNDTYPE
Definition liblwgeom.h:110
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:247
#define LW_FAILURE
Definition liblwgeom.h:96
#define CURVEPOLYTYPE
Definition liblwgeom.h:111
#define MULTILINETYPE
Definition liblwgeom.h:106
void(* lwfreeor)(void *mem)
Definition liblwgeom.h:244
#define SRID_USER_MAXIMUM
Maximum valid SRID value for the user We reserve 1000 values for internal use.
Definition liblwgeom.h:212
#define MULTISURFACETYPE
Definition liblwgeom.h:113
#define LINETYPE
Definition liblwgeom.h:103
void *(* lwallocator)(size_t size)
Global functions for memory/logging handlers.
Definition liblwgeom.h:242
#define LW_SUCCESS
Definition liblwgeom.h:97
uint16_t lwflags_t
Definition liblwgeom.h:299
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition liblwgeom.h:206
void(* lwreporter)(const char *fmt, va_list ap) __attribute__((format(printf
Definition liblwgeom.h:245
#define TINTYPE
Definition liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
#define POLYGONTYPE
Definition liblwgeom.h:104
void *(* lwreallocator)(void *mem, size_t size)
Definition liblwgeom.h:243
#define __attribute__(x)
Definition liblwgeom.h:228
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:114
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
#define MULTICURVETYPE
Definition liblwgeom.h:112
#define TRIANGLETYPE
Definition liblwgeom.h:115
#define FLAGS_SET_GEODETIC(flags, value)
Definition liblwgeom.h:175
#define FLAGS_SET_M(flags, value)
Definition liblwgeom.h:173
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
#define FLAGS_SET_Z(flags, value)
Definition liblwgeom.h:172
#define str(s)
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 void static void lwreporter lwnotice_var
Definition lwutil.c:51
static char dumb_toupper(int in)
Definition lwutil.c:470
void * lwrealloc(void *mem, size_t size)
Definition lwutil.c:242
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,...)
Definition lwutil.c:190
void lwnotice(const char *fmt,...)
Definition lwutil.c:177
void * lwalloc0(size_t size)
Definition lwutil.c:234
char * lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
Definition lwutil.c:274
lwallocator lwalloc_var
Definition lwutil.c:44
static void * default_allocator(size_t size)
Definition lwutil.c:89
static void lwdebuglogger lwdebug_var
Definition lwutil.c:56
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:495
void * lwalloc(size_t size)
Definition lwutil.c:227
const char dumb_upper_map[128]
Definition lwutil.c:468
static void * default_reallocator(void *mem, size_t size)
Definition lwutil.c:102
void lwfree(void *mem)
Definition lwutil.c:248
static void default_debuglogger(int level, const char *fmt, va_list ap) __attribute__((format(printf
Definition lwutil.c:126
char * lwstrdup(const char *a)
Definition lwutil.c:254
#define GEOMTYPE_STRUCT_ARRAY_LEN
Definition lwutil.c:459
static void static void default_errorreporter(const char *fmt, va_list ap) __attribute__((format(printf
Definition lwutil.c:142
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
Definition lwutil.c:477
#define LW_MSG_MAXLEN
Definition lwutil.c:58
void lwdebug(int level, const char *fmt,...)
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:376
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:339
static void default_noticereporter(const char *fmt, va_list ap) __attribute__((format(printf
Definition lwutil.c:117