lib:ldb: Use correct integer types for sizes
[vlendec/samba-autobuild/.git] / source3 / lib / srprs.c
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 bool srprs_skipws(const char** ptr) {
34         while (isspace(**ptr))
35                 ++(*ptr);
36         return true;
37 }
38
39 bool srprs_char(const char** ptr, char c) {
40         if (**ptr == c) {
41                 ++(*ptr);
42                 return true;
43         }
44         return false;
45 }
46
47 bool srprs_str(const char** ptr, const char* str, ssize_t len)
48 {
49         if (len == -1)
50                 len = strlen(str);
51
52         if (memcmp(*ptr, str, len) == 0) {
53                 *ptr += len;
54                 return true;
55         }
56         return false;
57 }
58
59 bool srprs_charset(const char** ptr, const char* set, cbuf* oss)
60 {
61         const char* p = strchr(set, **ptr);
62         if (p != NULL && *p != '\0') {
63                 cbuf_putc(oss, **ptr);
64                 ++(*ptr);
65                 return true;
66         }
67         return false;
68 }
69
70 bool srprs_charsetinv(const char** ptr, const char* set, cbuf* oss)
71 {
72         if ((**ptr != '\0') && (strchr(set, **ptr) == NULL)) {
73                 cbuf_putc(oss, **ptr);
74                 ++(*ptr);
75                 return true;
76         }
77         return false;
78 }
79
80
81
82 bool srprs_quoted_string(const char** ptr, cbuf* str, bool* cont)
83 {
84         const char* pos = *ptr;
85         const size_t spos = cbuf_getpos(str);
86
87         if (cont == NULL || *cont == false) {
88                 if (!srprs_char(&pos, '\"'))
89                         goto fail;
90         }
91
92         while (true) {
93                 while (srprs_charsetinv(&pos, "\\\"", str))
94                         ;
95
96                 switch (*pos) {
97                 case '\0':
98                         if (cont == NULL) {
99                                 goto fail;
100                         } else {
101                                 *ptr = pos;
102                                 *cont = true;
103                                 return true;
104                         }
105                 case '\"':
106                         *ptr  = pos+1;
107                         if (cont != NULL) {
108                                 *cont = false;
109                         }
110                         return true;
111
112                 case '\\':
113                         pos++;
114                         if (!srprs_charset(&pos, "\\\"", str))
115                                 goto fail;
116                         break;
117
118                 default:
119                         assert(false);
120                 }
121         }
122
123 fail:
124         cbuf_setpos(str, spos);
125         return false;
126 }
127
128 bool srprs_hex(const char** ptr, size_t len, unsigned* u)
129 {
130         const char *str = *ptr;
131         const char *pos = *ptr;
132         int ret;
133         size_t i;
134         char buf[8+1] = {};
135
136         assert((len >= 1) && (len <= 8));
137
138         for (i=0; i<len; i++) {
139                 if (!srprs_charset(&pos, "0123456789abcdefABCDEF", NULL)) {
140                         break;
141                 }
142                 buf[i] = str[i];
143         }
144
145         ret = sscanf(buf, "%8x", u);
146
147         if ( ret != 1 ) {
148                 return false;
149         }
150
151         *ptr = pos;
152         return true;
153 }
154
155 bool srprs_nl(const char** ptr, cbuf* nl)
156 {
157         static const char CRLF[] = "\r\n";
158         if (srprs_str(ptr, CRLF, sizeof(CRLF) - 1)) {
159                 cbuf_puts(nl, CRLF, sizeof(CRLF) - 1);
160                 return true;
161         }
162         return srprs_charset(ptr, "\n\r", nl);
163 }
164
165 bool srprs_eos(const char** ptr)
166 {
167         return (**ptr == '\0');
168 }
169
170 bool srprs_eol(const char** ptr, cbuf* nl)
171 {
172         return  srprs_eos(ptr) || srprs_nl(ptr, nl);
173 }
174
175 bool srprs_line(const char** ptr, cbuf* str)
176 {
177         while (srprs_charsetinv(ptr, "\n\r", str))
178                 ;
179         return true;
180 }
181
182 bool srprs_quoted(const char** ptr, cbuf* str)
183 {
184         const char* pos = *ptr;
185         const size_t spos = cbuf_getpos(str);
186
187         if (!srprs_char(&pos, '"')) {
188                 goto fail;
189         }
190
191         while (true) {
192                 while (srprs_charsetinv(&pos, "\\\"", str))
193                         ;
194
195                 switch (*pos) {
196                 case '\0':
197                         goto fail;
198                 case '"':
199                         *ptr  = pos+1;
200                         return true;
201
202                 case '\\':
203                         pos++;
204                         if (!srprs_charset(&pos, "\\\"", str)) {
205                                 unsigned u;
206                                 if (!srprs_hex(&pos, 2, &u)) {
207                                         goto fail;
208                                 }
209                                 cbuf_putc(str, u);
210                         }
211                         break;
212                 default:
213                         assert(false);
214                 }
215         }
216
217 fail:
218         cbuf_setpos(str, spos);
219         return false;
220 }