2 * Copyright (c) 2013 David Chisnall
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * The source files are ASCII, so we provide a non-locale-aware version of
39 * isalpha. This is a class so that it can be used with a template function
40 * for parsing strings.
44 static inline bool check(const char c)
46 return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') &&
51 * Check whether a character is in the set allowed for node names. This is a
52 * class so that it can be used with a template function for parsing strings.
54 struct is_node_name_character
56 static inline bool check(const char c)
62 case 'a'...'z': case 'A'...'Z': case '0'...'9':
63 case ',': case '.': case '+': case '-':
70 * Check whether a character is in the set allowed for property names. This is
71 * a class so that it can be used with a template function for parsing strings.
73 struct is_property_name_character
75 static inline bool check(const char c)
81 case 'a'...'z': case 'A'...'Z': case '0'...'9':
82 case ',': case '.': case '+': case '-':
94 template<class T> string
95 string::parse(input_buffer &s)
97 const char *start = s;
99 while (T::check(*s)) { l++; ++s; }
100 return string(start, l);
103 string::string(input_buffer &s) : start((const char*)s), length(0)
105 while(s[length] != '\0')
112 string::parse_node_name(input_buffer &s)
114 return parse<is_node_name_character>(s);
118 string::parse_property_name(input_buffer &s)
120 return parse<is_property_name_character>(s);
123 string::parse_node_or_property_name(input_buffer &s, bool &is_property)
127 return parse_property_name(s);
129 const char *start = s;
131 while (is_node_name_character::check(*s))
136 while (is_property_name_character::check(*s))
142 return string(start, l);
146 string::operator==(const string& other) const
148 return (length == other.length) &&
149 (memcmp(start, other.start, length) == 0);
153 string::operator==(const char *other) const
155 return strncmp(other, start, length) == 0;
159 string::operator<(const string& other) const
161 if (length < other.length) { return true; }
162 if (length > other.length) { return false; }
163 return memcmp(start, other.start, length) < 0;
167 string::push_to_buffer(byte_buffer &buffer, bool escapes)
169 for (int i=0 ; i<length ; ++i)
171 uint8_t c = start[i];
172 if (escapes && c == '\\' && i+1 < length)
177 // For now, we just ignore invalid escape sequences.
206 int v = digittoint(c);
207 if (i+1 < length && start[i+1] <= '7' && start[i+1] >= '0')
210 v |= digittoint(start[i+1]);
212 if (i+1 < length && start[i+1] <= '7' && start[i+1] >= '0')
215 v |= digittoint(start[i+1]);
228 int v = digittoint(start[i]);
229 if (i+1 < length && ishexdigit(start[i+1]))
232 v |= digittoint(start[++i]);
244 string::print(FILE *file)
246 fwrite(start, length, 1, file);