PostGIS  2.3.7dev-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 lwnotice/lwerror handlers
82  *
83  * Since variadic functions cannot pass their parameters directly, we need
84  * wrappers for these functions to convert the arguments into a va_list
85  * structure.
86  */
87 
88 void
89 lwnotice(const char *fmt, ...)
90 {
91  va_list ap;
92 
93  va_start(ap, fmt);
94 
95  /* Call the supplied function */
96  (*lwnotice_var)(fmt, ap);
97 
98  va_end(ap);
99 }
100 
101 void
102 lwerror(const char *fmt, ...)
103 {
104  va_list ap;
105 
106  va_start(ap, fmt);
107 
108  /* Call the supplied function */
109  (*lwerror_var)(fmt, ap);
110 
111  va_end(ap);
112 }
113 
114 void
115 lwdebug(int level, const char *fmt, ...)
116 {
117  va_list ap;
118 
119  va_start(ap, fmt);
120 
121  /* Call the supplied function */
122  (*lwdebug_var)(level, fmt, ap);
123 
124  va_end(ap);
125 }
126 
127 /*
128  * Default allocators
129  *
130  * We include some default allocators that use malloc/free/realloc
131  * along with stdout/stderr since this is the most common use case
132  *
133  */
134 
135 static void *
136 default_allocator(size_t size)
137 {
138  void *mem = malloc(size);
139  return mem;
140 }
141 
142 static void
143 default_freeor(void *mem)
144 {
145  free(mem);
146 }
147 
148 static void *
149 default_reallocator(void *mem, size_t size)
150 {
151  void *ret = realloc(mem, size);
152  return ret;
153 }
154 
155 static void
156 default_noticereporter(const char *fmt, va_list ap)
157 {
158  char msg[LW_MSG_MAXLEN+1];
159  vsnprintf (msg, LW_MSG_MAXLEN, fmt, ap);
160  msg[LW_MSG_MAXLEN]='\0';
161  printf("%s\n", msg);
162 }
163 
164 static void
165 default_debuglogger(int level, const char *fmt, va_list ap)
166 {
167  char msg[LW_MSG_MAXLEN+1];
168  if ( POSTGIS_DEBUG_LEVEL >= level )
169  {
170  /* Space pad the debug output */
171  int i;
172  for ( i = 0; i < level; i++ )
173  msg[i] = ' ';
174  vsnprintf(msg+i, LW_MSG_MAXLEN-i, fmt, ap);
175  msg[LW_MSG_MAXLEN]='\0';
176  printf("%s\n", msg);
177  }
178 }
179 
180 static void
181 default_errorreporter(const char *fmt, va_list ap)
182 {
183  char msg[LW_MSG_MAXLEN+1];
184  vsnprintf (msg, LW_MSG_MAXLEN, fmt, ap);
185  msg[LW_MSG_MAXLEN]='\0';
186  fprintf(stderr, "%s\n", msg);
187  exit(1);
188 }
189 
196 void
198  lwfreeor freeor, lwreporter errorreporter,
199  lwreporter noticereporter) {
200 
201  if ( allocator ) lwalloc_var = allocator;
202  if ( reallocator ) lwrealloc_var = reallocator;
203  if ( freeor ) lwfree_var = freeor;
204 
205  if ( errorreporter ) lwerror_var = errorreporter;
206  if ( noticereporter ) lwnotice_var = noticereporter;
207 }
208 
209 void
211 
212  if ( debuglogger ) lwdebug_var = debuglogger;
213 }
214 
215 const char*
216 lwtype_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 
226 void *
227 lwalloc(size_t size)
228 {
229  void *mem = lwalloc_var(size);
230  LWDEBUGF(5, "lwalloc: %d@%p", size, mem);
231  return mem;
232 }
233 
234 void *
235 lwrealloc(void *mem, size_t size)
236 {
237  LWDEBUGF(5, "lwrealloc: %d@%p", size, mem);
238  return lwrealloc_var(mem, size);
239 }
240 
241 void
242 lwfree(void *mem)
243 {
244  lwfree_var(mem);
245 }
246 
247 /*
248  * Removes trailing zeros and dot for a %f formatted number.
249  * Modifies input.
250  */
251 void
253 {
254  char *ptr, *totrim=NULL;
255  int len;
256  int i;
257 
258  LWDEBUGF(3, "input: %s", str);
259 
260  ptr = strchr(str, '.');
261  if ( ! ptr ) return; /* no dot, no decimal digits */
262 
263  LWDEBUGF(3, "ptr: %s", ptr);
264 
265  len = strlen(ptr);
266  for (i=len-1; i; i--)
267  {
268  if ( ptr[i] != '0' ) break;
269  totrim=&ptr[i];
270  }
271  if ( totrim )
272  {
273  if ( ptr == totrim-1 ) *ptr = '\0';
274  else *totrim = '\0';
275  }
276 
277  LWDEBUGF(3, "output: %s", str);
278 }
279 
280 /*
281  * Returns a new string which contains a maximum of maxlength characters starting
282  * from startpos and finishing at endpos (0-based indexing). If the string is
283  * truncated then the first or last characters are replaced by "..." as
284  * appropriate.
285  *
286  * The caller should specify start or end truncation by setting the truncdirection
287  * parameter as follows:
288  * 0 - start truncation (i.e. characters are removed from the beginning)
289  * 1 - end trunctation (i.e. characters are removed from the end)
290  */
291 
292 char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
293 {
294  char *output;
295  char *outstart;
296 
297  /* Allocate space for new string */
298  output = lwalloc(maxlength + 4);
299  output[0] = '\0';
300 
301  /* Start truncation */
302  if (truncdirection == 0)
303  {
304  /* Calculate the start position */
305  if (endpos - startpos < maxlength)
306  {
307  outstart = str + startpos;
308  strncat(output, outstart, endpos - startpos + 1);
309  }
310  else
311  {
312  if (maxlength >= 3)
313  {
314  /* Add "..." prefix */
315  outstart = str + endpos + 1 - maxlength + 3;
316  strncat(output, "...", 3);
317  strncat(output, outstart, maxlength - 3);
318  }
319  else
320  {
321  /* maxlength is too small; just output "..." */
322  strncat(output, "...", 3);
323  }
324  }
325  }
326 
327  /* End truncation */
328  if (truncdirection == 1)
329  {
330  /* Calculate the end position */
331  if (endpos - startpos < maxlength)
332  {
333  outstart = str + startpos;
334  strncat(output, outstart, endpos - startpos + 1);
335  }
336  else
337  {
338  if (maxlength >= 3)
339  {
340  /* Add "..." suffix */
341  outstart = str + startpos;
342  strncat(output, outstart, maxlength - 3);
343  strncat(output, "...", 3);
344  }
345  else
346  {
347  /* maxlength is too small; just output "..." */
348  strncat(output, "...", 3);
349  }
350  }
351  }
352 
353  return output;
354 }
355 
356 
357 char
359 {
360  static int endian_check_int = 1; /* dont modify this!!! */
361 
362  return *((char *) &endian_check_int); /* 0 = big endian | xdr,
363  * 1 = little endian | ndr
364  */
365 }
366 
367 
368 void
369 error_if_srid_mismatch(int srid1, int srid2)
370 {
371  if ( srid1 != srid2 )
372  {
373  lwerror("Operation on mixed SRID geometries");
374  }
375 }
376 
377 int
378 clamp_srid(int srid)
379 {
380  int newsrid = srid;
381 
382  if ( newsrid <= 0 ) {
383  if ( newsrid != SRID_UNKNOWN ) {
384  newsrid = SRID_UNKNOWN;
385  lwnotice("SRID value %d converted to the officially unknown SRID value %d", srid, newsrid);
386  }
387  } else if ( srid > SRID_MAXIMUM ) {
388  newsrid = SRID_USER_MAXIMUM + 1 +
389  /* -1 is to reduce likelyhood of clashes */
390  /* NOTE: must match implementation in postgis_restore.pl */
391  ( srid % ( SRID_MAXIMUM - SRID_USER_MAXIMUM - 1 ) );
392  lwnotice("SRID value %d > SRID_MAXIMUM converted to %d", srid, newsrid);
393  }
394 
395  return newsrid;
396 }
397 
void lwdebug(int level, const char *fmt,...)
Write a debug message out.
Definition: lwutil.c:115
static void * default_allocator(size_t size)
Definition: lwutil.c:136
char getMachineEndian(void)
Definition: lwutil.c:358
static void default_debuglogger(int level, const char *fmt, va_list ap)
Definition: lwutil.c:165
tuple fmt
Definition: pixval.py:92
static void default_freeor(void *mem)
Definition: lwutil.c:143
void lwgeom_set_debuglogger(lwdebuglogger debuglogger)
Definition: lwutil.c:210
void lwfree(void *mem)
Definition: lwutil.c:242
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:378
lwallocator lwalloc_var
Definition: lwutil.c:44
void(* lwfreeor)(void *mem)
Definition: liblwgeom.h:216
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:184
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:235
void *(* lwallocator)(size_t size)
Global functions for memory/logging handlers.
Definition: liblwgeom.h:214
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:102
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:89
lwreporter lwerror_var
Definition: lwutil.c:52
void(* lwreporter)(const char *fmt, va_list ap) __attribute__((format(printf
Definition: liblwgeom.h:217
void *(* lwreallocator)(void *mem, size_t size)
Definition: liblwgeom.h:215
lwreporter lwnotice_var
Definition: lwutil.c:51
static void default_errorreporter(const char *fmt, va_list ap)
Definition: lwutil.c:181
static void default_noticereporter(const char *fmt, va_list ap)
Definition: lwutil.c:156
void(*) typedef void(* lwdebuglogger)(int level, const char *fmt, va_list ap) __attribute__((format(printf
Definition: liblwgeom.h:219
static void * default_reallocator(void *mem, size_t size)
Definition: lwutil.c:149
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:178
void trim_trailing_zeros(char *str)
Definition: lwutil.c:252
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
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:197
lwdebuglogger lwdebug_var
Definition: lwutil.c:56
char * lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
Definition: lwutil.c:292
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
void * lwalloc(size_t size)
Definition: lwutil.c:227
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:369
#define LW_MSG_MAXLEN
Definition: lwutil.c:58
lwfreeor lwfree_var
Definition: lwutil.c:46