PostGIS  2.1.10dev-r@@SVN_REVISION@@
g_util.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: g_util.c 10680 2012-11-15 00:15:24Z pramsey $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
6  *
7  * This is free software; you can redistribute and/or modify it under
8  * the terms of the GNU General Public Licence. See the COPYING file.
9  *
10  **********************************************************************/
11 
12 #include <ctype.h>
13 
14 #include "liblwgeom_internal.h"
15 
16 /* Structure for the type array */
18 {
19  char *typename;
20  int type;
21  int z;
22  int m;
23 };
24 
25 /* Type array. Note that the order of this array is important in
26  that any typename in the list must *NOT* occur within an entry
27  before it. Otherwise if we search for "POINT" at the top of the
28  list we would also match MULTIPOINT, for example. */
29 
31 {
32  { "GEOMETRYCOLLECTIONZM", COLLECTIONTYPE, 1, 1 },
33  { "GEOMETRYCOLLECTIONZ", COLLECTIONTYPE, 1, 0 },
34  { "GEOMETRYCOLLECTIONM", COLLECTIONTYPE, 0, 1 },
35  { "GEOMETRYCOLLECTION", COLLECTIONTYPE, 0, 0 },
36 
37  { "GEOMETRYZM", 0, 1, 1 },
38  { "GEOMETRYZ", 0, 1, 0 },
39  { "GEOMETRYM", 0, 0, 1 },
40  { "GEOMETRY", 0, 0, 0 },
41 
42  { "POLYHEDRALSURFACEZM", POLYHEDRALSURFACETYPE, 1, 1 },
43  { "POLYHEDRALSURFACEZ", POLYHEDRALSURFACETYPE, 1, 0 },
44  { "POLYHEDRALSURFACEM", POLYHEDRALSURFACETYPE, 0, 1 },
45  { "POLYHEDRALSURFACE", POLYHEDRALSURFACETYPE, 0, 0 },
46 
47  { "TINZM", TINTYPE, 1, 1 },
48  { "TINZ", TINTYPE, 1, 0 },
49  { "TINM", TINTYPE, 0, 1 },
50  { "TIN", TINTYPE, 0, 0 },
51 
52  { "CIRCULARSTRINGZM", CIRCSTRINGTYPE, 1, 1 },
53  { "CIRCULARSTRINGZ", CIRCSTRINGTYPE, 1, 0 },
54  { "CIRCULARSTRINGM", CIRCSTRINGTYPE, 0, 1 },
55  { "CIRCULARSTRING", CIRCSTRINGTYPE, 0, 0 },
56 
57  { "COMPOUNDCURVEZM", COMPOUNDTYPE, 1, 1 },
58  { "COMPOUNDCURVEZ", COMPOUNDTYPE, 1, 0 },
59  { "COMPOUNDCURVEM", COMPOUNDTYPE, 0, 1 },
60  { "COMPOUNDCURVE", COMPOUNDTYPE, 0, 0 },
61 
62  { "CURVEPOLYGONZM", CURVEPOLYTYPE, 1, 1 },
63  { "CURVEPOLYGONZ", CURVEPOLYTYPE, 1, 0 },
64  { "CURVEPOLYGONM", CURVEPOLYTYPE, 0, 1 },
65  { "CURVEPOLYGON", CURVEPOLYTYPE, 0, 0 },
66 
67  { "MULTICURVEZM", MULTICURVETYPE, 1, 1 },
68  { "MULTICURVEZ", MULTICURVETYPE, 1, 0 },
69  { "MULTICURVEM", MULTICURVETYPE, 0, 1 },
70  { "MULTICURVE", MULTICURVETYPE, 0, 0 },
71 
72  { "MULTISURFACEZM", MULTISURFACETYPE, 1, 1 },
73  { "MULTISURFACEZ", MULTISURFACETYPE, 1, 0 },
74  { "MULTISURFACEM", MULTISURFACETYPE, 0, 1 },
75  { "MULTISURFACE", MULTISURFACETYPE, 0, 0 },
76 
77  { "MULTILINESTRINGZM", MULTILINETYPE, 1, 1 },
78  { "MULTILINESTRINGZ", MULTILINETYPE, 1, 0 },
79  { "MULTILINESTRINGM", MULTILINETYPE, 0, 1 },
80  { "MULTILINESTRING", MULTILINETYPE, 0, 0 },
81 
82  { "MULTIPOLYGONZM", MULTIPOLYGONTYPE, 1, 1 },
83  { "MULTIPOLYGONZ", MULTIPOLYGONTYPE, 1, 0 },
84  { "MULTIPOLYGONM", MULTIPOLYGONTYPE, 0, 1 },
85  { "MULTIPOLYGON", MULTIPOLYGONTYPE, 0, 0 },
86 
87  { "MULTIPOINTZM", MULTIPOINTTYPE, 1, 1 },
88  { "MULTIPOINTZ", MULTIPOINTTYPE, 1, 0 },
89  { "MULTIPOINTM", MULTIPOINTTYPE, 0, 1 },
90  { "MULTIPOINT", MULTIPOINTTYPE, 0, 0 },
91 
92  { "LINESTRINGZM", LINETYPE, 1, 1 },
93  { "LINESTRINGZ", LINETYPE, 1, 0 },
94  { "LINESTRINGM", LINETYPE, 0, 1 },
95  { "LINESTRING", LINETYPE, 0, 0 },
96 
97  { "TRIANGLEZM", TRIANGLETYPE, 1, 1 },
98  { "TRIANGLEZ", TRIANGLETYPE, 1, 0 },
99  { "TRIANGLEM", TRIANGLETYPE, 0, 1 },
100  { "TRIANGLE", TRIANGLETYPE, 0, 0 },
101 
102  { "POLYGONZM", POLYGONTYPE, 1, 1 },
103  { "POLYGONZ", POLYGONTYPE, 1, 0 },
104  { "POLYGONM", POLYGONTYPE, 0, 1 },
105  { "POLYGON", POLYGONTYPE, 0, 0 },
106 
107  { "POINTZM", POINTTYPE, 1, 1 },
108  { "POINTZ", POINTTYPE, 1, 0 },
109  { "POINTM", POINTTYPE, 0, 1 },
110  { "POINT", POINTTYPE, 0, 0 }
111 
112 };
113 #define GEOMTYPE_STRUCT_ARRAY_LEN (sizeof geomtype_struct_array/sizeof(struct geomtype_struct))
114 
115 /*
116 * We use a very simple upper case mapper here, because the system toupper() function
117 * is locale dependent and may have trouble mapping lower case strings to the upper
118 * case ones we expect (see, the "Turkisk I", http://www.i18nguy.com/unicode/turkish-i18n.html)
119 * We could also count on PgSQL sending us *lower* case inputs, as it seems to do that
120 * regardless of the case the user provides for the type arguments.
121 */
122 const char dumb_upper_map[128] = "................................................0123456789.......ABCDEFGHIJKLMNOPQRSTUVWXYZ......ABCDEFGHIJKLMNOPQRSTUVWXYZ.....";
123 
124 static char dump_toupper(int in)
125 {
126  if ( in < 0 || in > 127 )
127  return '.';
128  return dumb_upper_map[in];
129 }
130 
131 uint8_t gflags(int hasz, int hasm, int geodetic)
132 {
133  uint8_t flags = 0;
134  if ( hasz )
135  FLAGS_SET_Z(flags, 1);
136  if ( hasm )
137  FLAGS_SET_M(flags, 1);
138  if ( geodetic )
139  FLAGS_SET_GEODETIC(flags, 1);
140  return flags;
141 }
142 
149 int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
150 {
151  char *tmpstr;
152  int tmpstartpos, tmpendpos;
153  int i;
154 
155  assert(str);
156  assert(type);
157  assert(z);
158  assert(m);
159 
160  /* Initialize. */
161  *type = 0;
162  *z = 0;
163  *m = 0;
164 
165  /* Locate any leading/trailing spaces */
166  tmpstartpos = 0;
167  for (i = 0; i < strlen(str); i++)
168  {
169  if (str[i] != ' ')
170  {
171  tmpstartpos = i;
172  break;
173  }
174  }
175 
176  tmpendpos = strlen(str) - 1;
177  for (i = strlen(str) - 1; i >= 0; i--)
178  {
179  if (str[i] != ' ')
180  {
181  tmpendpos = i;
182  break;
183  }
184  }
185 
186  /* Copy and convert to upper case for comparison */
187  tmpstr = lwalloc(tmpendpos - tmpstartpos + 2);
188  for (i = tmpstartpos; i <= tmpendpos; i++)
189  tmpstr[i - tmpstartpos] = dump_toupper(str[i]);
190 
191  /* Add NULL to terminate */
192  tmpstr[i - tmpstartpos] = '\0';
193 
194  /* Now check for the type */
195  for (i = 0; i < GEOMTYPE_STRUCT_ARRAY_LEN; i++)
196  {
197  if (!strcmp(tmpstr, geomtype_struct_array[i].typename))
198  {
199  *type = geomtype_struct_array[i].type;
200  *z = geomtype_struct_array[i].z;
201  *m = geomtype_struct_array[i].m;
202 
203  lwfree(tmpstr);
204 
205  return LW_SUCCESS;
206  }
207 
208  }
209 
210  lwfree(tmpstr);
211 
212  return LW_FAILURE;
213 }
214 
215 
216 
217 
#define LINETYPE
Definition: liblwgeom.h:61
#define MULTICURVETYPE
Definition: liblwgeom.h:70
void lwfree(void *mem)
Definition: lwutil.c:190
#define POLYGONTYPE
Definition: liblwgeom.h:62
#define CURVEPOLYTYPE
Definition: liblwgeom.h:69
#define COMPOUNDTYPE
Definition: liblwgeom.h:68
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
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: g_util.c:149
#define LW_SUCCESS
Definition: liblwgeom.h:55
#define TRIANGLETYPE
Definition: liblwgeom.h:73
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:72
#define FLAGS_SET_GEODETIC(flags, value)
Definition: liblwgeom.h:115
#define LW_FAILURE
Definition: liblwgeom.h:54
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:112
#define TINTYPE
Definition: liblwgeom.h:74
const char dumb_upper_map[128]
Definition: g_util.c:122
struct geomtype_struct geomtype_struct_array[]
Definition: g_util.c:30
uint8_t gflags(int hasz, int hasm, int geodetic)
Construct a new flags char.
Definition: g_util.c:131
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define MULTISURFACETYPE
Definition: liblwgeom.h:71
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:67
void * lwalloc(size_t size)
Definition: lwutil.c:175
static char dump_toupper(int in)
Definition: g_util.c:124
#define MULTILINETYPE
Definition: liblwgeom.h:64
#define GEOMTYPE_STRUCT_ARRAY_LEN
Definition: g_util.c:113
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
#define FLAGS_SET_M(flags, value)
Definition: liblwgeom.h:113