s3: libsmb: Cleanup in get_dc_list()
[Samba.git] / source3 / lib / srprs.c
blob67ada3796f0effa0b93e63c0878fb8c5eecd423e
1 /*
2 * Samba Unix/Linux SMB client library
4 * Copyright (C) Gregor Beck 2010
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.
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.
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/>.
20 /**
21 * @file srprs.c
22 * @author Gregor Beck <gb@sernet.de>
23 * @date Aug 2010
24 * @brief A simple recursive parser.
27 #include "replace.h"
28 #include "system/locale.h"
29 #include "srprs.h"
30 #include "cbuf.h"
31 #include <assert.h>
33 bool srprs_skipws(const char** ptr) {
34 while (isspace(**ptr))
35 ++(*ptr);
36 return true;
39 bool srprs_char(const char** ptr, char c) {
40 if (**ptr == c) {
41 ++(*ptr);
42 return true;
44 return false;
47 bool srprs_str(const char** ptr, const char* str, ssize_t len)
49 /* By definition *ptr must be null terminated. */
50 size_t ptr_len = strlen(*ptr);
52 if (len == -1)
53 len = strlen(str);
55 /* Don't memcmp read past end of buffer. */
56 if (len > ptr_len) {
57 return false;
60 if (memcmp(*ptr, str, len) == 0) {
61 *ptr += len;
62 return true;
64 return false;
67 bool srprs_charset(const char** ptr, const char* set, cbuf* oss)
69 const char* p = strchr(set, **ptr);
70 if (p != NULL && *p != '\0') {
71 cbuf_putc(oss, **ptr);
72 ++(*ptr);
73 return true;
75 return false;
78 bool srprs_charsetinv(const char** ptr, const char* set, cbuf* oss)
80 if ((**ptr != '\0') && (strchr(set, **ptr) == NULL)) {
81 cbuf_putc(oss, **ptr);
82 ++(*ptr);
83 return true;
85 return false;
90 bool srprs_quoted_string(const char** ptr, cbuf* str, bool* cont)
92 const char* pos = *ptr;
93 const size_t spos = cbuf_getpos(str);
95 if (cont == NULL || *cont == false) {
96 if (!srprs_char(&pos, '\"'))
97 goto fail;
100 while (true) {
101 while (srprs_charsetinv(&pos, "\\\"", str))
104 switch (*pos) {
105 case '\0':
106 if (cont == NULL) {
107 goto fail;
108 } else {
109 *ptr = pos;
110 *cont = true;
111 return true;
113 case '\"':
114 *ptr = pos+1;
115 if (cont != NULL) {
116 *cont = false;
118 return true;
120 case '\\':
121 pos++;
122 if (!srprs_charset(&pos, "\\\"", str))
123 goto fail;
124 break;
126 default:
127 assert(false);
131 fail:
132 cbuf_setpos(str, spos);
133 return false;
136 bool srprs_hex(const char** ptr, size_t len, unsigned* u)
138 const char *str = *ptr;
139 const char *pos = *ptr;
140 int ret;
141 size_t i;
142 char buf[8+1] = {};
144 assert((len >= 1) && (len <= 8));
146 for (i=0; i<len; i++) {
147 if (!srprs_charset(&pos, "0123456789abcdefABCDEF", NULL)) {
148 break;
150 buf[i] = str[i];
153 ret = sscanf(buf, "%8x", u);
155 if ( ret != 1 ) {
156 return false;
159 *ptr = pos;
160 return true;
163 bool srprs_nl(const char** ptr, cbuf* nl)
165 static const char CRLF[] = "\r\n";
166 if (srprs_str(ptr, CRLF, sizeof(CRLF) - 1)) {
167 cbuf_puts(nl, CRLF, sizeof(CRLF) - 1);
168 return true;
170 return srprs_charset(ptr, "\n\r", nl);
173 bool srprs_eos(const char** ptr)
175 return (**ptr == '\0');
178 bool srprs_eol(const char** ptr, cbuf* nl)
180 return srprs_eos(ptr) || srprs_nl(ptr, nl);
183 bool srprs_line(const char** ptr, cbuf* str)
185 while (srprs_charsetinv(ptr, "\n\r", str))
187 return true;
190 bool srprs_quoted(const char** ptr, cbuf* str)
192 const char* pos = *ptr;
193 const size_t spos = cbuf_getpos(str);
195 if (!srprs_char(&pos, '"')) {
196 goto fail;
199 while (true) {
200 while (srprs_charsetinv(&pos, "\\\"", str))
203 switch (*pos) {
204 case '\0':
205 goto fail;
206 case '"':
207 *ptr = pos+1;
208 return true;
210 case '\\':
211 pos++;
212 if (!srprs_charset(&pos, "\\\"", str)) {
213 unsigned u;
214 if (!srprs_hex(&pos, 2, &u)) {
215 goto fail;
217 cbuf_putc(str, u);
219 break;
220 default:
221 assert(false);
225 fail:
226 cbuf_setpos(str, spos);
227 return false;