PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
rtpg_internal.c
Go to the documentation of this file.
1/*
2 *
3 * WKTRaster - Raster Types for PostGIS
4 * http://trac.osgeo.org/postgis/wiki/WKTRaster
5 *
6 * Copyright (C) 2011-2013 Regents of the University of California
7 * <bkpark@ucdavis.edu>
8 * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9 * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10 * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11 * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12 * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 *
28 */
29
30#include <ctype.h> /* for isspace */
31#include <postgres.h> /* for palloc */
32#include <executor/spi.h>
33
34#include "rtpg_internal.h"
35
36/* string replacement function taken from
37 * http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3
38 */
39/* ---------------------------------------------------------------------------
40 Name : replace - Search & replace a substring by another one.
41 Creation : Thierry Husson, Sept 2010
42 Parameters :
43 str : Big string where we search
44 oldstr : Substring we are looking for
45 newstr : Substring we want to replace with
46 count : Optional pointer to int (input / output value). NULL to ignore.
47 Input: Maximum replacements to be done. NULL or < 1 to do all.
48 Output: Number of replacements done or -1 if not enough memory.
49 Returns : Pointer to the new string or NULL if error.
50 Notes :
51 - Case sensitive - Otherwise, replace functions "strstr" by "strcasestr"
52 - Always allocates memory for the result.
53--------------------------------------------------------------------------- */
54char*
56 const char *str,
57 const char *oldstr, const char *newstr,
58 int *count
59) {
60 const char *tmp = str;
61 char *result;
62 int found = 0;
63 int64_t length, reslen;
64 size_t oldlen = strlen(oldstr);
65 size_t newlen = strlen(newstr);
66 int limit = (count != NULL && *count > 0) ? *count : -1;
67
68 tmp = str;
69 while ((tmp = strstr(tmp, oldstr)) != NULL && found != limit)
70 found++, tmp += oldlen;
71
72 length = strlen(str) + found * (newlen - oldlen);
73 if ((result = (char *) palloc(length + 1)) == NULL) {
74 fprintf(stderr, "Not enough memory\n");
75 found = -1;
76 }
77 else {
78 tmp = str;
79 limit = found; /* Countdown */
80 reslen = 0; /* length of current result */
81
82 /* Replace each old string found with new string */
83 while ((limit-- > 0) && (tmp = strstr(tmp, oldstr)) != NULL) {
84 length = (tmp - str); /* Number of chars to keep intouched */
85 strncpy(result + reslen, str, length); /* Original part keeped */
86 strcpy(result + (reslen += length), newstr); /* Insert new string */
87
88 reslen += newlen;
89 tmp += oldlen;
90 str = tmp;
91 }
92 strcpy(result + reslen, str); /* Copies last part and ending null char */
93 }
94
95 if (count != NULL) *count = found;
96 return result;
97}
98
99char *
101 int j;
102
103 for (j = strlen(str) - 1; j >= 0; j--)
104 str[j] = toupper(str[j]);
105
106 return str;
107}
108
109char*
110rtpg_chartrim(const char *input, char *remove) {
111 char *rtn = NULL;
112 char *ptr = NULL;
113 uint32_t offset = 0;
114
115 if (!input)
116 return NULL;
117 else if (!*input)
118 return (char *) input;
119
120 /* trim left */
121 while (strchr(remove, *input) != NULL)
122 input++;
123
124 /* trim right */
125 ptr = ((char *) input) + strlen(input);
126 while (strchr(remove, *--ptr) != NULL)
127 offset++;
128
129 rtn = palloc(sizeof(char) * (strlen(input) - offset + 1));
130 if (!rtn) {
131 fprintf(stderr, "Not enough memory\n");
132 return NULL;
133 }
134 memcpy(rtn, input, strlen(input) - offset);
135 rtn[strlen(input) - offset] = '\0';
136
137 return rtn;
138}
139
140/* split a string based on a delimiter */
141char**
142rtpg_strsplit(const char *str, const char *delimiter, uint32_t *n) {
143 char *tmp = NULL;
144 char **rtn = NULL;
145 char *token = NULL;
146
147 *n = 0;
148 if (!str)
149 return NULL;
150
151 /* copy str to tmp as strtok will mangle the string */
152 tmp = palloc(sizeof(char) * (strlen(str) + 1));
153 if (NULL == tmp) {
154 fprintf(stderr, "Not enough memory\n");
155 return NULL;
156 }
157 strcpy(tmp, str);
158
159 if (!strlen(tmp) || !delimiter || !strlen(delimiter)) {
160 *n = 1;
161 rtn = (char **) palloc(*n * sizeof(char *));
162 if (NULL == rtn) {
163 fprintf(stderr, "Not enough memory\n");
164 return NULL;
165 }
166 rtn[0] = (char *) palloc(sizeof(char) * (strlen(tmp) + 1));
167 if (NULL == rtn[0]) {
168 fprintf(stderr, "Not enough memory\n");
169 return NULL;
170 }
171 strcpy(rtn[0], tmp);
172 pfree(tmp);
173 return rtn;
174 }
175
176 token = strtok(tmp, delimiter);
177 while (token != NULL) {
178 if (*n < 1) {
179 rtn = (char **) palloc(sizeof(char *));
180 }
181 else {
182 rtn = (char **) repalloc(rtn, (*n + 1) * sizeof(char *));
183 }
184 if (NULL == rtn) {
185 fprintf(stderr, "Not enough memory\n");
186 return NULL;
187 }
188
189 rtn[*n] = NULL;
190 rtn[*n] = (char *) palloc(sizeof(char) * (strlen(token) + 1));
191 if (NULL == rtn[*n]) {
192 fprintf(stderr, "Not enough memory\n");
193 return NULL;
194 }
195
196 strcpy(rtn[*n], token);
197 *n = *n + 1;
198
199 token = strtok(NULL, delimiter);
200 }
201
202 pfree(tmp);
203 return rtn;
204}
205
206char *
208 char *rtn;
209 char *tmp;
210
211 rtn = rtpg_strreplace(str, " ", "", NULL);
212
213 tmp = rtpg_strreplace(rtn, "\n", "", NULL);
214 pfree(rtn);
215 rtn = rtpg_strreplace(tmp, "\t", "", NULL);
216 pfree(tmp);
217 tmp = rtpg_strreplace(rtn, "\f", "", NULL);
218 pfree(rtn);
219 rtn = rtpg_strreplace(tmp, "\r", "", NULL);
220 pfree(tmp);
221
222 return rtn;
223}
224
225char*
226rtpg_trim(const char *input) {
227 char *rtn;
228 char *ptr;
229 uint32_t offset = 0;
230 int inputlen = 0;
231
232 if (!input)
233 return NULL;
234 else if (!*input)
235 return (char *) input;
236
237 /* trim left */
238 while (isspace(*input) && *input != '\0')
239 input++;
240
241 /* trim right */
242 inputlen = strlen(input);
243 if (inputlen) {
244 ptr = ((char *) input) + inputlen;
245 while (isspace(*--ptr))
246 offset++;
247 }
248
249 rtn = palloc(sizeof(char) * (inputlen - offset + 1));
250 if (rtn == NULL) {
251 fprintf(stderr, "Not enough memory\n");
252 return NULL;
253 }
254 strncpy(rtn, input, inputlen - offset);
255 rtn[inputlen - offset] = '\0';
256
257 return rtn;
258}
259
260/*
261 * reverse string search function from
262 * http://stackoverflow.com/a/1634398
263 */
264char *
265rtpg_strrstr(const char *s1, const char *s2) {
266 int s1len = strlen(s1);
267 int s2len = strlen(s2);
268 char *s;
269
270 if (s2len > s1len)
271 return NULL;
272
273 s = (char *) (s1 + s1len - s2len);
274 for (; s >= s1; --s)
275 if (strncmp(s, s2, s2len) == 0)
276 return s;
277
278 return NULL;
279}
280
281char *
282rtpg_getSR(int32_t srid)
283{
284 int i = 0;
285 int len = 0;
286 char *sql = NULL;
287 int spi_result;
288 TupleDesc tupdesc;
289 SPITupleTable *tuptable = NULL;
290 HeapTuple tuple;
291 char *tmp = NULL;
292 char *srs = NULL;
293
294/*
295SELECT
296 CASE
297 WHEN (upper(auth_name) = 'EPSG' OR upper(auth_name) = 'EPSGA') AND length(COALESCE(auth_srid::text, '')) > 0
298 THEN upper(auth_name) || ':' || auth_srid
299 WHEN length(COALESCE(auth_name, '') || COALESCE(auth_srid::text, '')) > 0
300 THEN COALESCE(auth_name, '') || COALESCE(auth_srid::text, '')
301 ELSE ''
302 END,
303 proj4text,
304 srtext
305FROM spatial_ref_sys
306WHERE srid = X
307LIMIT 1
308*/
309
310 len = sizeof(char) * (strlen("SELECT CASE WHEN (upper(auth_name) = 'EPSG' OR upper(auth_name) = 'EPSGA') AND length(COALESCE(auth_srid::text, '')) > 0 THEN upper(auth_name) || ':' || auth_srid WHEN length(COALESCE(auth_name, '') || COALESCE(auth_srid::text, '')) > 0 THEN COALESCE(auth_name, '') || COALESCE(auth_srid::text, '') ELSE '' END, proj4text, srtext FROM spatial_ref_sys WHERE srid = LIMIT 1") + MAX_INT_CHARLEN + 1);
311 sql = (char *) palloc(len);
312 if (NULL == sql) {
313 elog(ERROR, "rtpg_getSR: Could not allocate memory for sql\n");
314 return NULL;
315 }
316
317 spi_result = SPI_connect();
318 if (spi_result != SPI_OK_CONNECT) {
319 pfree(sql);
320 elog(ERROR, "rtpg_getSR: Could not connect to database using SPI\n");
321 return NULL;
322 }
323
324 /* execute query */
325 snprintf(sql, len, "SELECT CASE WHEN (upper(auth_name) = 'EPSG' OR upper(auth_name) = 'EPSGA') AND length(COALESCE(auth_srid::text, '')) > 0 THEN upper(auth_name) || ':' || auth_srid WHEN length(COALESCE(auth_name, '') || COALESCE(auth_srid::text, '')) > 0 THEN COALESCE(auth_name, '') || COALESCE(auth_srid::text, '') ELSE '' END, proj4text, srtext FROM spatial_ref_sys WHERE srid = %d LIMIT 1", srid);
326 POSTGIS_RT_DEBUGF(4, "SRS query: %s", sql);
327 spi_result = SPI_execute(sql, TRUE, 0);
328 SPI_pfree(sql);
329 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
330 if (SPI_tuptable) SPI_freetuptable(tuptable);
331 SPI_finish();
332 elog(ERROR, "rtpg_getSR: Cannot find SRID (%d) in spatial_ref_sys", srid);
333 return NULL;
334 }
335
336 tupdesc = SPI_tuptable->tupdesc;
337 tuptable = SPI_tuptable;
338 tuple = tuptable->vals[0];
339
340 /* which column to use? */
341 for (i = 1; i < 4; i++) {
342 tmp = SPI_getvalue(tuple, tupdesc, i);
343
344 /* value AND GDAL supports this SR */
345 if (
346 SPI_result != SPI_ERROR_NOATTRIBUTE &&
347 SPI_result != SPI_ERROR_NOOUTFUNC &&
348 tmp != NULL &&
349 strlen(tmp) &&
351 ) {
352 POSTGIS_RT_DEBUGF(4, "Value for column %d is %s", i, tmp);
353
354 len = strlen(tmp) + 1;
355 srs = SPI_palloc(sizeof(char) * len);
356 if (NULL == srs) {
357 pfree(tmp);
358 if (SPI_tuptable) SPI_freetuptable(tuptable);
359 SPI_finish();
360 elog(ERROR, "rtpg_getSR: Could not allocate memory for spatial reference text\n");
361 return NULL;
362 }
363 strncpy(srs, tmp, len);
364 pfree(tmp);
365
366 break;
367 }
368
369 if (tmp != NULL)
370 pfree(tmp);
371 continue;
372 }
373
374 if (SPI_tuptable) SPI_freetuptable(tuptable);
375 SPI_finish();
376
377 /* unable to get SR info */
378 if (srs == NULL) {
379 if (SPI_tuptable) SPI_freetuptable(tuptable);
380 SPI_finish();
381 elog(ERROR, "rtpg_getSR: Could not find a viable spatial reference for SRID (%d)", srid);
382 return NULL;
383 }
384
385 return srs;
386}
char * s
Definition cu_in_wkt.c:23
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
#define TRUE
Definition dbfopen.c:73
int rt_util_gdal_supported_sr(const char *srs)
Definition rt_util.c:353
#define str(s)
char ** rtpg_strsplit(const char *str, const char *delimiter, uint32_t *n)
char * rtpg_removespaces(char *str)
char * rtpg_getSR(int32_t srid)
char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
char * rtpg_trim(const char *input)
char * rtpg_strtoupper(char *str)
char * rtpg_chartrim(const char *input, char *remove)
char * rtpg_strrstr(const char *s1, const char *s2)
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition rtpostgis.h:69
#define MAX_INT_CHARLEN
Definition rtpostgis.h:80