PostGIS  2.5.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 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  * Returns a new string which contains a maximum of maxlength characters starting
251  * from startpos and finishing at endpos (0-based indexing). If the string is
252  * truncated then the first or last characters are replaced by "..." as
253  * appropriate.
254  *
255  * The caller should specify start or end truncation by setting the truncdirection
256  * parameter as follows:
257  * 0 - start truncation (i.e. characters are removed from the beginning)
258  * 1 - end truncation (i.e. characters are removed from the end)
259  */
260 
261 char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
262 {
263  char *output;
264  char *outstart;
265 
266  /* Allocate space for new string */
267  output = lwalloc(maxlength + 4);
268  output[0] = '\0';
269 
270  /* Start truncation */
271  if (truncdirection == 0)
272  {
273  /* Calculate the start position */
274  if (endpos - startpos < maxlength)
275  {
276  outstart = str + startpos;
277  strncat(output, outstart, endpos - startpos + 1);
278  }
279  else
280  {
281  if (maxlength >= 3)
282  {
283  /* Add "..." prefix */
284  outstart = str + endpos + 1 - maxlength + 3;
285  strncat(output, "...", 4);
286  strncat(output, outstart, maxlength - 3);
287  }
288  else
289  {
290  /* maxlength is too small; just output "..." */
291  strncat(output, "...", 4);
292  }
293  }
294  }
295 
296  /* End truncation */
297  if (truncdirection == 1)
298  {
299  /* Calculate the end position */
300  if (endpos - startpos < maxlength)
301  {
302  outstart = str + startpos;
303  strncat(output, outstart, endpos - startpos + 1);
304  }
305  else
306  {
307  if (maxlength >= 3)
308  {
309  /* Add "..." suffix */
310  outstart = str + startpos;
311  strncat(output, outstart, maxlength - 3);
312  strncat(output, "...", 4);
313  }
314  else
315  {
316  /* maxlength is too small; just output "..." */
317  strncat(output, "...", 4);
318  }
319  }
320  }
321 
322  return output;
323 }
324 
325 
326 char
328 {
329  static int endian_check_int = 1; /* don't modify this!!! */
330 
331  return *((char *) &endian_check_int); /* 0 = big endian | xdr,
332  * 1 = little endian | ndr
333  */
334 }
335 
336 
337 void
338 error_if_srid_mismatch(int srid1, int srid2)
339 {
340  if ( srid1 != srid2 )
341  {
342  lwerror("Operation on mixed SRID geometries");
343  }
344 }
345 
346 int
347 clamp_srid(int srid)
348 {
349  int newsrid = srid;
350 
351  if ( newsrid <= 0 ) {
352  if ( newsrid != SRID_UNKNOWN ) {
353  newsrid = SRID_UNKNOWN;
354  lwnotice("SRID value %d converted to the officially unknown SRID value %d", srid, newsrid);
355  }
356  } else if ( srid > SRID_MAXIMUM ) {
357  newsrid = SRID_USER_MAXIMUM + 1 +
358  /* -1 is to reduce likelyhood of clashes */
359  /* NOTE: must match implementation in postgis_restore.pl */
360  ( srid % ( SRID_MAXIMUM - SRID_USER_MAXIMUM - 1 ) );
361  lwnotice("SRID value %d > SRID_MAXIMUM converted to %d", srid, newsrid);
362  }
363 
364  return newsrid;
365 }
366 
void(*) typedef void(* lwdebuglogger)(int level, const char *fmt, va_list ap) __attribute__((format(printf
Definition: liblwgeom.h:223
void(* lwfreeor)(void *mem)
Definition: liblwgeom.h:220
#define SRID_USER_MAXIMUM
Maximum valid SRID value for the user We reserve 1000 values for internal use.
Definition: liblwgeom.h:185
#define SRID_MAXIMUM
Maximum allowed SRID value in serialized geometry.
Definition: liblwgeom.h:179
void(* lwreporter)(const char *fmt, va_list ap) __attribute__((format(printf
Definition: liblwgeom.h:221
void *(* lwreallocator)(void *mem, size_t size)
Definition: liblwgeom.h:219
void *(* lwallocator)(size_t size)
Global functions for memory/logging handlers.
Definition: liblwgeom.h:218
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void * malloc(YYSIZE_T)
void free(void *)
static void default_noticereporter(const char *fmt, va_list ap)
Definition: lwutil.c:117
lwreporter lwerror_var
Definition: lwutil.c:52
static char * lwgeomTypeName[]
Definition: lwutil.c:60
char getMachineEndian(void)
Definition: lwutil.c:327
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:261
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
static void * default_reallocator(void *mem, size_t size)
Definition: lwutil.c:102
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:237
void lwfree(void *mem)
Definition: lwutil.c:244
lwdebuglogger lwdebug_var
Definition: lwutil.c:56
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:347
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
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
void * lwalloc(size_t size)
Definition: lwutil.c:229
lwreporter lwnotice_var
Definition: lwutil.c:51
void error_if_srid_mismatch(int srid1, int srid2)
Definition: lwutil.c:338
#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
static void default_debuglogger(int level, const char *fmt, va_list ap)
Definition: lwutil.c:126
type
Definition: ovdump.py:41
def fmt
Definition: pixval.py:92
unsigned char uint8_t
Definition: uthash.h:79