PostGIS  2.4.9dev-r@@SVN_REVISION@@
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 */
41 static void * default_allocator(size_t size);
42 static void default_freeor(void *mem);
43 static void * default_reallocator(void *mem, size_t size);
47 
48 /* Default reporters */
49 static void default_noticereporter(const char *fmt, va_list ap);
50 static void default_errorreporter(const char *fmt, va_list ap);
53 
54 /* Default logger */
55 static void default_debuglogger(int level, const char *fmt, va_list ap);
57 
58 #define LW_MSG_MAXLEN 256
59 
60 static 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 
88 static void *
89 default_allocator(size_t size)
90 {
91  void *mem = malloc(size);
92  return mem;
93 }
94 
95 static void
96 default_freeor(void *mem)
97 {
98  free(mem);
99 }
100 
101 static void *
102 default_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 
116 static void
117 default_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 
125 static void
126 default_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 
141 static void
142 default_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 
157 void
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 
170 void
172 
173  if ( debuglogger ) lwdebug_var = debuglogger;
174 }
175 
176 void
177 lwnotice(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 
189 void
190 lwerror(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 
202 void
203 lwdebug(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 
215 
216 
217 const char*
219 {
220  if ( type > 15 )
221  {
222  /* assert(0); */
223  return "Invalid type";
224  }
225  return lwgeomTypeName[(int ) type];
226 }
227 
228 void *
229 lwalloc(size_t size)
230 {
231  void *mem = lwalloc_var(size);
232  LWDEBUGF(5, "lwalloc: %d@%p", size, mem);
233  return mem;
234 }
235 
236 void *
237 lwrealloc(void *mem, size_t size)
238 {
239  LWDEBUGF(5, "lwrealloc: %d@%p", size, mem);
240  return lwrealloc_var(mem, size);
241 }
242 
243 void
244 lwfree(void *mem)
245 {
246  lwfree_var(mem);
247 }
248 
249 /*
250  * Removes trailing zeros and dot for a %f formatted number.
251  * Modifies input.
252  */
253 void
255 {
256  char *ptr, *totrim=NULL;
257  int len;
258  int i;
259 
260  LWDEBUGF(3, "input: %s", str);
261 
262  ptr = strchr(str, '.');
263  if ( ! ptr ) return; /* no dot, no decimal digits */
264 
265  LWDEBUGF(3, "ptr: %s", ptr);
266 
267  len = strlen(ptr);
268  for (i=len-1; i; i--)
269  {
270  if ( ptr[i] != '0' ) break;
271  totrim=&ptr[i];
272  }
273  if ( totrim )
274  {
275  if ( ptr == totrim-1 ) *ptr = '\0';
276  else *totrim = '\0';
277  }
278 
279  LWDEBUGF(3, "output: %s", str);
280 }
281 
282 /*
283  * Returns a new string which contains a maximum of maxlength characters starting
284  * from startpos and finishing at endpos (0-based indexing). If the string is
285  * truncated then the first or last characters are replaced by "..." as
286  * appropriate.
287  *
288  * The caller should specify start or end truncation by setting the truncdirection
289  * parameter as follows:
290  * 0 - start truncation (i.e. characters are removed from the beginning)
291  * 1 - end trunctation (i.e. characters are removed from the end)
292  */
293 
294 char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
295 {
296  char *output;
297  char *outstart;
298 
299  /* Allocate space for new string */
300  output = lwalloc(maxlength + 4);
301  output[0] = '\0';
302 
303  /* Start truncation */
304  if (truncdirection == 0)
305  {
306  /* Calculate the start 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 "..." prefix */
317  outstart = str + endpos + 1 - maxlength + 3;
318  strncat(output, "...", 3);
319  strncat(output, outstart, maxlength - 3);
320  }
321  else
322  {
323  /* maxlength is too small; just output "..." */
324  strncat(output, "...", 3);
325  }
326  }
327  }
328 
329  /* End truncation */
330  if (truncdirection == 1)
331  {
332  /* Calculate the end position */
333  if (endpos - startpos < maxlength)
334  {
335  outstart = str + startpos;
336  strncat(output, outstart, endpos - startpos + 1);
337  }
338  else
339  {
340  if (maxlength >= 3)
341  {
342  /* Add "..." suffix */
343  outstart = str + startpos;
344  strncat(output, outstart, maxlength - 3);
345  strncat(output, "...", 3);
346  }
347  else
348  {
349  /* maxlength is too small; just output "..." */
350  strncat(output, "...", 3);
351  }
352  }
353  }
354 
355  return output;
356 }
357 
358 
359 char
361 {
362  static int endian_check_int = 1; /* dont modify this!!! */
363 
364  return *((char *) &endian_check_int); /* 0 = big endian | xdr,
365  * 1 = little endian | ndr
366  */
367 }
368 
369 
370 void
371 error_if_srid_mismatch(int srid1, int srid2)
372 {
373  if ( srid1 != srid2 )
374  {
375  lwerror("Operation on mixed SRID geometries");
376  }
377 }
378 
379 int
380 clamp_srid(int srid)
381 {
382  int newsrid = srid;
383 
384  if ( newsrid <= 0 ) {
385  if ( newsrid != SRID_UNKNOWN ) {
386  newsrid = SRID_UNKNOWN;
387  lwnotice("SRID value %d converted to the officially unknown SRID value %d", srid, newsrid);
388  }
389  } else if ( srid > SRID_MAXIMUM ) {
390  newsrid = SRID_USER_MAXIMUM + 1 +
391  /* -1 is to reduce likelyhood of clashes */
392  /* NOTE: must match implementation in postgis_restore.pl */
393  ( srid % ( SRID_MAXIMUM - SRID_USER_MAXIMUM - 1 ) );
394  lwnotice("SRID value %d > SRID_MAXIMUM converted to %d", srid, newsrid);
395  }
396 
397  return newsrid;
398 }
399 
void lwdebug(int level, const char *fmt,...)
Write a debug message out.
Definition: lwutil.c:203
static void * default_allocator(size_t size)
Definition: lwutil.c:89
char getMachineEndian(void)
Definition: lwutil.c:360
static void default_debuglogger(int level, const char *fmt, va_list ap)
Definition: lwutil.c:126
def fmt
Definition: pixval.py:92
static void default_freeor(void *mem)
Definition: lwutil.c:96
void lwgeom_set_debuglogger(lwdebuglogger debuglogger)
Definition: lwutil.c:171
void lwfree(void *mem)
Definition: lwutil.c:244
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:380
lwallocator lwalloc_var
Definition: lwutil.c:44
void(* lwfreeor)(void *mem)
Definition: liblwgeom.h:217
static char * lwgeomTypeName[]
Definition: lwutil.c:60
#define SRID_USER_MAXIMUM
Maximum valid SRID value for the user We reserve 1000 values for internal use.
Definition: liblwgeom.h:185
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:237
void *(* lwallocator)(size_t size)
Global functions for memory/logging handlers.
Definition: liblwgeom.h:215
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
lwreporter lwerror_var
Definition: lwutil.c:52
void(* lwreporter)(const char *fmt, va_list ap) __attribute__((format(printf
Definition: liblwgeom.h:218
void *(* lwreallocator)(void *mem, size_t size)
Definition: liblwgeom.h:216
lwreporter lwnotice_var
Definition: lwutil.c:51
static void default_errorreporter(const char *fmt, va_list ap)
Definition: lwutil.c:142
static void default_noticereporter(const char *fmt, va_list ap)
Definition: lwutil.c:117
void(*) typedef void(* lwdebuglogger)(int level, const char *fmt, va_list ap) __attribute__((format(printf
Definition: liblwgeom.h:220
static void * default_reallocator(void *mem, size_t size)
Definition: lwutil.c:102
type
Definition: ovdump.py:41
lwreallocator lwrealloc_var
Definition: lwutil.c:45
void free(void *)
void * malloc(YYSIZE_T)
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition: liblwgeom.h:179
void trim_trailing_zeros(char *str)
Definition: lwutil.c:254
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
unsigned char uint8_t
Definition: uthash.h:79
void lwgeom_set_handlers(lwallocator allocator, lwreallocator reallocator, lwfreeor freeor, lwreporter errorreporter, lwreporter noticereporter)
This function is called by programs which want to set up custom handling for memory management and er...
Definition: lwutil.c:158
lwdebuglogger lwdebug_var
Definition: lwutil.c:56
char * lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
Definition: lwutil.c:294
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
void * lwalloc(size_t size)
Definition: lwutil.c:229
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:371
#define LW_MSG_MAXLEN
Definition: lwutil.c:58
lwfreeor lwfree_var
Definition: lwutil.c:46