2004-09-30 08:18:06 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
2008-06-29 19:11:48 +00:00
|
|
|
#include <string.h>
|
2004-09-30 08:18:06 +00:00
|
|
|
|
|
|
|
/* Global variables */
|
2008-05-14 17:10:19 +00:00
|
|
|
#include "../postgis_config.h"
|
2010-11-01 01:28:12 +00:00
|
|
|
#include "liblwgeom_internal.h"
|
2011-09-28 10:05:36 +00:00
|
|
|
#include "lwgeom_log.h"
|
2004-10-07 10:03:23 +00:00
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
/* Default allocators */
|
|
|
|
static void * default_allocator(size_t size);
|
|
|
|
static void default_freeor(void *mem);
|
|
|
|
static void * default_reallocator(void *mem, size_t size);
|
|
|
|
lwallocator lwalloc_var = default_allocator;
|
|
|
|
lwreallocator lwrealloc_var = default_reallocator;
|
|
|
|
lwfreeor lwfree_var = default_freeor;
|
|
|
|
|
|
|
|
/* Default reporters */
|
|
|
|
static void default_noticereporter(const char *fmt, va_list ap);
|
|
|
|
static void default_errorreporter(const char *fmt, va_list ap);
|
|
|
|
lwreporter lwnotice_var = default_noticereporter;
|
|
|
|
lwreporter lwerror_var = default_errorreporter;
|
2008-05-31 09:56:44 +00:00
|
|
|
|
2009-06-11 16:44:03 +00:00
|
|
|
static char *lwgeomTypeName[] =
|
2010-02-01 17:35:55 +00:00
|
|
|
{
|
|
|
|
"Unknown",
|
|
|
|
"Point",
|
|
|
|
"LineString",
|
|
|
|
"Polygon",
|
|
|
|
"MultiPoint",
|
|
|
|
"MultiLineString",
|
|
|
|
"MultiPolygon",
|
|
|
|
"GeometryCollection",
|
|
|
|
"CircularString",
|
2011-06-27 18:02:47 +00:00
|
|
|
"CompoundCurve",
|
2010-02-01 17:35:55 +00:00
|
|
|
"CurvePolygon",
|
|
|
|
"MultiCurve",
|
2010-07-25 21:20:09 +00:00
|
|
|
"MultiSurface",
|
2010-08-15 08:30:08 +00:00
|
|
|
"PolyhedralSurface",
|
2010-08-13 17:29:29 +00:00
|
|
|
"Triangle",
|
|
|
|
"Tin"
|
2010-02-01 17:35:55 +00:00
|
|
|
};
|
2004-09-30 08:18:06 +00:00
|
|
|
|
2008-09-23 19:44:57 +00:00
|
|
|
/*
|
2012-12-27 12:56:59 +00:00
|
|
|
* Default lwnotice/lwerror handlers
|
2008-09-23 19:44:57 +00:00
|
|
|
*
|
|
|
|
* Since variadic functions cannot pass their parameters directly, we need
|
|
|
|
* wrappers for these functions to convert the arguments into a va_list
|
|
|
|
* structure.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
lwnotice(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
|
|
|
/* Call the supplied function */
|
|
|
|
(*lwnotice_var)(fmt, ap);
|
|
|
|
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lwerror(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
|
|
|
/* Call the supplied function */
|
|
|
|
(*lwerror_var)(fmt, ap);
|
|
|
|
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2008-06-29 19:11:48 +00:00
|
|
|
/*
|
|
|
|
* Default allocators
|
|
|
|
*
|
|
|
|
* We include some default allocators that use malloc/free/realloc
|
|
|
|
* along with stdout/stderr since this is the most common use case
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
static void *
|
2004-09-30 08:18:06 +00:00
|
|
|
default_allocator(size_t size)
|
|
|
|
{
|
|
|
|
void *mem = malloc(size);
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
static void
|
2004-09-30 08:18:06 +00:00
|
|
|
default_freeor(void *mem)
|
|
|
|
{
|
|
|
|
free(mem);
|
|
|
|
}
|
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
static void *
|
2004-09-30 08:18:06 +00:00
|
|
|
default_reallocator(void *mem, size_t size)
|
|
|
|
{
|
|
|
|
void *ret = realloc(mem, size);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
static void
|
2008-09-23 19:44:57 +00:00
|
|
|
default_noticereporter(const char *fmt, va_list ap)
|
2004-09-30 08:18:06 +00:00
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
/*
|
2004-11-02 16:48:54 +00:00
|
|
|
* This is a GNU extension.
|
|
|
|
* Dunno how to handle errors here.
|
|
|
|
*/
|
2008-09-23 19:44:57 +00:00
|
|
|
if (!lw_vasprintf (&msg, fmt, ap))
|
2004-09-30 08:18:06 +00:00
|
|
|
{
|
|
|
|
va_end (ap);
|
|
|
|
return;
|
|
|
|
}
|
2004-10-05 15:12:18 +00:00
|
|
|
printf("%s\n", msg);
|
2004-09-30 08:18:06 +00:00
|
|
|
free(msg);
|
|
|
|
}
|
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
static void
|
2008-09-23 19:44:57 +00:00
|
|
|
default_errorreporter(const char *fmt, va_list ap)
|
2004-09-30 08:18:06 +00:00
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
/*
|
2004-11-02 16:48:54 +00:00
|
|
|
* This is a GNU extension.
|
|
|
|
* Dunno how to handle errors here.
|
|
|
|
*/
|
2008-09-23 19:44:57 +00:00
|
|
|
if (!lw_vasprintf (&msg, fmt, ap))
|
2004-09-30 08:18:06 +00:00
|
|
|
{
|
|
|
|
va_end (ap);
|
|
|
|
return;
|
|
|
|
}
|
2004-10-05 15:12:18 +00:00
|
|
|
fprintf(stderr, "%s\n", msg);
|
2004-09-30 08:18:06 +00:00
|
|
|
free(msg);
|
2004-10-07 10:03:23 +00:00
|
|
|
exit(1);
|
2004-09-30 08:18:06 +00:00
|
|
|
}
|
2004-09-30 11:45:40 +00:00
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
/**
|
|
|
|
* This function is called by programs which want to set up custom handling
|
|
|
|
* for memory management and error reporting
|
|
|
|
*
|
|
|
|
* Only non-NULL values change their respective handler
|
2008-06-29 19:11:48 +00:00
|
|
|
*/
|
2012-12-27 12:56:59 +00:00
|
|
|
void
|
|
|
|
lwgeom_set_handlers(lwallocator allocator, lwreallocator reallocator,
|
|
|
|
lwfreeor freeor, lwreporter errorreporter,
|
|
|
|
lwreporter noticereporter) {
|
2008-06-29 19:11:48 +00:00
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
if ( allocator ) lwalloc_var = allocator;
|
|
|
|
if ( reallocator ) lwrealloc_var = reallocator;
|
|
|
|
if ( freeor ) lwfree_var = freeor;
|
2009-06-11 16:44:03 +00:00
|
|
|
|
2012-12-27 12:56:59 +00:00
|
|
|
if ( errorreporter ) lwerror_var = errorreporter;
|
|
|
|
if ( noticereporter ) lwnotice_var = noticereporter;
|
|
|
|
}
|
2008-06-29 19:11:48 +00:00
|
|
|
|
2011-10-28 17:01:02 +00:00
|
|
|
const char*
|
|
|
|
lwtype_name(uint8_t type)
|
2004-09-30 11:45:40 +00:00
|
|
|
{
|
2010-11-21 19:02:23 +00:00
|
|
|
if ( type > 15 )
|
2009-06-11 16:44:03 +00:00
|
|
|
{
|
2008-12-22 12:15:12 +00:00
|
|
|
/* assert(0); */
|
2006-04-18 10:28:48 +00:00
|
|
|
return "Invalid type";
|
|
|
|
}
|
2010-11-21 19:02:23 +00:00
|
|
|
return lwgeomTypeName[(int ) type];
|
2004-09-30 11:45:40 +00:00
|
|
|
}
|
2004-10-07 10:03:23 +00:00
|
|
|
|
|
|
|
void *
|
|
|
|
lwalloc(size_t size)
|
|
|
|
{
|
2004-10-08 13:16:58 +00:00
|
|
|
void *mem = lwalloc_var(size);
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(5, "lwalloc: %d@%p", size, mem);
|
2004-10-08 13:16:58 +00:00
|
|
|
return mem;
|
2004-10-07 10:03:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
lwrealloc(void *mem, size_t size)
|
|
|
|
{
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(5, "lwrealloc: %d@%p", size, mem);
|
2004-10-07 10:03:23 +00:00
|
|
|
return lwrealloc_var(mem, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lwfree(void *mem)
|
|
|
|
{
|
2006-01-09 12:39:05 +00:00
|
|
|
lwfree_var(mem);
|
2004-10-07 10:03:23 +00:00
|
|
|
}
|
2004-10-15 09:41:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Removes trailing zeros and dot for a %f formatted number.
|
|
|
|
* Modifies input.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
trim_trailing_zeros(char *str)
|
|
|
|
{
|
|
|
|
char *ptr, *totrim=NULL;
|
|
|
|
int len;
|
|
|
|
int i;
|
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(3, "input: %s", str);
|
2009-06-11 16:44:03 +00:00
|
|
|
|
2004-10-15 09:41:01 +00:00
|
|
|
ptr = strchr(str, '.');
|
2006-01-09 12:39:05 +00:00
|
|
|
if ( ! ptr ) return; /* no dot, no decimal digits */
|
2004-10-15 09:41:01 +00:00
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(3, "ptr: %s", ptr);
|
2004-10-15 09:41:01 +00:00
|
|
|
|
|
|
|
len = strlen(ptr);
|
|
|
|
for (i=len-1; i; i--)
|
|
|
|
{
|
|
|
|
if ( ptr[i] != '0' ) break;
|
|
|
|
totrim=&ptr[i];
|
|
|
|
}
|
|
|
|
if ( totrim )
|
|
|
|
{
|
|
|
|
if ( ptr == totrim-1 ) *ptr = '\0';
|
|
|
|
else *totrim = '\0';
|
|
|
|
}
|
2009-06-11 16:44:03 +00:00
|
|
|
|
2008-05-31 09:56:44 +00:00
|
|
|
LWDEBUGF(3, "output: %s", str);
|
2004-10-15 09:41:01 +00:00
|
|
|
}
|
2004-12-17 11:08:53 +00:00
|
|
|
|
2008-12-10 12:32:40 +00:00
|
|
|
/*
|
2009-06-11 16:44:03 +00:00
|
|
|
* Returns a new string which contains a maximum of maxlength characters starting
|
|
|
|
* from startpos and finishing at endpos (0-based indexing). If the string is
|
|
|
|
* truncated then the first or last characters are replaced by "..." as
|
2008-12-11 13:46:29 +00:00
|
|
|
* appropriate.
|
2008-12-10 12:32:40 +00:00
|
|
|
*
|
|
|
|
* The caller should specify start or end truncation by setting the truncdirection
|
|
|
|
* parameter as follows:
|
|
|
|
* 0 - start truncation (i.e. characters are removed from the beginning)
|
|
|
|
* 1 - end trunctation (i.e. characters are removed from the end)
|
2009-06-11 16:44:03 +00:00
|
|
|
*/
|
2008-12-10 12:32:40 +00:00
|
|
|
|
|
|
|
char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection)
|
|
|
|
{
|
|
|
|
char *output;
|
|
|
|
char *outstart;
|
|
|
|
|
|
|
|
/* Allocate space for new string */
|
2008-12-11 14:55:21 +00:00
|
|
|
output = lwalloc(maxlength + 4);
|
2008-12-10 12:32:40 +00:00
|
|
|
output[0] = '\0';
|
|
|
|
|
|
|
|
/* Start truncation */
|
|
|
|
if (truncdirection == 0)
|
|
|
|
{
|
|
|
|
/* Calculate the start position */
|
2009-06-11 16:44:03 +00:00
|
|
|
if (endpos - startpos < maxlength)
|
2008-12-10 12:32:40 +00:00
|
|
|
{
|
|
|
|
outstart = str + startpos;
|
2009-06-11 16:44:03 +00:00
|
|
|
strncat(output, outstart, endpos - startpos + 1);
|
|
|
|
}
|
2008-12-10 12:32:40 +00:00
|
|
|
else
|
|
|
|
{
|
2008-12-11 13:46:29 +00:00
|
|
|
if (maxlength >= 3)
|
|
|
|
{
|
|
|
|
/* Add "..." prefix */
|
|
|
|
outstart = str + endpos + 1 - maxlength + 3;
|
|
|
|
strncat(output, "...", 3);
|
2009-06-11 16:44:03 +00:00
|
|
|
strncat(output, outstart, maxlength - 3);
|
2008-12-11 13:46:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* maxlength is too small; just output "..." */
|
|
|
|
strncat(output, "...", 3);
|
|
|
|
}
|
2008-12-10 12:32:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* End truncation */
|
|
|
|
if (truncdirection == 1)
|
|
|
|
{
|
|
|
|
/* Calculate the end position */
|
2008-12-11 13:46:29 +00:00
|
|
|
if (endpos - startpos < maxlength)
|
2008-12-10 12:32:40 +00:00
|
|
|
{
|
2008-12-11 13:46:29 +00:00
|
|
|
outstart = str + startpos;
|
|
|
|
strncat(output, outstart, endpos - startpos + 1);
|
2009-06-11 16:44:03 +00:00
|
|
|
}
|
2008-12-10 12:32:40 +00:00
|
|
|
else
|
|
|
|
{
|
2008-12-11 13:46:29 +00:00
|
|
|
if (maxlength >= 3)
|
|
|
|
{
|
|
|
|
/* Add "..." suffix */
|
2009-06-11 16:44:03 +00:00
|
|
|
outstart = str + startpos;
|
2008-12-11 13:46:29 +00:00
|
|
|
strncat(output, outstart, maxlength - 3);
|
2009-06-11 16:44:03 +00:00
|
|
|
strncat(output, "...", 3);
|
2008-12-11 13:46:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* maxlength is too small; just output "..." */
|
|
|
|
strncat(output, "...", 3);
|
|
|
|
}
|
2008-12-10 12:32:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-18 12:36:27 +00:00
|
|
|
char
|
|
|
|
getMachineEndian(void)
|
2004-12-17 11:08:53 +00:00
|
|
|
{
|
2006-01-09 12:39:05 +00:00
|
|
|
static int endian_check_int = 1; /* dont modify this!!! */
|
2004-12-17 11:08:53 +00:00
|
|
|
|
2006-01-09 12:39:05 +00:00
|
|
|
return *((char *) &endian_check_int); /* 0 = big endian | xdr,
|
2011-12-21 14:37:11 +00:00
|
|
|
* 1 = little endian | ndr
|
|
|
|
*/
|
2004-12-17 11:08:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-01 16:21:00 +00:00
|
|
|
void
|
2010-11-25 17:34:21 +00:00
|
|
|
error_if_srid_mismatch(int srid1, int srid2)
|
2005-12-01 16:21:00 +00:00
|
|
|
{
|
|
|
|
if ( srid1 != srid2 )
|
|
|
|
{
|
|
|
|
lwerror("Operation on mixed SRID geometries");
|
|
|
|
}
|
|
|
|
}
|
2011-10-06 13:35:46 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
clamp_srid(int srid)
|
|
|
|
{
|
2012-02-10 16:53:15 +00:00
|
|
|
int newsrid = srid;
|
|
|
|
|
|
|
|
if ( newsrid <= 0 ) {
|
|
|
|
if ( newsrid != SRID_UNKNOWN ) {
|
|
|
|
newsrid = SRID_UNKNOWN;
|
|
|
|
lwnotice("SRID value %d converted to the officially unknown SRID value %d", srid, newsrid);
|
2011-10-10 07:38:27 +00:00
|
|
|
}
|
|
|
|
} else if ( srid > SRID_MAXIMUM ) {
|
2012-02-10 16:53:15 +00:00
|
|
|
newsrid = SRID_USER_MAXIMUM + 1 +
|
|
|
|
/* -1 is to reduce likelyhood of clashes */
|
|
|
|
/* NOTE: must match implementation in postgis_restore.pl */
|
|
|
|
( srid % ( SRID_MAXIMUM - SRID_USER_MAXIMUM - 1 ) );
|
|
|
|
lwnotice("SRID value %d > SRID_MAXIMUM converted to %d", srid, newsrid);
|
2011-10-06 14:08:59 +00:00
|
|
|
}
|
2011-10-10 07:38:27 +00:00
|
|
|
|
2012-02-10 16:53:15 +00:00
|
|
|
return newsrid;
|
2011-10-06 13:35:46 +00:00
|
|
|
}
|