rubywmq 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/decode_rfh.c CHANGED
@@ -1,348 +1,348 @@
1
- /*
2
- * Copyright 2007 Edwin M. Fine, Fine Computer Consultants, Inc.
3
- *
4
- * Licensed under the Apache License, Version 2.0
5
- * (the "License"); you may not use this file except
6
- * in compliance with the License. You may obtain a copy
7
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
8
- * Unless required by applicable law or agreed to in writing,
9
- * software distributed under the License is distributed on an
10
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11
- * either express or implied. See the License for the specific
12
- * language governing permissions and limitations under the License.
13
- */
14
-
15
- /*
16
- * This function decodes an RFH NameValueString into separate
17
- * name/value strings and invokes a callback function for each
18
- * name/value pair. The callback function prototype is
19
- *
20
- * void cbfunc(const char *name, const char *value);
21
- *
22
- * Strings are expected to be null-terminated and not contain any
23
- * null characters.
24
- *
25
- * This is the specification for NameValueString:
26
- *
27
- * NameValueString (MQCHARn)
28
- *
29
- * String containing name/value pairs.
30
- *
31
- * This is a variable-length character string containing name/value
32
- * pairs in the form:
33
- *
34
- * name1 value1 name2 value2 name3 value3 ...
35
- *
36
- * Each name or value must be separated from the adjacent name
37
- * or value by one or more blank characters; these blanks are
38
- * not significant. A name or value can contain significant
39
- * blanks by prefixing and suffixing the name or value with the
40
- * double-quote character; all characters between the open
41
- * double-quote and the matching close double-quote are treated
42
- * as significant. In the following example, the name is
43
- * FAMOUS_WORDS, and the value is Hello World:
44
- *
45
- * FAMOUS_WORDS "Hello World"
46
- *
47
- * A name or value can contain any characters other than the
48
- * null character (which acts as a delimiter for
49
- * NameValueString). However, to assist interoperability, an
50
- * application might prefer to restrict names to the following
51
- * characters:
52
- *
53
- * * First character: upper case or lower case alphabetic (A
54
- * through Z, or a through z), or underscore.
55
- *
56
- * * Second character: upper case or lower case alphabetic,
57
- * decimal digit (0 through 9), underscore, hyphen, or
58
- * dot.
59
- *
60
- * If a name or value contains one or more double-quote
61
- * characters, the name or value must be enclosed in double
62
- * quotes, and each double quote within the string must be
63
- * doubled, for example:
64
- *
65
- * Famous_Words "The program displayed ""Hello World"""
66
- *
67
- * Names and values are case sensitive, that is, lowercase
68
- * letters are not considered to be the same as uppercase
69
- * letters. For example, FAMOUS_WORDS and Famous_Words are two
70
- * different names. / The length in bytes of NameValueString is
71
- * equal to StrucLength minus MQRFH_STRUC_LENGTH_FIXED. To avoid
72
- * problems with data conversion of the user data in some
73
- * environments, make sure that this length is a multiple of
74
- * four. NameValueString must be padded with blanks to this
75
- * length, or terminated earlier by placing a null character
76
- * following the last value in the string. The null and bytes
77
- * following it, up to the specified length of NameValueString,
78
- * are ignored.
79
- */
80
-
81
- #include "decode_rfh.h"
82
- #include <stdio.h>
83
-
84
- #define MAX_TOK_LEN 1024 /* This is pretty generous */
85
- #define EOS -1 /* End of input string */
86
- #define QUOTE '"'
87
-
88
- #define IS_SEPARATOR(ch) ((ch) == ' ' || (ch) == '\0')
89
- #define IS_VALID_ID_CHAR(ch) (!IS_SEPARATOR(ch))
90
- #define IS_UNQUOTED_ID_CHAR(ch) (!IS_SEPARATOR(ch) && ch != QUOTE)
91
- #define GETCHAR(charp, endp) ((charp) < (endp) ? (int)*charp++ : EOS)
92
- #define LOOKAHEAD(charp, endp) (charp < endp - 1 ? (int)*charp : EOS)
93
- #define PUSHBACK(ch, charp) (*--charp = (char)ch)
94
-
95
- #define SKIP_SEPARATORS(charp, endp) \
96
- while (charp < endp && IS_SEPARATOR(*charp)) ++charp
97
-
98
- typedef enum {
99
- ST_INITIAL,
100
- ST_IN_QUOTED_ID,
101
- ST_IN_UNQUOTED_ID,
102
- ST_END,
103
- } state_t;
104
-
105
- static int debug_mode = 0;
106
-
107
- int rfh_in_debug_mode(void)
108
- {
109
- return debug_mode;
110
- }
111
-
112
- void rfh_set_debug_mode(int on_if_true)
113
- {
114
- debug_mode = on_if_true;
115
- }
116
-
117
- #define ENUM_TUPLE(enum_val) { enum_val, #enum_val }
118
- #define NUM_ELEMS(arr) (sizeof(arr) / sizeof(*arr))
119
-
120
- static const char *rfh_state_to_s(state_t state)
121
- {
122
- static struct
123
- {
124
- state_t state;
125
- const char *str;
126
- } state_map[] =
127
- {
128
- ENUM_TUPLE(ST_INITIAL),
129
- ENUM_TUPLE(ST_IN_QUOTED_ID),
130
- ENUM_TUPLE(ST_IN_UNQUOTED_ID),
131
- ENUM_TUPLE(ST_END),
132
- };
133
-
134
- size_t i;
135
-
136
- for (i = 0; i < NUM_ELEMS(state_map); ++i)
137
- if (state_map[i].state == state)
138
- return state_map[i].str;
139
-
140
- return "";
141
- }
142
-
143
- const char *rfh_toktype_to_s(rfh_toktype_t toktype)
144
- {
145
- static struct
146
- {
147
- rfh_toktype_t toktype;
148
- const char *str;
149
- } toktype_map[] =
150
- {
151
- ENUM_TUPLE(TT_TOKEN),
152
- ENUM_TUPLE(TT_UNESCAPED_QUOTE),
153
- ENUM_TUPLE(TT_ILLEGAL_QUOTE),
154
- ENUM_TUPLE(TT_UNEXPECTED_EOS),
155
- ENUM_TUPLE(TT_TOKEN_TRUNCATED),
156
- ENUM_TUPLE(TT_INTERNAL_ERROR),
157
- ENUM_TUPLE(TT_ALLOC_FAILURE),
158
- ENUM_TUPLE(TT_END),
159
- };
160
-
161
- size_t i;
162
-
163
- for (i = 0; i < NUM_ELEMS(toktype_map); ++i)
164
- if (toktype_map[i].toktype == toktype)
165
- return toktype_map[i].str;
166
-
167
- return "";
168
- }
169
-
170
- static rfh_toktype_t get_token(const char **charpp, const char *endp, char *token, char *end_token)
171
- {
172
- const char *charp = *charpp;
173
- char *tokp = token;
174
- int ch;
175
- state_t state = ST_INITIAL;
176
- rfh_toktype_t toktype = TT_TOKEN;
177
-
178
- SKIP_SEPARATORS(charp, endp);
179
-
180
- while (state != ST_END && tokp < end_token)
181
- {
182
- ch = GETCHAR(charp, endp);
183
-
184
- if (debug_mode)
185
- fprintf(stderr, "state = %s, char = %c [%d]\n", rfh_state_to_s(state), (char)ch, ch);
186
-
187
- switch (state)
188
- {
189
- case ST_INITIAL:
190
- if (ch == EOS)
191
- {
192
- *tokp = '\0';
193
- toktype = TT_END;
194
- state = ST_END;
195
- if (debug_mode)
196
- fprintf(stderr, "new state = %s, toktype = %s\n",
197
- rfh_state_to_s(state), rfh_toktype_to_s(toktype));
198
- }
199
- else if (IS_UNQUOTED_ID_CHAR(ch))
200
- {
201
- *tokp++ = (char)ch;
202
- state = ST_IN_UNQUOTED_ID;
203
- if (debug_mode)
204
- fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
205
- }
206
- else if (ch == QUOTE)
207
- {
208
- state = ST_IN_QUOTED_ID;
209
- if (debug_mode)
210
- fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
211
- }
212
- break;
213
-
214
- case ST_IN_UNQUOTED_ID:
215
- if (IS_SEPARATOR(ch) || ch == EOS)
216
- {
217
- *tokp = '\0';
218
- state = ST_END;
219
- if (debug_mode)
220
- fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
221
- }
222
- else if (ch == QUOTE) /* Not allowed in unquoted string */
223
- {
224
- toktype = TT_ILLEGAL_QUOTE;
225
- state = ST_END;
226
- if (debug_mode)
227
- fprintf(stderr, "new state = %s, toktype = %s\n",
228
- rfh_state_to_s(state), rfh_toktype_to_s(toktype));
229
- }
230
- else
231
- *tokp++ = (char)ch;
232
- break;
233
-
234
- case ST_IN_QUOTED_ID:
235
- if (ch == QUOTE) /* Could be end of token, or first char of "" */
236
- {
237
- int lookahead_ch = LOOKAHEAD(charp, endp);
238
- if (lookahead_ch == QUOTE) /* Found escaped quote */
239
- {
240
- *tokp++ = QUOTE;
241
- ++charp; /* Skip second quote */
242
- }
243
- else if (IS_SEPARATOR(lookahead_ch) || lookahead_ch == EOS) /* End of token */
244
- {
245
- *tokp = '\0';
246
- state = ST_END;
247
- if (debug_mode)
248
- fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
249
- }
250
- else /* Error: Unescaped quote */
251
- {
252
- toktype = TT_UNESCAPED_QUOTE;
253
- state = ST_END;
254
- if (debug_mode)
255
- fprintf(stderr, "new state = %s, toktype = %s\n",
256
- rfh_state_to_s(state), rfh_toktype_to_s(toktype));
257
- }
258
- }
259
- else if (ch == EOS) /* Error */
260
- {
261
- toktype = TT_UNEXPECTED_EOS;
262
- state = ST_END;
263
- if (debug_mode)
264
- fprintf(stderr, "new state = %s, toktype = %s\n",
265
- rfh_state_to_s(state), rfh_toktype_to_s(toktype));
266
- }
267
- else
268
- *tokp++ = (char)ch;
269
- break;
270
-
271
- default:
272
- toktype = TT_INTERNAL_ERROR;
273
- state = ST_END;
274
- if (debug_mode)
275
- fprintf(stderr, "new state = %s, toktype = %s\n",
276
- rfh_state_to_s(state), rfh_toktype_to_s(toktype));
277
- break;
278
- } /* switch */
279
- } /* while */
280
-
281
- /* If state is not ST_END, an error may have occurred */
282
- if (state != ST_END && toktype == TT_TOKEN)
283
- {
284
- if (tokp >= end_token)
285
- toktype = TT_TOKEN_TRUNCATED;
286
- else
287
- toktype = TT_UNEXPECTED_EOS;
288
-
289
- if (debug_mode)
290
- fprintf(stderr, "end state = %s, toktype = %s\n",
291
- rfh_state_to_s(state), rfh_toktype_to_s(toktype));
292
- }
293
-
294
- *charpp = charp;
295
-
296
- if (debug_mode)
297
- fprintf(stderr, "-- leaving; end state = %s, returned toktype = %s, returned token = [%s]\n",
298
- rfh_state_to_s(state), rfh_toktype_to_s(toktype), token);
299
-
300
- return toktype;
301
- }
302
-
303
- rfh_toktype_t rfh_decode_name_val_str(const char *nvstr, size_t len, CALLBACK_FN callback, void *user_data)
304
- {
305
- #if defined(USE_FIXED_BUFFERS)
306
- char name[MAX_TOK_LEN + 1];
307
- char value[MAX_TOK_LEN + 1];
308
- size_t name_len = sizeof(name);
309
- size_t value_len = sizeof(value);
310
- #else
311
- size_t name_len = len + 1;
312
- size_t value_len = len + 1;
313
- char *buf = (char *)malloc(len * 2 * sizeof(char) + 2);
314
- char *name = buf;
315
- char *value = buf + len + 1;
316
- #endif
317
-
318
- const char *charp = nvstr, *endp = nvstr + len;
319
- rfh_toktype_t toktype;
320
-
321
- #if !defined(USE_FIXED_BUFFERS)
322
- if (buf == NULL) /* Out of mem */
323
- return TT_ALLOC_FAILURE;
324
- #endif
325
-
326
- for (;;)
327
- {
328
- if ((toktype = get_token(&charp, endp, name, name + name_len)) != TT_TOKEN)
329
- {
330
- break;
331
- }
332
-
333
- if ((toktype = get_token(&charp, endp, value, value + value_len)) != TT_TOKEN)
334
- {
335
- if (toktype == TT_END) /* Expected a value! */
336
- toktype = TT_UNEXPECTED_EOS;
337
- break;
338
- }
339
-
340
- callback(name, value, user_data);
341
- }
342
-
343
- #if !defined(USE_FIXED_BUFFERS)
344
- free(buf);
345
- #endif
346
-
347
- return toktype;
348
- }
1
+ /*
2
+ * Copyright 2007 Edwin M. Fine, Fine Computer Consultants, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0
5
+ * (the "License"); you may not use this file except
6
+ * in compliance with the License. You may obtain a copy
7
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ * Unless required by applicable law or agreed to in writing,
9
+ * software distributed under the License is distributed on an
10
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11
+ * either express or implied. See the License for the specific
12
+ * language governing permissions and limitations under the License.
13
+ */
14
+
15
+ /*
16
+ * This function decodes an RFH NameValueString into separate
17
+ * name/value strings and invokes a callback function for each
18
+ * name/value pair. The callback function prototype is
19
+ *
20
+ * void cbfunc(const char *name, const char *value);
21
+ *
22
+ * Strings are expected to be null-terminated and not contain any
23
+ * null characters.
24
+ *
25
+ * This is the specification for NameValueString:
26
+ *
27
+ * NameValueString (MQCHARn)
28
+ *
29
+ * String containing name/value pairs.
30
+ *
31
+ * This is a variable-length character string containing name/value
32
+ * pairs in the form:
33
+ *
34
+ * name1 value1 name2 value2 name3 value3 ...
35
+ *
36
+ * Each name or value must be separated from the adjacent name
37
+ * or value by one or more blank characters; these blanks are
38
+ * not significant. A name or value can contain significant
39
+ * blanks by prefixing and suffixing the name or value with the
40
+ * double-quote character; all characters between the open
41
+ * double-quote and the matching close double-quote are treated
42
+ * as significant. In the following example, the name is
43
+ * FAMOUS_WORDS, and the value is Hello World:
44
+ *
45
+ * FAMOUS_WORDS "Hello World"
46
+ *
47
+ * A name or value can contain any characters other than the
48
+ * null character (which acts as a delimiter for
49
+ * NameValueString). However, to assist interoperability, an
50
+ * application might prefer to restrict names to the following
51
+ * characters:
52
+ *
53
+ * * First character: upper case or lower case alphabetic (A
54
+ * through Z, or a through z), or underscore.
55
+ *
56
+ * * Second character: upper case or lower case alphabetic,
57
+ * decimal digit (0 through 9), underscore, hyphen, or
58
+ * dot.
59
+ *
60
+ * If a name or value contains one or more double-quote
61
+ * characters, the name or value must be enclosed in double
62
+ * quotes, and each double quote within the string must be
63
+ * doubled, for example:
64
+ *
65
+ * Famous_Words "The program displayed ""Hello World"""
66
+ *
67
+ * Names and values are case sensitive, that is, lowercase
68
+ * letters are not considered to be the same as uppercase
69
+ * letters. For example, FAMOUS_WORDS and Famous_Words are two
70
+ * different names. / The length in bytes of NameValueString is
71
+ * equal to StrucLength minus MQRFH_STRUC_LENGTH_FIXED. To avoid
72
+ * problems with data conversion of the user data in some
73
+ * environments, make sure that this length is a multiple of
74
+ * four. NameValueString must be padded with blanks to this
75
+ * length, or terminated earlier by placing a null character
76
+ * following the last value in the string. The null and bytes
77
+ * following it, up to the specified length of NameValueString,
78
+ * are ignored.
79
+ */
80
+
81
+ #include "decode_rfh.h"
82
+ #include <stdio.h>
83
+
84
+ #define MAX_TOK_LEN 1024 /* This is pretty generous */
85
+ #define EOS -1 /* End of input string */
86
+ #define QUOTE '"'
87
+
88
+ #define IS_SEPARATOR(ch) ((ch) == ' ' || (ch) == '\0')
89
+ #define IS_VALID_ID_CHAR(ch) (!IS_SEPARATOR(ch))
90
+ #define IS_UNQUOTED_ID_CHAR(ch) (!IS_SEPARATOR(ch) && ch != QUOTE)
91
+ #define GETCHAR(charp, endp) ((charp) < (endp) ? (int)*charp++ : EOS)
92
+ #define LOOKAHEAD(charp, endp) (charp < endp - 1 ? (int)*charp : EOS)
93
+ #define PUSHBACK(ch, charp) (*--charp = (char)ch)
94
+
95
+ #define SKIP_SEPARATORS(charp, endp) \
96
+ while (charp < endp && IS_SEPARATOR(*charp)) ++charp
97
+
98
+ typedef enum {
99
+ ST_INITIAL,
100
+ ST_IN_QUOTED_ID,
101
+ ST_IN_UNQUOTED_ID,
102
+ ST_END,
103
+ } state_t;
104
+
105
+ static int debug_mode = 0;
106
+
107
+ int rfh_in_debug_mode(void)
108
+ {
109
+ return debug_mode;
110
+ }
111
+
112
+ void rfh_set_debug_mode(int on_if_true)
113
+ {
114
+ debug_mode = on_if_true;
115
+ }
116
+
117
+ #define ENUM_TUPLE(enum_val) { enum_val, #enum_val }
118
+ #define NUM_ELEMS(arr) (sizeof(arr) / sizeof(*arr))
119
+
120
+ static const char *rfh_state_to_s(state_t state)
121
+ {
122
+ static struct
123
+ {
124
+ state_t state;
125
+ const char *str;
126
+ } state_map[] =
127
+ {
128
+ ENUM_TUPLE(ST_INITIAL),
129
+ ENUM_TUPLE(ST_IN_QUOTED_ID),
130
+ ENUM_TUPLE(ST_IN_UNQUOTED_ID),
131
+ ENUM_TUPLE(ST_END),
132
+ };
133
+
134
+ size_t i;
135
+
136
+ for (i = 0; i < NUM_ELEMS(state_map); ++i)
137
+ if (state_map[i].state == state)
138
+ return state_map[i].str;
139
+
140
+ return "";
141
+ }
142
+
143
+ const char *rfh_toktype_to_s(rfh_toktype_t toktype)
144
+ {
145
+ static struct
146
+ {
147
+ rfh_toktype_t toktype;
148
+ const char *str;
149
+ } toktype_map[] =
150
+ {
151
+ ENUM_TUPLE(TT_TOKEN),
152
+ ENUM_TUPLE(TT_UNESCAPED_QUOTE),
153
+ ENUM_TUPLE(TT_ILLEGAL_QUOTE),
154
+ ENUM_TUPLE(TT_UNEXPECTED_EOS),
155
+ ENUM_TUPLE(TT_TOKEN_TRUNCATED),
156
+ ENUM_TUPLE(TT_INTERNAL_ERROR),
157
+ ENUM_TUPLE(TT_ALLOC_FAILURE),
158
+ ENUM_TUPLE(TT_END),
159
+ };
160
+
161
+ size_t i;
162
+
163
+ for (i = 0; i < NUM_ELEMS(toktype_map); ++i)
164
+ if (toktype_map[i].toktype == toktype)
165
+ return toktype_map[i].str;
166
+
167
+ return "";
168
+ }
169
+
170
+ static rfh_toktype_t get_token(const char **charpp, const char *endp, char *token, char *end_token)
171
+ {
172
+ const char *charp = *charpp;
173
+ char *tokp = token;
174
+ int ch;
175
+ state_t state = ST_INITIAL;
176
+ rfh_toktype_t toktype = TT_TOKEN;
177
+
178
+ SKIP_SEPARATORS(charp, endp);
179
+
180
+ while (state != ST_END && tokp < end_token)
181
+ {
182
+ ch = GETCHAR(charp, endp);
183
+
184
+ if (debug_mode)
185
+ fprintf(stderr, "state = %s, char = %c [%d]\n", rfh_state_to_s(state), (char)ch, ch);
186
+
187
+ switch (state)
188
+ {
189
+ case ST_INITIAL:
190
+ if (ch == EOS)
191
+ {
192
+ *tokp = '\0';
193
+ toktype = TT_END;
194
+ state = ST_END;
195
+ if (debug_mode)
196
+ fprintf(stderr, "new state = %s, toktype = %s\n",
197
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype));
198
+ }
199
+ else if (IS_UNQUOTED_ID_CHAR(ch))
200
+ {
201
+ *tokp++ = (char)ch;
202
+ state = ST_IN_UNQUOTED_ID;
203
+ if (debug_mode)
204
+ fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
205
+ }
206
+ else if (ch == QUOTE)
207
+ {
208
+ state = ST_IN_QUOTED_ID;
209
+ if (debug_mode)
210
+ fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
211
+ }
212
+ break;
213
+
214
+ case ST_IN_UNQUOTED_ID:
215
+ if (IS_SEPARATOR(ch) || ch == EOS)
216
+ {
217
+ *tokp = '\0';
218
+ state = ST_END;
219
+ if (debug_mode)
220
+ fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
221
+ }
222
+ else if (ch == QUOTE) /* Not allowed in unquoted string */
223
+ {
224
+ toktype = TT_ILLEGAL_QUOTE;
225
+ state = ST_END;
226
+ if (debug_mode)
227
+ fprintf(stderr, "new state = %s, toktype = %s\n",
228
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype));
229
+ }
230
+ else
231
+ *tokp++ = (char)ch;
232
+ break;
233
+
234
+ case ST_IN_QUOTED_ID:
235
+ if (ch == QUOTE) /* Could be end of token, or first char of "" */
236
+ {
237
+ int lookahead_ch = LOOKAHEAD(charp, endp);
238
+ if (lookahead_ch == QUOTE) /* Found escaped quote */
239
+ {
240
+ *tokp++ = QUOTE;
241
+ ++charp; /* Skip second quote */
242
+ }
243
+ else if (IS_SEPARATOR(lookahead_ch) || lookahead_ch == EOS) /* End of token */
244
+ {
245
+ *tokp = '\0';
246
+ state = ST_END;
247
+ if (debug_mode)
248
+ fprintf(stderr, "new state = %s\n", rfh_state_to_s(state));
249
+ }
250
+ else /* Error: Unescaped quote */
251
+ {
252
+ toktype = TT_UNESCAPED_QUOTE;
253
+ state = ST_END;
254
+ if (debug_mode)
255
+ fprintf(stderr, "new state = %s, toktype = %s\n",
256
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype));
257
+ }
258
+ }
259
+ else if (ch == EOS) /* Error */
260
+ {
261
+ toktype = TT_UNEXPECTED_EOS;
262
+ state = ST_END;
263
+ if (debug_mode)
264
+ fprintf(stderr, "new state = %s, toktype = %s\n",
265
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype));
266
+ }
267
+ else
268
+ *tokp++ = (char)ch;
269
+ break;
270
+
271
+ default:
272
+ toktype = TT_INTERNAL_ERROR;
273
+ state = ST_END;
274
+ if (debug_mode)
275
+ fprintf(stderr, "new state = %s, toktype = %s\n",
276
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype));
277
+ break;
278
+ } /* switch */
279
+ } /* while */
280
+
281
+ /* If state is not ST_END, an error may have occurred */
282
+ if (state != ST_END && toktype == TT_TOKEN)
283
+ {
284
+ if (tokp >= end_token)
285
+ toktype = TT_TOKEN_TRUNCATED;
286
+ else
287
+ toktype = TT_UNEXPECTED_EOS;
288
+
289
+ if (debug_mode)
290
+ fprintf(stderr, "end state = %s, toktype = %s\n",
291
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype));
292
+ }
293
+
294
+ *charpp = charp;
295
+
296
+ if (debug_mode)
297
+ fprintf(stderr, "-- leaving; end state = %s, returned toktype = %s, returned token = [%s]\n",
298
+ rfh_state_to_s(state), rfh_toktype_to_s(toktype), token);
299
+
300
+ return toktype;
301
+ }
302
+
303
+ rfh_toktype_t rfh_decode_name_val_str(const char *nvstr, size_t len, CALLBACK_FN callback, void *user_data)
304
+ {
305
+ #if defined(USE_FIXED_BUFFERS)
306
+ char name[MAX_TOK_LEN + 1];
307
+ char value[MAX_TOK_LEN + 1];
308
+ size_t name_len = sizeof(name);
309
+ size_t value_len = sizeof(value);
310
+ #else
311
+ size_t name_len = len + 1;
312
+ size_t value_len = len + 1;
313
+ char *buf = (char *)malloc(len * 2 * sizeof(char) + 2);
314
+ char *name = buf;
315
+ char *value = buf + len + 1;
316
+ #endif
317
+
318
+ const char *charp = nvstr, *endp = nvstr + len;
319
+ rfh_toktype_t toktype;
320
+
321
+ #if !defined(USE_FIXED_BUFFERS)
322
+ if (buf == NULL) /* Out of mem */
323
+ return TT_ALLOC_FAILURE;
324
+ #endif
325
+
326
+ for (;;)
327
+ {
328
+ if ((toktype = get_token(&charp, endp, name, name + name_len)) != TT_TOKEN)
329
+ {
330
+ break;
331
+ }
332
+
333
+ if ((toktype = get_token(&charp, endp, value, value + value_len)) != TT_TOKEN)
334
+ {
335
+ if (toktype == TT_END) /* Expected a value! */
336
+ toktype = TT_UNEXPECTED_EOS;
337
+ break;
338
+ }
339
+
340
+ callback(name, value, user_data);
341
+ }
342
+
343
+ #if !defined(USE_FIXED_BUFFERS)
344
+ free(buf);
345
+ #endif
346
+
347
+ return toktype;
348
+ }