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