rubywmq 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }