OSDN Git Service

jsonrpcのバグフィクス
[mimic/MiMicSDK.git] / lib / src / http / json / NyLPC_cJsonRpcParser.c
1 #include "NyLPC_cJsonRpcParser.h"\r
2 #include <ctype.h>\r
3 //\r
4 //      NyLPC_TJsonRpcParserResult\r
5 //\r
6 \r
7 \r
8 NyLPC_TBool NyLPC_TJsonRpcParserResult_getUInt32(const union NyLPC_TJsonRpcParserResult* i_struct,NyLPC_TInt16 i_idx,NyLPC_TUInt32* o_val)\r
9 {\r
10         if(i_struct->method.param_index[i_idx]==0xff){\r
11                 return NyLPC_TBool_FALSE;\r
12         }\r
13         if(i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx]!=NyLPC_cJsonRpcParser_TYPE_UINT32){\r
14                 return NyLPC_TBool_FALSE;\r
15         }\r
16         *o_val = *((NyLPC_TUInt32*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx]));\r
17         return NyLPC_TBool_TRUE;\r
18 }\r
19 NyLPC_TBool NyLPC_TJsonRpcParserResult_getInt32(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TInt32* o_val)\r
20 {\r
21         if(i_struct->method.param_index[i_idx]==0xff){\r
22                 return NyLPC_TBool_FALSE;\r
23         }\r
24         if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_INT32){\r
25                 return NyLPC_TBool_FALSE;\r
26         }\r
27         *o_val = *((NyLPC_TInt32*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx]));\r
28         return NyLPC_TBool_TRUE;\r
29 }\r
30 NyLPC_TBool NyLPC_TJsonRpcParserResult_getStr(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, const NyLPC_TChar** o_val, NyLPC_TUInt8* o_len)\r
31 {\r
32         if(i_struct->method.param_index[i_idx]==0xff){\r
33                 return NyLPC_TBool_FALSE;\r
34         }\r
35         if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_STRING){\r
36                 return NyLPC_TBool_FALSE;\r
37         }\r
38         *o_val = ((NyLPC_TChar*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx]+1));\r
39         if (o_len){\r
40                 *o_len = *((NyLPC_TUInt8*)(*o_val-1));\r
41         }\r
42         return NyLPC_TBool_TRUE;\r
43 }\r
44 NyLPC_TBool NyLPC_TJsonRpcParserResult_getByteArray(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, const NyLPC_TUInt8** o_val, NyLPC_TUInt8* o_len)\r
45 {\r
46         if (i_struct->method.param_index[i_idx] == 0xff){\r
47                 return NyLPC_TBool_FALSE;\r
48         }\r
49         if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_BSTRING){\r
50                 return NyLPC_TBool_FALSE;\r
51         }\r
52         *o_val = ((NyLPC_TUInt8*)(i_struct->method.param_buf + i_struct->method.param_index[i_idx] + 1));\r
53         if (o_len){\r
54                 *o_len = *((NyLPC_TUInt8*)(*o_val - 1));\r
55         }\r
56         return NyLPC_TBool_TRUE;\r
57 }\r
58 \r
59 NyLPC_TBool NyLPC_TJsonRpcParserResult_getByte(const union NyLPC_TJsonRpcParserResult* i_struct, NyLPC_TInt16 i_idx, NyLPC_TUInt8* o_val)\r
60 {\r
61         if(i_struct->method.param_index[i_idx]==0xff){\r
62                 return NyLPC_TBool_FALSE;\r
63         }\r
64         if (i_struct->method.class_def->functions[i_struct->method.func_number].param_patt[i_idx] != NyLPC_cJsonRpcParser_TYPE_BYTE){\r
65                 return NyLPC_TBool_FALSE;\r
66         }\r
67         *o_val = *(i_struct->method.param_buf + i_struct->method.param_index[i_idx]);\r
68         return NyLPC_TBool_TRUE;\r
69 }\r
70 \r
71 \r
72 //\r
73 //      NyLPC_cJsonRpcParser\r
74 //\r
75 \r
76 \r
77 \r
78 #define NAME_ID_UNKNOWN         0\r
79 #define NAME_ID_VERSION         1\r
80 #define NAME_ID_METHOD          2\r
81 #define NAME_ID_RESULT          3\r
82 #define NAME_ID_PARAMS          4\r
83 #define NAME_ID_ID                      5\r
84 \r
85 const struct NyLPC_TTextIdTbl method_name_tbl[]=\r
86 {\r
87         {"jsonrpc",NAME_ID_VERSION},\r
88         {"method",NAME_ID_METHOD},\r
89         {"params",NAME_ID_PARAMS},\r
90         {"id",NAME_ID_ID},\r
91         {NULL,NAME_ID_UNKNOWN}\r
92 };\r
93 \r
94 \r
95 static const struct NyLPC_TJsonRpcClassDef* findFunction(const struct NyLPC_TJsonRpcClassDef** i_tbl, const NyLPC_TChar* i_method_path, NyLPC_TUInt8* o_function_idx);\r
96 static void putchar_params(NyLPC_TcJsonRpcParser_t* i_inst, char i_c);\r
97 static NyLPC_TUInt8 valTerminator2St(NyLPC_TChar i_c);\r
98 \r
99 \r
100 void NyLPC_cJsonRpcParser_initialize(\r
101         NyLPC_TcJsonRpcParser_t* i_inst,\r
102         const struct NyLPC_TJsonRpcClassDef** i_class_def)\r
103 {\r
104         i_inst->_class_def=i_class_def;\r
105 }\r
106 void NyLPC_cJsonRpcParser_initParser(NyLPC_TcJsonRpcParser_t* i_inst,union NyLPC_TJsonRpcParserResult* i_result)\r
107 {\r
108         i_inst->_result=i_result;\r
109         i_result->type=NyLPC_TJsonRpcParserResult_TYPE_UNKNOWN;\r
110         i_inst->_st = NyLPC_TcJsonRpcParser_ST_START;\r
111         i_inst->_pcounter = 0;\r
112         memset(i_result->raw.param_index, 0xff, NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX);\r
113 }\r
114 \r
115 \r
116 \r
117 static const struct NyLPC_TJsonRpcClassDef* findFunction(const struct NyLPC_TJsonRpcClassDef** i_tbl,const NyLPC_TChar* i_method_path,NyLPC_TUInt8* o_function_idx)\r
118 {\r
119         const NyLPC_TChar* ns;\r
120         const NyLPC_TChar* class_;\r
121         const NyLPC_TChar* method;\r
122         NyLPC_TUInt8 fidx;\r
123         int l;\r
124         //namespaceの抽出\r
125         ns=i_method_path;\r
126         class_=strchr(i_method_path,':');\r
127         if(class_==NULL){\r
128                 return NULL;\r
129         }\r
130         class_++;\r
131         //functionの抽出\r
132         method=strchr(class_,':');\r
133         if(method==NULL){\r
134                 return NULL;\r
135         }\r
136         method++;\r
137         while((*i_tbl)!=NULL){\r
138                 l=class_-ns-1;\r
139                 if(strncmp((*i_tbl)->names_pace,ns,l)!=0 || (*(ns+l))!=':'){\r
140                         i_tbl++;\r
141                         continue;\r
142                 }\r
143                 l=method-class_-1;\r
144                 if(strncmp((*i_tbl)->class_name,class_,l)!=0 || (*(class_+l))!=':'){\r
145                         i_tbl++;\r
146                         continue;\r
147                 }\r
148                 fidx=0;\r
149                 while(((*i_tbl)->functions+fidx)->name!=NULL){\r
150                         if(strcmp(((*i_tbl)->functions+fidx)->name,method)!=0){\r
151                                 fidx++;\r
152                                 continue;\r
153                         }\r
154                         *o_function_idx=fidx;\r
155                         return (*i_tbl);\r
156                 }\r
157                 break;\r
158         }\r
159         return NULL;\r
160 }\r
161 /**\r
162  * putchar_paramのステータス値\r
163  */\r
164 #define PARAM_ST_START                   1\r
165 #define PARAM_ST_VAL                     2\r
166 #define PARAM_ST_INT                     3\r
167 #define PARAM_ST_UINT                    4\r
168 #define PARAM_ST_STR                     5\r
169 #define PARAM_ST_STR_ESCAPE_HEX  6\r
170 #define PARAM_ST_STR_ESCAPE              7\r
171 #define PARAM_ST_BYTE                    8\r
172 #define PARAM_ST_BSTR                    9\r
173 #define PARAM_ST_NEXT                   11\r
174 \r
175 \r
176 /**\r
177  * シングルエスケープ文字列をエスケープされた文字列へ変換します。\r
178  */\r
179 static NyLPC_TBool convertSingleCharEscape(const char i_s, char* o_out)\r
180 {\r
181         switch (i_s){\r
182         case '0':       *o_out = '\0'; break;\r
183         case 'r':       *o_out = '\r'; break;\r
184         case 'n':       *o_out = '\n'; break;\r
185         case 't':       *o_out = '\t'; break;\r
186         case '\'':      *o_out = '\''; break;\r
187         case '\"':      *o_out = '\"'; break;\r
188         case '\\':      *o_out = '\\'; break;\r
189         default:\r
190                 return NyLPC_TBool_FALSE;\r
191         }\r
192         return NyLPC_TBool_TRUE;\r
193 }\r
194 /**\r
195  * 符号付整数値を構成する文字セットであるかを返します。\r
196  */\r
197 static NyLPC_TBool isSignedCharSet(const char i_c)\r
198 {\r
199         return (strchr("-0123456789", i_c) != NULL);\r
200 }\r
201 /**\r
202  * 整数を構成する文字セットであるかを返します。\r
203  */\r
204 #define isUnSignedCharSet(i_c) isdigit(i_c)\r
205 \r
206 static void putchar_params(NyLPC_TcJsonRpcParser_t* i_inst, char i_c)\r
207 {\r
208         switch (i_inst->_pst){\r
209         case PARAM_ST_START:\r
210                 if (i_c == '['){\r
211                         //パース開始\r
212                         i_inst->_work.str.n = 0;\r
213                         i_inst->_pst = PARAM_ST_VAL;\r
214                         return;\r
215                 }\r
216                 if (strchr(" ", i_c) != NULL){\r
217                         //無視\r
218                         return;\r
219                 }\r
220                 //エラー\r
221                 goto ERROR;\r
222         case PARAM_ST_VAL:\r
223                 if (i_inst->_pcounter >= NyLPC_TJsonRpcParserResult_NUMBER_OF_PARAM_INDEX){\r
224                         goto ERROR;\r
225                 }\r
226                 if (strchr(" ", i_c) != NULL){\r
227                         //無視\r
228                         return;\r
229                 }\r
230                 if (strchr("]", i_c) != NULL){\r
231                         i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT;\r
232                         i_inst->_pcounter = 0xff;\r
233                         return;\r
234                 }\r
235                 switch (i_inst->_result->method.class_def->functions[i_inst->_result->method.func_number].param_patt[i_inst->_pcounter]){\r
236                 case NyLPC_cJsonRpcParser_TYPE_INT32:\r
237                         if(!isSignedCharSet(i_c)){\r
238                                 goto ERROR;\r
239                         }\r
240                         i_inst->_pst = PARAM_ST_INT;\r
241                         i_inst->_work.int32.s = i_c == '-' ? -1 : 1;\r
242                         i_inst->_work.int32.v = i_c == '-' ? 0 : (i_c - '0');\r
243                         i_inst->_work.str.n = ((i_inst->_work.str.n + 3) / 4) * 4;\r
244                         break;\r
245                 case NyLPC_cJsonRpcParser_TYPE_UINT32:\r
246                         if (!isUnSignedCharSet(i_c)){\r
247                                 goto ERROR;\r
248                         }\r
249                         i_inst->_pst = PARAM_ST_UINT;\r
250                         i_inst->_work.uint32 = (i_c - '0');\r
251                         //開始位置を4バイト境界に\r
252                         i_inst->_work.str.n = ((i_inst->_work.str.n + 3) / 4) * 4;\r
253                         break;\r
254                 case NyLPC_cJsonRpcParser_TYPE_BYTE:\r
255                         if (!isUnSignedCharSet(i_c)){\r
256                                 goto ERROR;\r
257                         }\r
258                         i_inst->_pst = PARAM_ST_BYTE;\r
259                         i_inst->_work.uint32 = (i_c - '0');\r
260                         break;\r
261                 case NyLPC_cJsonRpcParser_TYPE_STRING:\r
262                         if (i_c != '"'){\r
263                                 goto ERROR;\r
264                         }\r
265                         i_inst->_result->method.param_index[i_inst->_pcounter] = i_inst->_work.str.n;\r
266                         i_inst->_pcounter++;\r
267                         if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
268                                 goto ERROR;\r
269                         }\r
270                         i_inst->_work.str.n++;//文字数の記憶領域\r
271                         i_inst->_pst = PARAM_ST_STR;\r
272                         return;//開始時に1バイト予約するから手順が違う\r
273                 case NyLPC_cJsonRpcParser_TYPE_BSTRING:\r
274                         if (i_c != '"'){\r
275                                 goto ERROR;\r
276                         }\r
277                         i_inst->_result->method.param_index[i_inst->_pcounter] = i_inst->_work.str.n;\r
278                         i_inst->_pcounter++;\r
279                         if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
280                                 goto ERROR;\r
281                         }\r
282                         i_inst->_work.str.n++;//文字数の記憶領域\r
283                         i_inst->_pst = PARAM_ST_BSTR;\r
284                         i_inst->_work.str.st = 0;\r
285                         return;//開始時に1バイト予約するから手順が違う\r
286                 default:\r
287                         goto ERROR;\r
288                 }\r
289                 i_inst->_result->method.param_index[i_inst->_pcounter] = i_inst->_work.str.n;\r
290                 i_inst->_pcounter++;\r
291                 return;\r
292         case PARAM_ST_STR_ESCAPE_HEX:\r
293                 //16進数構成文字のみ\r
294                 if (!isxdigit((int)i_c)){\r
295                         goto ERROR;\r
296                 }\r
297                 i_inst->_work.str.vt = (i_inst->_work.str.vt << 4) | NyLPC_ctox(i_c);\r
298                 i_inst->_work.str.st++;\r
299                 //2文字目で値を確定\r
300                 if (i_inst->_work.str.st>=2){\r
301                         if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
302                                 goto ERROR;\r
303                         }\r
304                         i_inst->_result->method.param_buf[i_inst->_work.str.n] = i_inst->_work.str.vt;\r
305                         i_inst->_work.str.n++;\r
306                         i_inst->_pst = PARAM_ST_STR;\r
307                 }\r
308                 return;\r
309         case PARAM_ST_STR_ESCAPE:\r
310                 if(i_c=='x'){\r
311                         i_inst->_pst = PARAM_ST_STR_ESCAPE_HEX;\r
312                         i_inst->_work.str.st = 0;\r
313                         i_inst->_work.str.vt = 0;\r
314                 }\r
315                 else{\r
316                         if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
317                                 goto ERROR;\r
318                         }\r
319                         if (!convertSingleCharEscape(i_c,&i_inst->_result->method.param_buf[i_inst->_work.str.n])){\r
320                                 goto ERROR;\r
321                         }\r
322                         i_inst->_work.str.n++;\r
323                         i_inst->_pst = PARAM_ST_STR;\r
324                 }\r
325                 return;\r
326         case PARAM_ST_STR:\r
327                 if (i_c == '"'){\r
328                         //完了\r
329                         if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
330                                 goto ERROR;\r
331                         }\r
332                         i_inst->_result->method.param_buf[i_inst->_work.str.n] = '\0';\r
333                         i_inst->_work.str.n++;\r
334                         //文字数を更新\r
335                         *((NyLPC_TUInt8*)(i_inst->_result->method.param_buf+i_inst->_result->method.param_index[i_inst->_pcounter - 1])) = i_inst->_work.str.n - i_inst->_result->method.param_index[i_inst->_pcounter - 1]-2;\r
336                         i_inst->_pst = PARAM_ST_NEXT;\r
337                         return;\r
338                 }\r
339                 else if (i_c=='\\'){\r
340                         i_inst->_pst = PARAM_ST_STR_ESCAPE;\r
341                 }\r
342                 else{\r
343                         if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
344                                 goto ERROR;\r
345                         }\r
346                         i_inst->_result->method.param_buf[i_inst->_work.str.n] = i_c;\r
347                         i_inst->_work.str.n++;\r
348                 }\r
349                 return;\r
350         case PARAM_ST_BSTR:\r
351                 if (i_c == '"'){\r
352                         if (i_inst->_work.str.st != 0){\r
353                                 goto ERROR;\r
354                         }\r
355                         //文字数を更新\r
356                         *((NyLPC_TUInt8*)(i_inst->_result->method.param_buf + i_inst->_result->method.param_index[i_inst->_pcounter - 1])) = i_inst->_work.str.n - i_inst->_result->method.param_index[i_inst->_pcounter - 1] - 1;\r
357                         i_inst->_pst = PARAM_ST_NEXT;\r
358                         return;\r
359                 }\r
360                 else{\r
361                         //16進数構成文字のみ\r
362                         if (!isxdigit((int)i_c)){\r
363                                 goto ERROR;\r
364                         }\r
365                         switch(i_inst->_work.str.st){\r
366                         case 0:\r
367                                 i_inst->_work.str.vt = NyLPC_ctox(i_c);\r
368                                 i_inst->_work.str.st++;\r
369                                 break;\r
370                         case 1:\r
371                                 i_inst->_work.str.vt = (i_inst->_work.str.vt << 4) | NyLPC_ctox(i_c);\r
372                                 if (i_inst->_work.str.n >= NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
373                                         goto ERROR;\r
374                                 }\r
375                                 i_inst->_result->method.param_buf[i_inst->_work.str.n] = i_inst->_work.str.vt;\r
376                                 i_inst->_work.str.n++;\r
377                                 i_inst->_work.str.st = 0;\r
378                                 break;\r
379                         }\r
380                 }\r
381                 return;\r
382         case PARAM_ST_INT:\r
383                 if (isUnSignedCharSet(i_c)){\r
384                         i_inst->_work.int32.v = i_inst->_work.int32.v * 10 + (i_c - '0');\r
385                         return;\r
386                 }\r
387                 switch (i_c){\r
388                 case ' ':\r
389                         i_inst->_pst = PARAM_ST_NEXT; break;\r
390                 case ',':\r
391                         i_inst->_pst = PARAM_ST_VAL; break;\r
392                 case ']':\r
393                         i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
394                 default:\r
395                         goto ERROR;\r
396                 }\r
397                 //4バイト境界に揃える\r
398                 i_inst->_work.str.n += 4;\r
399                 if (i_inst->_work.str.n > NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
400                         goto ERROR;\r
401                 }\r
402                 *((NyLPC_TInt32*)&(i_inst->_result->method.param_buf[i_inst->_work.str.n - 4])) = i_inst->_work.int32.v*i_inst->_work.int32.s;\r
403                 return;\r
404         case PARAM_ST_UINT:\r
405                 if (isUnSignedCharSet(i_c)){\r
406                         i_inst->_work.uint32 = i_inst->_work.uint32 * 10 + (i_c - '0');\r
407                         return;\r
408                 }\r
409                 switch (i_c){\r
410                 case ' ':\r
411                         i_inst->_pst = PARAM_ST_NEXT; break;\r
412                 case ',':\r
413                         i_inst->_pst = PARAM_ST_VAL; break;\r
414                 case ']':\r
415                         i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
416                 default:\r
417                         goto ERROR;\r
418                 }\r
419                 i_inst->_work.str.n += 4;\r
420                 if (i_inst->_work.str.n > NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
421                         goto ERROR;\r
422                 }\r
423                 *((NyLPC_TUInt32*)&(i_inst->_result->method.param_buf[i_inst->_work.str.n - 4])) = i_inst->_work.uint32;\r
424                 return;\r
425         case PARAM_ST_BYTE:\r
426                 if (isUnSignedCharSet(i_c)){\r
427                         i_inst->_work.uint32 = i_inst->_work.uint32 * 10 + (i_c - '0');\r
428                         return;\r
429                 }\r
430                 switch (i_c){\r
431                 case ' ':\r
432                         i_inst->_pst = PARAM_ST_NEXT; break;\r
433                 case ',':\r
434                         i_inst->_pst = PARAM_ST_VAL; break;\r
435                 case ']':\r
436                         i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
437                 default:\r
438                         goto ERROR;\r
439                 }\r
440                 i_inst->_work.str.n ++;\r
441                 if (i_inst->_work.str.n > NyLPC_TJsonRpcParserResult_PARAM_BUF){\r
442                         goto ERROR;\r
443                 }\r
444                 *((NyLPC_TUInt8*)&(i_inst->_result->method.param_buf[i_inst->_work.str.n - 1])) = (NyLPC_TUInt8)(i_inst->_work.uint32&0xff);\r
445                 return;\r
446         case PARAM_ST_NEXT:\r
447                 switch (i_c){\r
448                 case ' ':break;\r
449                 case ',':\r
450                         i_inst->_pst = PARAM_ST_VAL; break;\r
451                 case ']':\r
452                         i_inst->_st = NyLPC_TcJsonRpcParser_ST_NEXT; break;\r
453                 default:\r
454                         goto ERROR;\r
455                 }\r
456                 return;\r
457         }\r
458 ERROR:\r
459         i_inst->_st = NyLPC_TcJsonRpcParser_ST_ERROR;\r
460         return;\r
461 }\r
462 \r
463 \r
464 /**\r
465 * NyLPC_cJsonRpcParser_putCharのサブ関数\r
466 */\r
467 static NyLPC_TUInt8 valTerminator2St(NyLPC_TChar i_c)\r
468 {\r
469         switch (i_c){\r
470         case ' ':\r
471                 return NyLPC_TcJsonRpcParser_ST_NEXT;\r
472         case '}':\r
473                 return NyLPC_TcJsonRpcParser_ST_END;\r
474         case ',':\r
475                 return NyLPC_TcJsonRpcParser_ST_NAME_Q;\r
476         default:\r
477                 //ないはず\r
478                 return NyLPC_TcJsonRpcParser_ST_ERROR;\r
479         }\r
480 }\r
481 \r
482 /** 文字列をパーサに入力してパーサの状態を遷移させます。\r
483 \r
484 */\r
485 void NyLPC_cJsonRpcParser_putChar(NyLPC_TcJsonRpcParser_t* i_inst,char i_c)\r
486 {\r
487         switch(i_inst->_st){\r
488         case NyLPC_TcJsonRpcParser_ST_PARAMS:\r
489                 putchar_params(i_inst,i_c);\r
490                 return;\r
491         case NyLPC_TcJsonRpcParser_ST_START:\r
492                 if(i_c=='{'){\r
493                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_NAME_Q;\r
494                         return;\r
495                 }\r
496                 if(strchr(" ",i_c)!=NULL){\r
497                         //無視\r
498                         return;\r
499                 }\r
500                 //エラー\r
501                 goto ERROR;\r
502         case NyLPC_TcJsonRpcParser_ST_NAME_Q:\r
503                 if(i_c=='"'){\r
504                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_NAME_STR;\r
505                         i_inst->_work.str.n=0;\r
506                         return;\r
507                 }\r
508                 if(strchr(" ",i_c)!=NULL){\r
509                         //無視\r
510                         return;\r
511                 }\r
512                 //エラー\r
513                 goto ERROR;\r
514         case NyLPC_TcJsonRpcParser_ST_NAME_STR:\r
515                 if(i_c=='"'){\r
516                         //完了\r
517                         i_inst->_work.str.buf[i_inst->_work.str.n]='\0';\r
518                         //メソッドIDを記録\r
519                         i_inst->_name_id=NyLPC_TTextIdTbl_getMatchId(i_inst->_work.str.buf,method_name_tbl);\r
520                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_NV_SEP;\r
521                         switch(i_inst->_name_id){\r
522                         case NAME_ID_METHOD:\r
523                         case NAME_ID_RESULT:\r
524                                 if(i_inst->_result->type!=NyLPC_TJsonRpcParserResult_TYPE_UNKNOWN){\r
525                                         goto ERROR;\r
526                                 }\r
527                                 break;\r
528                         case NAME_ID_PARAMS:\r
529                                 if (i_inst->_pcounter != 0){\r
530                                         goto ERROR;\r
531                                 }\r
532                                 break;\r
533                         default:\r
534                                 break;\r
535                         }\r
536                         return;\r
537                 }\r
538                 i_inst->_work.str.n++;\r
539                 if(i_inst->_work.str.n>=NyLPC_TcJsonRpcParser_WORK_MAX){\r
540                         //文字列長すぎでござる。\r
541                         goto ERROR;\r
542                 }\r
543                 i_inst->_work.str.buf[i_inst->_work.str.n-1]=i_c;\r
544                 return;\r
545         case NyLPC_TcJsonRpcParser_ST_NV_SEP:\r
546                 if(i_c==':'){\r
547                         if (i_inst->_name_id == NAME_ID_PARAMS){\r
548                                 i_inst->_pst = PARAM_ST_START;\r
549                                 i_inst->_st = NyLPC_TcJsonRpcParser_ST_PARAMS;\r
550                         }\r
551                         else{\r
552                                 i_inst->_st = NyLPC_TcJsonRpcParser_ST_VAL;\r
553                                 i_inst->_work.str.n = 0;\r
554                         }\r
555                         return;\r
556                 }\r
557                 if(strchr(" ",i_c)!=NULL){\r
558                         //無視\r
559                         return;\r
560                 }\r
561                 //エラー\r
562                 goto ERROR;\r
563         case NyLPC_TcJsonRpcParser_ST_VAL:\r
564                 if(i_c=='"'){\r
565                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_VAL_STR;\r
566                         i_inst->_work.str.n=0;\r
567                         return;\r
568                 }\r
569                 if(strchr(" ",i_c)!=NULL){\r
570                         //無視\r
571                         return;\r
572                 }\r
573                 if (isUnSignedCharSet(i_c)){\r
574                         i_inst->_work.uint32 = (i_c - '0');\r
575                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_VAL_UINT;\r
576                         return;\r
577                 }\r
578                 //エラー\r
579                 goto ERROR;\r
580         case NyLPC_TcJsonRpcParser_ST_VAL_UINT:\r
581                 if (isUnSignedCharSet(i_c)){\r
582                         i_inst->_work.uint32 = i_inst->_work.uint32 * 10 + (i_c - '0');\r
583                         return;\r
584                 }\r
585                 if(strchr(" ,}",i_c)!=NULL){\r
586                         //確定\r
587                         switch(i_inst->_name_id){\r
588                         case NAME_ID_ID:\r
589                                 i_inst->_result->method.id=i_inst->_work.uint32;\r
590                                 break;\r
591                         case NAME_ID_UNKNOWN:\r
592                                 //知らないIDは無視\r
593                                 break;\r
594                         default:\r
595                                 //数値を受け入れないパラメータ\r
596                                 goto ERROR;\r
597                         }\r
598                         i_inst->_st=valTerminator2St(i_c);\r
599                         return;\r
600                 }\r
601                 goto ERROR;\r
602         case NyLPC_TcJsonRpcParser_ST_VAL_STR:\r
603                 if(i_c=='"'){\r
604                         i_inst->_work.str.buf[i_inst->_work.str.n]='\0';\r
605                         //確定\r
606                         switch(i_inst->_name_id){\r
607                         case NAME_ID_VERSION:\r
608                                 if(strcmp(i_inst->_work.str.buf,"2.0")!=0){\r
609                                         goto ERROR;\r
610                                 }\r
611                                 break;\r
612                         case NAME_ID_METHOD:\r
613                                 i_inst->_result->method._type=NyLPC_TJsonRpcParserResult_TYPE_METHOD;\r
614                                 i_inst->_result->method.class_def=findFunction(i_inst->_class_def,i_inst->_work.str.buf,&(i_inst->_result->method.func_number));\r
615                                 if(i_inst->_result->method.class_def==NULL){\r
616                                         goto ERROR;\r
617                                 }\r
618                                 break;\r
619                         case NAME_ID_UNKNOWN:\r
620                                 //知らないIDは無視\r
621                                 break;\r
622                         default:\r
623                                 //文字列を受け入れないパラメータ\r
624                                 goto ERROR;\r
625                         }\r
626                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_NEXT;\r
627                         return;\r
628                 }\r
629                 i_inst->_work.str.n++;\r
630                 if(i_inst->_work.str.n>=NyLPC_TcJsonRpcParser_WORK_MAX){\r
631                         //文字列長すぎでござる。\r
632                         goto ERROR;\r
633                 }\r
634                 i_inst->_work.str.buf[i_inst->_work.str.n-1]=i_c;\r
635                 return;\r
636         case NyLPC_TcJsonRpcParser_ST_NEXT:\r
637                 if(i_c==','){\r
638                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_NAME_Q;\r
639                 }else if(i_c=='}'){\r
640                         i_inst->_st=NyLPC_TcJsonRpcParser_ST_END;\r
641                 }else if(strchr(" ",i_c)!=NULL){\r
642                         //nothing to do\r
643                 }else{\r
644                         goto ERROR;\r
645                 }\r
646                 return;\r
647         default:\r
648                 goto ERROR;\r
649         }\r
650 ERROR:\r
651         i_inst->_st = NyLPC_TcJsonRpcParser_ST_ERROR;\r
652         return;\r
653 }\r
654 \r
655 #define COMMENT_DEBUG\r
656 #ifndef COMMENT_DEBUG\r
657 \r
658 const struct NyLPC_TJsonRpcMethodDef test_method[]=\r
659 {\r
660         { "func" , ""},\r
661         { "func1", "d" },\r
662         { "func2", "dd" },\r
663         { "func3", "u" },\r
664         { "func4", "uu" },\r
665         { "func5", "uss" },\r
666         { "func5", "uss" },\r
667         { "func6", "s" },\r
668         { "func7", "sd" },\r
669         { "func8", "su" },\r
670         { "func9", "ss" },\r
671         { "f10", "suu" },\r
672         { "f11", "bbbb" },\r
673         { "f12", "usu" },\r
674         { "f13", "uBu" },\r
675         { NULL, "" }\r
676 };\r
677 \r
678 const struct NyLPC_TJsonRpcClassDef test_def=\r
679 {\r
680         "ns","class",\r
681         test_method\r
682 };\r
683 \r
684 /**\r
685  * テスト用のアレイ\r
686  */\r
687 const struct NyLPC_TJsonRpcClassDef* test_def_array[]=\r
688 {\r
689         &test_def,\r
690         NULL\r
691 };\r
692 \r
693 void NyLPC_cJsonRpcParser_putText(NyLPC_TcJsonRpcParser_t* i_inst, const NyLPC_TChar* i_text,NyLPC_TUInt16 i_size)\r
694 {\r
695         NyLPC_TUInt16 i;\r
696         NyLPC_TUInt32 u32;\r
697         NyLPC_TInt32 i32;\r
698         NyLPC_TChar* c;\r
699         NyLPC_TUInt8 u8,l8;\r
700 \r
701 \r
702         for (i = 0; i < i_size; i++){\r
703                 NyLPC_cJsonRpcParser_putChar(i_inst,i_text[i]);\r
704                 if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_ERROR){\r
705                         break;\r
706                 }\r
707                 else if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_END){\r
708                         break;\r
709                 }\r
710         }\r
711         if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_ERROR){\r
712                 printf("ERROR!\n");\r
713         }\r
714         else if (i_inst->_st == NyLPC_TcJsonRpcParser_ST_END){\r
715                 printf("OK!\n");\r
716                 for (int i = 0; i_inst->_result->method.param_index[i] != 0xff && i<i_inst->_pcounter; i++){\r
717                         switch (i_inst->_result->method.class_def->functions[i_inst->_result->method.func_number].param_patt[i]){\r
718                         case 'u':NyLPC_TJsonRpcParserResult_getUInt32(i_inst->_result,i, &u32); printf("%u,", u32); break;\r
719                         case 'd':NyLPC_TJsonRpcParserResult_getInt32(i_inst->_result, i, &i32); printf("%d,", i32); break;\r
720                         case 's':NyLPC_TJsonRpcParserResult_getStr(i_inst->_result, i, &c, &l8); printf("%s:%d,", c, l8); break;\r
721                         case 'B':NyLPC_TJsonRpcParserResult_getByteArray(i_inst->_result, i, &c, &l8); printf("--:%d,", l8); break;\r
722                         case 'b':NyLPC_TJsonRpcParserResult_getByte(i_inst->_result, i, &u8); printf("%u,", u8); break;\r
723                         }\r
724                 }\r
725                 printf("\n");\r
726         }\r
727         else{\r
728                 printf("CONTINUE...\n");\r
729         }\r
730 }\r
731 \r
732 void main(void)\r
733 {\r
734         NyLPC_TcJsonRpcParser_t inst;\r
735         union NyLPC_TJsonRpcParserResult ret;\r
736 \r
737 //JSONCORE\r
738 //#define JSONCORE 1\r
739 #ifdef JSONCORE\r
740         const char* t[] = {\r
741                 "{\"0123\"\"2.0\"}",//NO\r
742                 "{\"01234567890123456789\":\"2.0\"}",//NO\r
743                 "{\"0123\":\"01234567890123456789\"}",//NO\r
744                 "{\"version\":\"2.0\"}",//YES\r
745                 "{\"version\":\"2.1\"}",//NO\r
746                 " {  \"version\"  :  \"2.0\"  }",//YES\r
747                 "{\"version\":\"2.0\",}",//NO\r
748                 "{\"version\":\"2.0\" \"test\":\"t\"}",//NO\r
749                 "{\"version\":\"2.0\",\"method\":}",//NO\r
750                 "{\"version\":\"2.0\",\"method\":\"ns:class:func\"}",//YES\r
751                 "{\"version\":\"2.0\",\"method\":\"ns2:class:func\"}",//NO\r
752                 "{\"version\":\"2.0\",\"method\":\"ns:class2:func\"}",//NO\r
753                 "{\"version\":\"2.0\",\"method\":\"ns:class:func2\"}",//NO\r
754                 "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"method\":\"\"}",//NO\r
755                 "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"id\":0}",//YES\r
756                 "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"id\":\"123\"}",//YES\r
757                 "{\"version\":\"2.0\",\"method\":123}",//NO\r
758                 "{\"version\":\"2.0\",\"test\":123}",//YES\r
759                 "{\"version\":\"2.0\",\"test\":123, \"test\":123 }",//YES\r
760                 "{\"version\":\"2.0\",\"test\":123 ,\"test\":123 }",//YES\r
761                 NULL\r
762         };\r
763 #else\r
764         const char* t[] = {\r
765 /*              "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"params\":[]}",//YES\r
766                 "{\"version\":\"2.0\",\"method\":\"ns:class:func\",\"params\": [] }",//YES\r
767                 "{\"version\":\"2.0\",\"method\":\"ns:class:func1\",\"params\": [-123] }",//YES\r
768                 "{\"version\":\"2.0\",\"method\":\"ns:class:func1\",\"params\": [\"123\"] }",//NG\r
769                 "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 1 , 456 ] }",//YES\r
770                 "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 123 , 456 a] }",//NG\r
771                 "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 123a] }",//NG\r
772                 "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [ 123,456] }",//OK\r
773                 "{\"version\":\"2.0\",\"method\":\"ns:class:func2\",\"params\": [123,456] }",//YES\r
774                 "{\"version\":\"2.0\",\"method\":\"ns:class:func3\",\"params\": [123] }",//YES\r
775                 "{\"version\":\"2.0\",\"method\":\"ns:class:func3\",\"params\": [\"123\"] }",//NG\r
776                 "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123 , 456 ] }",//YES\r
777                 "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123 , 456 a] }",//NG\r
778                 "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123a] }",//NG\r
779                 "{\"version\":\"2.0\",\"method\":\"ns:class:func4\",\"params\": [ 123,456] }",//OK\r
780                 "{\"version\":\"2.0\",\"method\":\"ns:class:func5\",\"params\": [123, \"abc\" , \"abc\"] }",//OK\r
781                 "{\"version\":\"2.0\",\"method\":\"ns:class:func6\",\"params\": [\"01234567890123456789012\"] }",//OK\r
782                 "{\"version\":\"2.0\",\"method\":\"ns:class:func6\",\"params\": [1] }",//NG\r
783                 "{\"version\":\"2.0\",\"method\":\"ns:class:func8\",\"params\": [\"012345678901234567\",1,1] }",//OK\r
784                 "{\"version\":\"2.0\",\"method\":\"ns:class:func8\",\"params\": [\"012345678901234567\",1] }",//OK\r
785                 "{\"version\":\"2.0\",\"method\":\"ns:class:func7\",\"params\": [\"012345678901234567\",1] }",//OK\r
786                 "{\"version\":\"2.0\",\"method\":\"ns:class:f10\",\"params\": [\"01234567890123\",22,33] }",//OK\r
787                 "{\"version\":\"2.0\",\"method\":\"ns:class:f11\",\"params\": [ 0 , 1 ,2,3] }",//OK\r
788                 "{\"version\":\"2.0\",\"method\":\"ns:class:f11\",\"params\": [ 15 , 1 ,2,3a] }",//NG\r
789 */\r
790                 "{\"version\":\"2.0\",\"method\":\"ns:class:f13\",\"params\": [2,\"0011223344ff\",1] }",//NG\r
791 //              "{\"version\":\"2.0\",\"method\":\"ns:class:f12\",\"params\": [2,\"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\",1] }",//NG\r
792                 NULL\r
793         };\r
794 #endif\r
795         int i;\r
796 \r
797         for (i = 0;t[i]!=NULL; i++){\r
798                 NyLPC_cJsonRpcParser_initialize(&inst, test_def_array);\r
799                 NyLPC_cJsonRpcParser_initParser(&inst, &ret);\r
800                 NyLPC_cJsonRpcParser_putText(&inst, t[i], strlen(t[i]));\r
801                 continue;\r
802         }\r
803         printf("end\n");\r
804         return;\r
805 \r
806 }\r
807 #endif\r
808 \r