Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: runtime/vm/json.cc

Issue 9949054: Basic support for reading and writing JSON objects. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/json.h ('k') | runtime/vm/json_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/json.h"
6
7 #include "platform/assert.h"
8 #include "platform/utils.h"
9 #include "vm/os.h"
10
11 namespace dart {
12
13
14 JSONScanner::JSONScanner(const char* json_text) {
15 SetText(json_text);
16 }
17
18
19 void JSONScanner::SetText(const char* json_text) {
20 current_pos_ = json_text;
21 token_start_ = json_text;
22 token_length_ = 0;
23 token_ = TokenIllegal;
24 }
25
26
27 void JSONScanner::Recognize(Token t) {
28 ++current_pos_;
29 token_ = t;
30 }
31
32
33 bool JSONScanner::IsLetter(char ch) const {
34 return (('A' <= ch) && (ch <= 'Z')) || (('a' <= ch) && (ch <= 'z'));
35 }
36
37
38 bool JSONScanner::IsDigit(char ch) const {
39 return ('0' <= ch) && (ch <= '9');
40 }
41
42
43 bool JSONScanner::IsLiteral(const char* literal) {
44 int i = 0;
45 while ((literal[i] != '\0') && (current_pos_[i] == literal[i])) {
turnidge 2012/04/11 17:06:45 What if current_pos_[i] == '\0'? Might access bey
46 i++;
47 }
48 if ((literal[i] == '\0') && !IsLetter(current_pos_[i])) {
49 current_pos_ += i;
50 return true;
51 }
52 return false;
53 }
54
55
56 bool JSONScanner::IsStringLiteral(const char* literal) const {
57 if (token_ != TokenString) {
58 return false;
59 }
60 int i = 0;
61 while ((i < token_length_) && (token_start_[i] == literal[i])) {
turnidge 2012/04/11 17:06:45 What if literal is shorter than the current token?
62 i++;
63 }
64 return (i == token_length_) && (literal[i] == '\0');
65 }
66
67
68 void JSONScanner::Skip(Token matching_token) {
69 while (!EOM() && (token_ != TokenIllegal)) {
70 Scan();
71 if (token_ == TokenLBrace) {
72 Skip(TokenRBrace);
73 } else if (token_ == TokenLBrack) {
74 Skip(TokenRBrack);
75 } else if (token_ == matching_token) {
76 return;
77 } else if ((token_ == TokenRBrace) || (token_ == TokenRBrack)) {
78 // Mismatched brace or bracket.
79 token_ = TokenIllegal;
80 }
81 }
82 }
83
84
85 void JSONScanner::ScanString() {
86 ASSERT(*current_pos_ == '"');
87 ++current_pos_;
88 token_start_ = current_pos_;
89 while (*current_pos_ != '"') {
90 if (*current_pos_ == '\0') {
91 token_length_ = 0;
92 token_ = TokenIllegal;
93 return;
94 } else if (*current_pos_ == '\\') {
95 // TODO(hausner): Implement escape sequence.
96 UNIMPLEMENTED();
97 } else if (*current_pos_ < 0) {
98 // UTF-8 not supported.
99 token_length_ = 0;
100 token_ = TokenIllegal;
101 return;
102 } else {
103 ++current_pos_;
104 }
105 }
106 token_ = TokenString;
107 token_length_ = current_pos_ - token_start_;
108 ++current_pos_;
109 }
110
111
112 void JSONScanner::ScanNumber() {
113 if (*current_pos_ == '-') {
114 ++current_pos_;
115 }
116 if (!IsDigit(*current_pos_)) {
117 token_ = TokenIllegal;
118 token_length_ = 0;
119 return;
120 }
121 while (IsDigit(*current_pos_)) {
122 ++current_pos_;
123 }
124 if ((*current_pos_ == '.') ||
125 (*current_pos_ == 'e') ||
126 (*current_pos_ == 'E')) {
127 // Floating point numbers not supported.
128 token_ = TokenIllegal;
129 token_length_ = 0;
130 return;
131 }
132 token_ = TokenInteger;
133 token_length_ = current_pos_ - token_start_;
134 }
135
136
137 void JSONScanner::Scan() {
138 while ((*current_pos_ == ' ') ||
139 (*current_pos_ == '\t') ||
140 (*current_pos_ == '\n')) {
141 ++current_pos_;
142 }
143 token_start_ = current_pos_;
144 if (*current_pos_ == '\0') {
145 token_length_ = 0;
146 token_ = TokenEOM;
147 return;
148 }
149 switch (*current_pos_) {
150 case '{':
151 Recognize(TokenLBrace);
152 break;
153 case '}':
154 Recognize(TokenRBrace);
155 break;
156 case '[':
157 Recognize(TokenLBrack);
158 break;
159 case ']':
160 Recognize(TokenRBrack);
161 break;
162 case ':':
163 Recognize(TokenColon);
164 break;
165 case ',':
166 Recognize(TokenComma);
167 break;
168 case '"':
169 ScanString();
170 break;
171 case '0':
172 case '1':
173 case '2':
174 case '3':
175 case '4':
176 case '5':
177 case '6':
178 case '7':
179 case '8':
180 case '9':
181 case '-':
182 ScanNumber();
183 break;
184 default:
185 if (IsLiteral("true")) {
186 token_ = TokenTrue;
187 } else if (IsLiteral("false")) {
188 token_ = TokenFalse;
189 } else if (IsLiteral("null")) {
190 token_ = TokenNull;
191 } else {
192 token_length_ = 0;
193 token_ = TokenIllegal;
194 }
195 }
196 }
197
198
199 JSONReader::JSONReader(const char* json_object)
200 : scanner_(json_object) {
201 Set(json_object);
202 }
203
204 void JSONReader::Set(const char* json_object) {
205 scanner_.SetText(json_object);
206 json_object_ = json_object;
207 error_ = false;
208 }
209
210
211 bool JSONReader::Seek(const char* name) {
212 scanner_.SetText(json_object_);
213 scanner_.Scan();
214 if (scanner_.CurrentToken() != JSONScanner::TokenLBrace) {
215 error_ = true;
216 return false;
217 }
218 scanner_.Scan();
219 while (scanner_.CurrentToken() == JSONScanner::TokenString) {
220 bool found = scanner_.IsStringLiteral(name);
221 scanner_.Scan();
222 if (scanner_.CurrentToken() != JSONScanner::TokenColon) {
223 error_ = true;
224 return false;
225 }
226 scanner_.Scan();
227 switch (scanner_.CurrentToken()) {
228 case JSONScanner::TokenString:
229 case JSONScanner::TokenInteger:
230 case JSONScanner::TokenLBrace:
231 case JSONScanner::TokenLBrack:
232 case JSONScanner::TokenTrue:
233 case JSONScanner::TokenFalse:
234 case JSONScanner::TokenNull:
235 // Found a legal value.
236 if (found) {
237 return true;
238 }
239 break;
240 default:
241 error_ = true;
242 return false;
243 }
244 // Skip the value.
245 if (scanner_.CurrentToken() == JSONScanner::TokenLBrace) {
246 scanner_.Skip(JSONScanner::TokenRBrace);
247 if (scanner_.CurrentToken() != JSONScanner::TokenRBrace) {
248 error_ = true;
249 return false;
250 }
251 } else if (scanner_.CurrentToken() == JSONScanner::TokenLBrack) {
252 scanner_.Skip(JSONScanner::TokenRBrack);
253 if (scanner_.CurrentToken() != JSONScanner::TokenRBrack) {
254 error_ = true;
255 return false;
256 }
257 }
258 scanner_.Scan(); // Value or closing brace or bracket.
259 if (scanner_.CurrentToken() == JSONScanner::TokenComma) {
260 scanner_.Scan();
261 } else {
262 // End of json object or malformed object. Value not found.
263 error_ = true;
264 break;
265 }
266 }
267 return false;
268 }
269
270
271 JSONReader::JSONType JSONReader::Type() const {
272 if (error_) {
273 return kNone;
274 }
275 switch (scanner_.CurrentToken()) {
276 case JSONScanner::TokenString:
277 return kString;
278 case JSONScanner::TokenInteger:
279 return kInteger;
280 case JSONScanner::TokenLBrace:
281 return kObject;
282 case JSONScanner::TokenLBrack:
283 return kArray;
284 case JSONScanner::TokenTrue:
285 case JSONScanner::TokenFalse:
286 case JSONScanner::TokenNull:
287 return kLiteral;
288 default:
289 return kNone;
290 }
291 }
292
293
294 TextBuffer::TextBuffer(intptr_t buf_size) {
295 ASSERT(buf_size > 0);
296 buf_ = reinterpret_cast<char*>(malloc(buf_size));
297 buf_size_ = buf_size;
298 Clear();
299 }
300
301
302 TextBuffer::~TextBuffer() {
303 free(buf_);
304 buf_ = NULL;
305 }
306
307
308 void TextBuffer::Clear() {
309 msg_len_ = 0;
310 buf_[0] = '\0';
311 }
312
313
314 intptr_t TextBuffer::Printf(const char* format, ...) {
315 va_list args;
316 va_start(args, format);
317 intptr_t remaining = buf_size_ - msg_len_;
318 ASSERT(remaining >= 0);
319 intptr_t len = OS::VSNPrint(buf_ + msg_len_, remaining, format, args);
320 va_end(args);
321 if (len >= remaining) {
322 const int kBufferSpareCapacity = 64; // Somewhat arbitrary.
323 GrowBuffer(len + kBufferSpareCapacity);
324 remaining = buf_size_ - msg_len_;
325 ASSERT(remaining > len);
326 va_list args2;
327 va_start(args2, format);
328 intptr_t len2 = OS::VSNPrint(buf_ + msg_len_, remaining, format, args2);
329 va_end(args2);
330 ASSERT(len == len2);
331 }
332 msg_len_ += len;
333 buf_[msg_len_] = '\0';
334 return len;
335 }
336
337
338 void TextBuffer::GrowBuffer(intptr_t len) {
339 intptr_t new_size = buf_size_ + len;
340 char* new_buf = reinterpret_cast<char*>(realloc(buf_, new_size));
341 ASSERT(new_buf != NULL);
342 buf_ = new_buf;
343 buf_size_ = new_size;
344 }
345
346 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/json.h ('k') | runtime/vm/json_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698