PostGIS  3.4.0dev-r@@SVN_REVISION@@
optionlist.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 2021 Paul Ramsey <pramsey@cleverelephant.ca>
22  *
23  **********************************************************************/
24 
25 #include "liblwgeom_internal.h"
26 #include "optionlist.h"
27 
28 #include <ctype.h> // tolower
29 #include <string.h> // strtok
30 
31 static void
33 {
34  if (!key) return;
35  while (*key) {
36  *key = tolower(*key);
37  key++;
38  }
39  return;
40 }
41 
42 // static void
43 // option_list_string_to_upper(char* key)
44 // {
45 // if (!key) return;
46 // while (*key) {
47 // *key = toupper(*key);
48 // key++;
49 // }
50 // return;
51 // }
52 
53 const char*
54 option_list_search(char** olist, const char* key)
55 {
56  size_t i = 0;
57  if (!olist) return NULL;
58  if (!key) return NULL;
59  while (olist[i]) {
60  // Even entries are keys
61  if (!(i % 2)) {
62  // Does this key match ours?
63  if (strcmp(olist[i], key) == 0) {
64  return olist[i+1];
65  }
66  }
67  i++;
68  }
69  return NULL;
70 }
71 
72 size_t
73 option_list_length(char** olist)
74 {
75  size_t i = 0;
76  char **iter = olist;
77  if (!olist) return 0;
78  while(*iter) {
79  i++;
80  iter++;
81  }
82  return i;
83 }
84 
85 void
86 option_list_parse(char* input, char** olist)
87 {
88  const char *toksep = " ";
89  const char kvsep = '=';
90  char *key, *val;
91  if (!input) return;
92  size_t i = 0, sz;
93 
94  /* strtok nulls out the space between each token */
95  for (key = strtok(input, toksep); key; key = strtok(NULL, toksep)) {
96  if (i >= OPTION_LIST_SIZE) return;
97  olist[i] = key;
98  i += 2;
99  }
100 
101  sz = i;
102  /* keys are every second entry in the olist */
103  for (i = 0; i < sz; i += 2) {
104  if (i >= OPTION_LIST_SIZE) return;
105  key = olist[i];
106  /* find the key/value separator */
107  val = strchr(key, kvsep);
108  if (!val) {
109  lwerror("Option string entry '%s' lacks separator '%c'", key, kvsep);
110  }
111  /* null out the separator */
112  *val = '\0';
113  /* point value entry to just after separator */
114  olist[i+1] = ++val;
115  /* all keys forced to lower case */
117  }
118 }
119 
120 void
121 option_list_gdal_parse(char* input, char** olist)
122 {
123  const char *toksep = " ";
124  const char kvsep = '=';
125  const char q2 = '"';
126  const char q1 = '\'';
127  const char notspace = 0x1F;
128 
129  char *key, *val;
130  int in_str = 0;
131  size_t i = 0, sz, input_sz;
132  char *ptr = input;
133 
134  if (!input)
135  lwerror("Option string is null");
136  input_sz = strlen(input);
137 
138  /* Temporarily hide quoted spaces */
139  while(*ptr) {
140  if (*ptr == q2 || *ptr == q1)
141  in_str = !in_str;
142  else if (in_str && *ptr == ' ')
143  *ptr = notspace;
144 
145  ptr++;
146  }
147 
148  /* Tokenize on spaces */
149  for (key = strtok(input, toksep); key; key = strtok(NULL, toksep)) {
150  if (i >= OPTION_LIST_SIZE) return;
151  olist[i++] = key;
152  }
153 
154  /* Check that these are GDAL KEY=VALUE options */
155  sz = i;
156  for (i = 0; i < sz; ++i) {
157  if (i >= OPTION_LIST_SIZE) return;
158  key = olist[i];
159  /* find the key/value separator */
160  val = strchr(key, kvsep);
161  if (!val) {
162  lwerror("Option string entry '%s' lacks separator '%c'", key, kvsep);
163  return;
164  }
165  }
166 
167  /* Unhide quoted space */
168  for (i = 0; i <= input_sz; ++i) {
169  if (input[i] == notspace)
170  input[i] = ' ';
171  }
172 }
173 
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static void option_list_string_to_lower(char *key)
Definition: optionlist.c:32
void option_list_gdal_parse(char *input, char **olist)
Definition: optionlist.c:121
size_t option_list_length(char **olist)
Returns the total number of keys and values in the list.
Definition: optionlist.c:73
const char * option_list_search(char **olist, const char *key)
Returns null if the key cannot be found.
Definition: optionlist.c:54
void option_list_parse(char *input, char **olist)
option_list is a null-terminated list of strings, where every odd string is a key and every even stri...
Definition: optionlist.c:86
#define OPTION_LIST_SIZE
Definition: optionlist.h:31