xref: /aosp_15_r20/external/fastrpc/inc/sbuf_parser.h (revision 418b791d679beb2078b579a3b6936cf330c41799)
1*418b791dSBob Badour /**
2*418b791dSBob Badour  * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3*418b791dSBob Badour  *
4*418b791dSBob Badour  * Redistribution and use in source and binary forms, with or without
5*418b791dSBob Badour  * modification, are permitted provided that the following conditions are
6*418b791dSBob Badour  * met:
7*418b791dSBob Badour  *    * Redistributions of source code must retain the above copyright
8*418b791dSBob Badour  *      notice, this list of conditions and the following disclaimer.
9*418b791dSBob Badour  *    * Redistributions in binary form must reproduce the above
10*418b791dSBob Badour  *      copyright notice, this list of conditions and the following
11*418b791dSBob Badour  *      disclaimer in the documentation and/or other materials provided
12*418b791dSBob Badour  *      with the distribution.
13*418b791dSBob Badour  *    * Neither the name of The Linux Foundation nor the names of its
14*418b791dSBob Badour  *      contributors may be used to endorse or promote products derived
15*418b791dSBob Badour  *      from this software without specific prior written permission.
16*418b791dSBob Badour  *
17*418b791dSBob Badour  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18*418b791dSBob Badour  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*418b791dSBob Badour  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20*418b791dSBob Badour  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21*418b791dSBob Badour  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*418b791dSBob Badour  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*418b791dSBob Badour  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24*418b791dSBob Badour  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25*418b791dSBob Badour  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26*418b791dSBob Badour  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*418b791dSBob Badour  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*418b791dSBob Badour  */
29*418b791dSBob Badour 
30*418b791dSBob Badour #ifndef SBUF_PARSER_H
31*418b791dSBob Badour #define SBUF_PARSER_H
32*418b791dSBob Badour 
33*418b791dSBob Badour #include "sbuf.h"
34*418b791dSBob Badour 
35*418b791dSBob Badour /**
36*418b791dSBob Badour  * Greedy Recursive Descent Parser in C
37*418b791dSBob Badour  *
38*418b791dSBob Badour  * Stop using strstr or regular expressions.  This simple Recursive Descent Parser can be
39*418b791dSBob Badour  * used to handle complex grammars.
40*418b791dSBob Badour  *
41*418b791dSBob Badour  * For example:
42*418b791dSBob Badour  *   parsing a query string form a uri
43*418b791dSBob Badour  *   input: "file:///foo/bar_far.so.1?_blah1&_bar=barval5&_barfar"
44*418b791dSBob Badour  *   expected output:
45*418b791dSBob Badour  *      parsed query: _blah1 =
46*418b791dSBob Badour  *      parsed query: _bar = barval5
47*418b791dSBob Badour  *      parsed query: _barfar =
48*418b791dSBob Badour  *
49*418b791dSBob Badour  *   static int qmark(struct sbuf *buf) {
50*418b791dSBob Badour  *      return sbuf_char(buf, '?');
51*418b791dSBob Badour  *   }
52*418b791dSBob Badour  *   static int notandoreq(struct sbuf *buf) {
53*418b791dSBob Badour  *      return sbuf_notchars(buf, "&=");
54*418b791dSBob Badour  *   }
55*418b791dSBob Badour  *   static int notand(struct sbuf *buf) {
56*418b791dSBob Badour  *      return sbuf_notchar(buf, '&');
57*418b791dSBob Badour  *   }
58*418b791dSBob Badour  *
59*418b791dSBob Badour  *   const char *name;
60*418b791dSBob Badour  *   int nameLen;
61*418b791dSBob Badour  *   const char *value;
62*418b791dSBob Badour  *   int valueLen;
63*418b791dSBob Badour  *   const char *data = "file:///foo/bar_far.so.1?_blah1&_bar=barval5&_barfar";
64*418b791dSBob Badour  *
65*418b791dSBob Badour  *   //initialize
66*418b791dSBob Badour  *   sbuf_parser_init(&buf, data, strlen(data));
67*418b791dSBob Badour  *
68*418b791dSBob Badour  *   //parse until question mark
69*418b791dSBob Badour  *   assert(sbuf_until(&buf, sbuf_any, qmark));
70*418b791dSBob Badour  *
71*418b791dSBob Badour  *   //parse each query
72*418b791dSBob Badour  *   while(!sbuf_end(&buf)) {
73*418b791dSBob Badour  *      //record where the name starts
74*418b791dSBob Badour  *      name = sbuf_cur(&buf);
75*418b791dSBob Badour  *
76*418b791dSBob Badour  *      //name is valid until '=' or '&'
77*418b791dSBob Badour  *      assert(sbuf_many1(&buf, notandoreq));
78*418b791dSBob Badour  *      nameLen = sbuf_cur(&buf) - name;
79*418b791dSBob Badour  *
80*418b791dSBob Badour  *      value = 0;
81*418b791dSBob Badour  *      valueLen = 0;
82*418b791dSBob Badour  *      //if the next char is a '=' then we also get a value
83*418b791dSBob Badour  *      if(sbuf_char(&buf, '=')) {
84*418b791dSBob Badour  *         value = sbuf_cur(&buf);
85*418b791dSBob Badour  *
86*418b791dSBob Badour  *         //value is until the next query that starts with '&'
87*418b791dSBob Badour  *         assert(sbuf_many1(&buf, notand));
88*418b791dSBob Badour  *         valueLen = sbuf_cur(&buf) - value;
89*418b791dSBob Badour  *      }
90*418b791dSBob Badour  *      //expect '&' or end
91*418b791dSBob Badour  *      sbuf_char(&buf, '&');
92*418b791dSBob Badour  *      printf("parsed query: %.*s = %.*s\n", nameLen, name, valueLen, value);
93*418b791dSBob Badour  *   }
94*418b791dSBob Badour  *
95*418b791dSBob Badour  */
96*418b791dSBob Badour 
97*418b791dSBob Badour //! init
sbuf_parser_init(struct sbuf * buf,const char * data,int dataLen)98*418b791dSBob Badour static __inline void sbuf_parser_init(struct sbuf* buf, const char *data, int dataLen) {
99*418b791dSBob Badour    sbuf_init(buf, 0, (void*)data, dataLen);
100*418b791dSBob Badour }
101*418b791dSBob Badour 
102*418b791dSBob Badour //! current postiion
sbuf_cur(struct sbuf * buf)103*418b791dSBob Badour static __inline char *sbuf_cur(struct sbuf* buf) {
104*418b791dSBob Badour    return (char*)sbuf_head(buf);
105*418b791dSBob Badour }
106*418b791dSBob Badour 
107*418b791dSBob Badour //! look at the next character if the buffer is still valid
sbuf_peek(struct sbuf * buf,char * c)108*418b791dSBob Badour static __inline int sbuf_peek(struct sbuf* buf, char* c) {
109*418b791dSBob Badour    if(!sbuf_valid(buf)) {
110*418b791dSBob Badour       return 0;
111*418b791dSBob Badour    }
112*418b791dSBob Badour    *c = *sbuf_cur(buf);
113*418b791dSBob Badour    return 1;
114*418b791dSBob Badour }
115*418b791dSBob Badour 
116*418b791dSBob Badour //! returns true if the buffer is ended
sbuf_end(struct sbuf * buf)117*418b791dSBob Badour static __inline int sbuf_end(struct sbuf* buf) {
118*418b791dSBob Badour    return sbuf_left(buf) == 0;
119*418b791dSBob Badour }
120*418b791dSBob Badour 
121*418b791dSBob Badour //! consume 1 char if its in string chars
sbuf_chars(struct sbuf * buf,const char * chars)122*418b791dSBob Badour static __inline int sbuf_chars(struct sbuf *buf, const char *chars) {
123*418b791dSBob Badour    int i = 0;
124*418b791dSBob Badour    char c;
125*418b791dSBob Badour    if(!sbuf_peek(buf, &c)) {
126*418b791dSBob Badour       return 0;
127*418b791dSBob Badour    }
128*418b791dSBob Badour    for(i = 0; chars[i] != 0; ++i) {
129*418b791dSBob Badour       if(c == chars[i]) {
130*418b791dSBob Badour          sbuf_advance(buf, 1);
131*418b791dSBob Badour          return 1;
132*418b791dSBob Badour       }
133*418b791dSBob Badour    }
134*418b791dSBob Badour    return 0;
135*418b791dSBob Badour }
136*418b791dSBob Badour 
137*418b791dSBob Badour //! consume 1 char only if its not in string chars
sbuf_notchars(struct sbuf * buf,const char * chars)138*418b791dSBob Badour static __inline int sbuf_notchars(struct sbuf *buf, const char *chars) {
139*418b791dSBob Badour    int i = 0;
140*418b791dSBob Badour    char c;
141*418b791dSBob Badour    if(!sbuf_peek(buf, &c)) {
142*418b791dSBob Badour       return 0;
143*418b791dSBob Badour    }
144*418b791dSBob Badour    for(i = 0; chars[i] != 0; ++i) {
145*418b791dSBob Badour       if(c == chars[i]) {
146*418b791dSBob Badour          return 0;
147*418b791dSBob Badour       }
148*418b791dSBob Badour    }
149*418b791dSBob Badour    sbuf_advance(buf, 1);
150*418b791dSBob Badour    return 1;
151*418b791dSBob Badour }
152*418b791dSBob Badour 
153*418b791dSBob Badour //! consume only char t
sbuf_char(struct sbuf * buf,const char t)154*418b791dSBob Badour static __inline int sbuf_char(struct sbuf *buf, const char t) {
155*418b791dSBob Badour    char str[2] = {t, 0};
156*418b791dSBob Badour    return sbuf_chars(buf, str);
157*418b791dSBob Badour }
158*418b791dSBob Badour 
159*418b791dSBob Badour //! consume any char except for t
sbuf_notchar(struct sbuf * buf,const char t)160*418b791dSBob Badour static __inline int sbuf_notchar(struct sbuf *buf, const char t) {
161*418b791dSBob Badour    char str[2] = {t, 0};
162*418b791dSBob Badour    return sbuf_notchars(buf, str);
163*418b791dSBob Badour }
164*418b791dSBob Badour 
165*418b791dSBob Badour /**
166*418b791dSBob Badour  * consume any char
167*418b791dSBob Badour  */
sbuf_any(struct sbuf * buf)168*418b791dSBob Badour static __inline int sbuf_any(struct sbuf* buf) {
169*418b791dSBob Badour    return sbuf_notchars(buf, "");
170*418b791dSBob Badour }
171*418b791dSBob Badour 
172*418b791dSBob Badour 
173*418b791dSBob Badour /**
174*418b791dSBob Badour  * range is pairs of characters
175*418b791dSBob Badour  *
176*418b791dSBob Badour  * pairs are inclusive, start must be less then or equal then the end
177*418b791dSBob Badour  *
178*418b791dSBob Badour  * for example: AZaz09--..
179*418b791dSBob Badour  *   matches uppercase and lowercase letters, numbers, dashes and dots
180*418b791dSBob Badour  *
181*418b791dSBob Badour  */
sbuf_range(struct sbuf * buf,const char * chars)182*418b791dSBob Badour static __inline int sbuf_range(struct sbuf *buf, const char *chars) {
183*418b791dSBob Badour    int i, j;
184*418b791dSBob Badour    char c;
185*418b791dSBob Badour    if(!sbuf_peek(buf, &c)) {
186*418b791dSBob Badour       return 0;
187*418b791dSBob Badour    }
188*418b791dSBob Badour    for(i = 0, j = 1; chars[i] != 0 && chars[j] != 0; i+=2,j+=2) {
189*418b791dSBob Badour       if(c >= chars[i] && c <= chars[j]) {
190*418b791dSBob Badour          sbuf_advance(buf, 1);
191*418b791dSBob Badour          return 1;
192*418b791dSBob Badour       }
193*418b791dSBob Badour    }
194*418b791dSBob Badour    return 0;
195*418b791dSBob Badour }
196*418b791dSBob Badour 
197*418b791dSBob Badour 
198*418b791dSBob Badour /**
199*418b791dSBob Badour  * greedly consume and match the entire string
200*418b791dSBob Badour  * empty string always succeeds without consuming any data
201*418b791dSBob Badour  */
sbuf_string(struct sbuf * buf,const char * str)202*418b791dSBob Badour static __inline int sbuf_string(struct sbuf *buf, const char *str) {
203*418b791dSBob Badour    int i = 0;
204*418b791dSBob Badour    for(i = 0; str[i] != 0; ++i) {
205*418b791dSBob Badour       if(!sbuf_char(buf, str[i])) {
206*418b791dSBob Badour          return 0;
207*418b791dSBob Badour       }
208*418b791dSBob Badour    }
209*418b791dSBob Badour    return 1;
210*418b791dSBob Badour }
211*418b791dSBob Badour 
212*418b791dSBob Badour /**
213*418b791dSBob Badour  * consumes until fails
214*418b791dSBob Badour  */
sbuf_many(struct sbuf * buf,int (* consume)(struct sbuf * buf))215*418b791dSBob Badour static __inline int sbuf_many(struct sbuf *buf,
216*418b791dSBob Badour                               int(*consume)(struct sbuf *buf))
217*418b791dSBob Badour {
218*418b791dSBob Badour    if(!sbuf_valid(buf)) {
219*418b791dSBob Badour       return 0;
220*418b791dSBob Badour    }
221*418b791dSBob Badour    while(consume(buf)) {;}
222*418b791dSBob Badour    return 1;
223*418b791dSBob Badour }
224*418b791dSBob Badour /**
225*418b791dSBob Badour  * consumes until fails, must consume at least 1
226*418b791dSBob Badour  */
sbuf_many1(struct sbuf * buf,int (* consume)(struct sbuf * buf))227*418b791dSBob Badour static __inline int sbuf_many1(struct sbuf *buf,
228*418b791dSBob Badour                                int(*consume)(struct sbuf *buf))
229*418b791dSBob Badour {
230*418b791dSBob Badour    if(!consume(buf)) {
231*418b791dSBob Badour       return 0;
232*418b791dSBob Badour    }
233*418b791dSBob Badour    sbuf_many(buf, consume);
234*418b791dSBob Badour    return 1;
235*418b791dSBob Badour }
236*418b791dSBob Badour /**
237*418b791dSBob Badour  * runs 'consume' until 'stop' succeeds
238*418b791dSBob Badour  * 'stop' must fail in such a way that it doesn't consume any data
239*418b791dSBob Badour  */
sbuf_until(struct sbuf * buf,int (* consume)(struct sbuf * buf),int (* stop)(struct sbuf * buf))240*418b791dSBob Badour static __inline int sbuf_until(struct sbuf *buf,
241*418b791dSBob Badour                                int(*consume)(struct sbuf *buf),
242*418b791dSBob Badour                                int(*stop)(struct sbuf *buf))
243*418b791dSBob Badour {
244*418b791dSBob Badour    while(!stop(buf)) {
245*418b791dSBob Badour       if(!consume(buf))  {
246*418b791dSBob Badour          return 0;
247*418b791dSBob Badour       }
248*418b791dSBob Badour    }
249*418b791dSBob Badour    return 1;
250*418b791dSBob Badour }
251*418b791dSBob Badour 
252*418b791dSBob Badour /**
253*418b791dSBob Badour  * allows for backtracking,
254*418b791dSBob Badour  * @param parser, runs parser and only consume if it succeeds
255*418b791dSBob Badour  */
sbuf_try(struct sbuf * buf,int (* parser)(struct sbuf * buf))256*418b791dSBob Badour static __inline int sbuf_try(struct sbuf *buf, int(*parser)(struct sbuf *buf))
257*418b791dSBob Badour {
258*418b791dSBob Badour    struct sbuf tryp;
259*418b791dSBob Badour    sbuf_parser_init(&tryp, sbuf_cur(buf), sbuf_left(buf));
260*418b791dSBob Badour    if(parser(&tryp)) {
261*418b791dSBob Badour       sbuf_advance(buf, sbuf_cur(&tryp) - sbuf_cur(buf));
262*418b791dSBob Badour       return 1;
263*418b791dSBob Badour    }
264*418b791dSBob Badour    return 0;
265*418b791dSBob Badour }
266*418b791dSBob Badour #endif // SBUF_PARSER_H
267