754fdd6430b99dbb9d8142e221d66034f24db82c
[ric-plt/resource-status-manager.git] / RSM / asn1codec / e2ap_engine / xer_support.c
1
2 /*
3  * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com.
4  * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
5  *      All rights reserved.
6  * Redistribution and modifications are permitted subject to BSD license.
7  */
8 #include <asn_system.h>
9 #include <xer_support.h>
10
11 /* Parser states */
12 typedef enum {
13         ST_TEXT,
14         ST_TAG_START,
15         ST_TAG_BODY,
16         ST_TAG_QUOTE_WAIT,
17         ST_TAG_QUOTED_STRING,
18         ST_TAG_UNQUOTED_STRING,
19         ST_COMMENT_WAIT_DASH1,  /* "<!--"[1] */
20         ST_COMMENT_WAIT_DASH2,  /* "<!--"[2] */
21         ST_COMMENT,
22         ST_COMMENT_CLO_DASH2,   /* "-->"[0] */
23         ST_COMMENT_CLO_RT       /* "-->"[1] */
24 } pstate_e;
25
26 static const int
27 _charclass[256] = {
28         0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0,
29         0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
30         1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
31         2,2,2,2,2,2,2,2, 2,2,0,0,0,0,0,0,       /* 01234567 89       */
32         0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,       /*  ABCDEFG HIJKLMNO */
33         3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0,       /* PQRSTUVW XYZ      */
34         0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,       /*  abcdefg hijklmno */
35         3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0        /* pqrstuvw xyz      */
36 };
37 #define WHITESPACE(c)   (_charclass[(unsigned char)(c)] == 1)
38 #define ALNUM(c)        (_charclass[(unsigned char)(c)] >= 2)
39 #define ALPHA(c)        (_charclass[(unsigned char)(c)] == 3)
40
41 /* Aliases for characters, ASCII/UTF-8 */
42 #define EXCLAM  0x21    /* '!' */
43 #define CQUOTE  0x22    /* '"' */
44 #define CDASH   0x2d    /* '-' */
45 #define CSLASH  0x2f    /* '/' */
46 #define LANGLE  0x3c    /* '<' */
47 #define CEQUAL  0x3d    /* '=' */
48 #define RANGLE  0x3e    /* '>' */
49 #define CQUEST  0x3f    /* '?' */
50
51 /* Invoke token callback */
52 #define TOKEN_CB_CALL(type, _ns, _current_too, _final) do {     \
53                 int _ret;                                       \
54                 pstate_e ns  = _ns;                             \
55                 ssize_t _sz = (p - chunk_start) + _current_too; \
56                 if (!_sz) {                                     \
57                         /* Shortcut */                          \
58                         state = _ns;                            \
59                         break;                                  \
60                 }                                               \
61                 _ret = cb(type, chunk_start, _sz, key);         \
62                 if(_ret < _sz) {                                \
63                         if(_current_too && _ret == -1)          \
64                                 state = ns;                     \
65                         goto finish;                            \
66                 }                                               \
67                 chunk_start = p + _current_too;                 \
68                 state = ns;                                     \
69         } while(0)
70
71 #define TOKEN_CB(_type, _ns, _current_too)                      \
72         TOKEN_CB_CALL(_type, _ns, _current_too, 0)
73
74 #define PXML_TAG_FINAL_CHUNK_TYPE      PXML_TAG_END
75 #define PXML_COMMENT_FINAL_CHUNK_TYPE  PXML_COMMENT_END
76
77 #define TOKEN_CB_FINAL(_type, _ns, _current_too)                \
78         TOKEN_CB_CALL( _type ## _FINAL_CHUNK_TYPE , _ns, _current_too, 1)
79
80 /*
81  * Parser itself
82  */
83 ssize_t pxml_parse(int *stateContext, const void *xmlbuf, size_t size, pxml_callback_f *cb, void *key) {
84         pstate_e state = (pstate_e)*stateContext;
85         const char *chunk_start = (const char *)xmlbuf;
86         const char *p = chunk_start;
87         const char *end = p + size;
88
89         for(; p < end; p++) {
90           int C = *(const unsigned char *)p;
91           switch(state) {
92           case ST_TEXT:
93                 /*
94                  * Initial state: we're in the middle of some text,
95                  * or just have started.
96                  */
97                 if (C == LANGLE) 
98                         /* We're now in the tag, probably */
99                         TOKEN_CB(PXML_TEXT, ST_TAG_START, 0);
100                 break;
101           case ST_TAG_START:
102                 if (ALPHA(C) || (C == CSLASH))
103                         state = ST_TAG_BODY;
104                 else if (C == EXCLAM)
105                         state = ST_COMMENT_WAIT_DASH1;
106                 else 
107                         /*
108                          * Not characters and not whitespace.
109                          * Must be something like "3 < 4".
110                          */
111                         TOKEN_CB(PXML_TEXT, ST_TEXT, 1);/* Flush as data */
112                 break;
113           case ST_TAG_BODY:
114                 switch(C) {
115                 case RANGLE:
116                         /* End of the tag */
117                         TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
118                         break;
119                 case LANGLE:
120                         /*
121                          * The previous tag wasn't completed, but still
122                          * recognized as valid. (Mozilla-compatible)
123                          */
124                         TOKEN_CB_FINAL(PXML_TAG, ST_TAG_START, 0);      
125                         break;
126                 case CEQUAL:
127                         state = ST_TAG_QUOTE_WAIT;
128                         break;
129                 }
130                 break;
131           case ST_TAG_QUOTE_WAIT:
132                 /*
133                  * State after the equal sign ("=") in the tag.
134                  */
135                 switch(C) {
136                 case CQUOTE:
137                         state = ST_TAG_QUOTED_STRING;
138                         break;
139                 case RANGLE:
140                         /* End of the tag */
141                         TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
142                         break;
143                 default:
144                         if(!WHITESPACE(C))
145                                 /* Unquoted string value */
146                                 state = ST_TAG_UNQUOTED_STRING;
147                 }
148                 break;
149           case ST_TAG_QUOTED_STRING:
150                 /*
151                  * Tag attribute's string value in quotes.
152                  */
153                 if(C == CQUOTE) {
154                         /* Return back to the tag state */
155                         state = ST_TAG_BODY;
156                 }
157                 break;
158           case ST_TAG_UNQUOTED_STRING:
159                 if(C == RANGLE) {
160                         /* End of the tag */
161                         TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1);
162                 } else if(WHITESPACE(C)) {
163                         /* Return back to the tag state */
164                         state = ST_TAG_BODY;
165                 }
166                 break;
167           case ST_COMMENT_WAIT_DASH1:
168                 if(C == CDASH) {
169                         state = ST_COMMENT_WAIT_DASH2;
170                 } else {
171                         /* Some ordinary tag. */
172                         state = ST_TAG_BODY;
173                 }
174                 break;
175           case ST_COMMENT_WAIT_DASH2:
176                 if(C == CDASH) {
177                         /* Seen "<--" */
178                         state = ST_COMMENT;
179                 } else {
180                         /* Some ordinary tag */
181                         state = ST_TAG_BODY;
182                 }
183                 break;
184           case ST_COMMENT:
185                 if(C == CDASH) {
186                         state = ST_COMMENT_CLO_DASH2;
187                 }
188                 break;
189           case ST_COMMENT_CLO_DASH2:
190                 if(C == CDASH) {
191                         state = ST_COMMENT_CLO_RT;
192                 } else {
193                         /* This is not an end of a comment */
194                         state = ST_COMMENT;
195                 }
196                 break;
197           case ST_COMMENT_CLO_RT:
198                 if(C == RANGLE) {
199                         TOKEN_CB_FINAL(PXML_COMMENT, ST_TEXT, 1);
200                 } else if(C == CDASH) {
201                         /* Maintain current state, still waiting for '>' */
202                 } else {
203                         state = ST_COMMENT;
204                 }
205                 break;
206           } /* switch(*ptr) */
207         } /* for() */
208
209         /*
210          * Flush the partially processed chunk, state permitting.
211          */
212         if(p - chunk_start) {
213                 switch (state) {
214                 case ST_COMMENT:
215                         TOKEN_CB(PXML_COMMENT, state, 0);
216                         break;
217                 case ST_TEXT:
218                         TOKEN_CB(PXML_TEXT, state, 0);
219                         break;
220                 default: break; /* a no-op */
221                 }
222         }
223
224 finish:
225         *stateContext = (int)state;
226         return chunk_start - (const char *)xmlbuf;
227 }
228