Line data Source code
1 : /*
2 : * Samba Unix/Linux SMB client library
3 : *
4 : * Copyright (C) Gregor Beck 2010
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /**
21 : * @file srprs.c
22 : * @author Gregor Beck <gb@sernet.de>
23 : * @date Aug 2010
24 : * @brief A simple recursive parser.
25 : */
26 :
27 : #include "replace.h"
28 : #include "system/locale.h"
29 : #include "srprs.h"
30 : #include "cbuf.h"
31 : #include <assert.h>
32 :
33 7864 : bool srprs_skipws(const char** ptr) {
34 9520 : while (isspace(**ptr))
35 1656 : ++(*ptr);
36 7864 : return true;
37 : }
38 :
39 12848 : bool srprs_char(const char** ptr, char c) {
40 12848 : if (**ptr == c) {
41 7078 : ++(*ptr);
42 7078 : return true;
43 : }
44 5770 : return false;
45 : }
46 :
47 9199 : bool srprs_str(const char** ptr, const char* str, ssize_t len)
48 : {
49 : /* By definition *ptr must be null terminated. */
50 9199 : size_t ptr_len = strlen(*ptr);
51 :
52 9199 : if (len == -1)
53 6074 : len = strlen(str);
54 :
55 : /* Don't memcmp read past end of buffer. */
56 9199 : if (len > ptr_len) {
57 721 : return false;
58 : }
59 :
60 8478 : if (memcmp(*ptr, str, len) == 0) {
61 394 : *ptr += len;
62 394 : return true;
63 : }
64 8084 : return false;
65 : }
66 :
67 3137 : bool srprs_charset(const char** ptr, const char* set, cbuf* oss)
68 : {
69 3137 : const char* p = strchr(set, **ptr);
70 3137 : if (p != NULL && *p != '\0') {
71 1672 : cbuf_putc(oss, **ptr);
72 1672 : ++(*ptr);
73 1672 : return true;
74 : }
75 1465 : return false;
76 : }
77 :
78 131079 : bool srprs_charsetinv(const char** ptr, const char* set, cbuf* oss)
79 : {
80 131079 : if ((**ptr != '\0') && (strchr(set, **ptr) == NULL)) {
81 125600 : cbuf_putc(oss, **ptr);
82 125600 : ++(*ptr);
83 125600 : return true;
84 : }
85 5479 : return false;
86 : }
87 :
88 :
89 :
90 2272 : bool srprs_quoted_string(const char** ptr, cbuf* str, bool* cont)
91 : {
92 2272 : const char* pos = *ptr;
93 2272 : const size_t spos = cbuf_getpos(str);
94 :
95 2272 : if (cont == NULL || *cont == false) {
96 2272 : if (!srprs_char(&pos, '\"'))
97 0 : goto fail;
98 : }
99 :
100 : while (true) {
101 50917 : while (srprs_charsetinv(&pos, "\\\"", str))
102 : ;
103 :
104 2288 : switch (*pos) {
105 0 : case '\0':
106 0 : if (cont == NULL) {
107 0 : goto fail;
108 : } else {
109 0 : *ptr = pos;
110 0 : *cont = true;
111 0 : return true;
112 : }
113 2272 : case '\"':
114 2272 : *ptr = pos+1;
115 2272 : if (cont != NULL) {
116 1136 : *cont = false;
117 : }
118 2272 : return true;
119 :
120 16 : case '\\':
121 16 : pos++;
122 16 : if (!srprs_charset(&pos, "\\\"", str))
123 0 : goto fail;
124 16 : break;
125 :
126 0 : default:
127 0 : assert(false);
128 : }
129 : }
130 :
131 0 : fail:
132 0 : cbuf_setpos(str, spos);
133 0 : return false;
134 : }
135 :
136 0 : bool srprs_hex(const char** ptr, size_t len, unsigned* u)
137 : {
138 0 : const char *str = *ptr;
139 0 : const char *pos = *ptr;
140 0 : int ret;
141 0 : size_t i;
142 0 : char buf[8+1] = {};
143 :
144 0 : assert((len >= 1) && (len <= 8));
145 :
146 0 : for (i=0; i<len; i++) {
147 0 : if (!srprs_charset(&pos, "0123456789abcdefABCDEF", NULL)) {
148 0 : break;
149 : }
150 0 : buf[i] = str[i];
151 : }
152 :
153 0 : ret = sscanf(buf, "%8x", u);
154 :
155 0 : if ( ret != 1 ) {
156 0 : return false;
157 : }
158 :
159 0 : *ptr = pos;
160 0 : return true;
161 : }
162 :
163 3125 : bool srprs_nl(const char** ptr, cbuf* nl)
164 : {
165 0 : static const char CRLF[] = "\r\n";
166 3125 : if (srprs_str(ptr, CRLF, sizeof(CRLF) - 1)) {
167 4 : cbuf_puts(nl, CRLF, sizeof(CRLF) - 1);
168 4 : return true;
169 : }
170 3121 : return srprs_charset(ptr, "\n\r", nl);
171 : }
172 :
173 5316 : bool srprs_eos(const char** ptr)
174 : {
175 5316 : return (**ptr == '\0');
176 : }
177 :
178 3054 : bool srprs_eol(const char** ptr, cbuf* nl)
179 : {
180 3054 : return srprs_eos(ptr) || srprs_nl(ptr, nl);
181 : }
182 :
183 1739 : bool srprs_line(const char** ptr, cbuf* str)
184 : {
185 69340 : while (srprs_charsetinv(ptr, "\n\r", str))
186 : ;
187 1739 : return true;
188 : }
189 :
190 0 : bool srprs_quoted(const char** ptr, cbuf* str)
191 : {
192 0 : const char* pos = *ptr;
193 0 : const size_t spos = cbuf_getpos(str);
194 :
195 0 : if (!srprs_char(&pos, '"')) {
196 0 : goto fail;
197 : }
198 :
199 : while (true) {
200 0 : while (srprs_charsetinv(&pos, "\\\"", str))
201 : ;
202 :
203 0 : switch (*pos) {
204 0 : case '\0':
205 0 : goto fail;
206 0 : case '"':
207 0 : *ptr = pos+1;
208 0 : return true;
209 :
210 0 : case '\\':
211 0 : pos++;
212 0 : if (!srprs_charset(&pos, "\\\"", str)) {
213 0 : unsigned u;
214 0 : if (!srprs_hex(&pos, 2, &u)) {
215 0 : goto fail;
216 : }
217 0 : cbuf_putc(str, u);
218 : }
219 0 : break;
220 0 : default:
221 0 : assert(false);
222 : }
223 : }
224 :
225 0 : fail:
226 0 : cbuf_setpos(str, spos);
227 0 : return false;
228 : }
|