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

Unified Diff: runtime/platform/json.cc

Issue 10357003: Beginnings of a debugger wire protocol (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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/platform/json.h ('k') | runtime/platform/platform_headers.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/platform/json.cc
===================================================================
--- runtime/platform/json.cc (revision 0)
+++ runtime/platform/json.cc (revision 0)
@@ -0,0 +1,367 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/json.h"
+
+#include "platform/assert.h"
+#include "platform/utils.h"
+#include "vm/os.h"
+
+namespace dart {
+
+
+JSONScanner::JSONScanner(const char* json_text) {
+ SetText(json_text);
+}
+
+
+void JSONScanner::SetText(const char* json_text) {
+ current_pos_ = json_text;
+ token_start_ = json_text;
+ token_length_ = 0;
+ token_ = TokenIllegal;
+}
+
+
+void JSONScanner::Recognize(Token t) {
+ ++current_pos_;
+ token_ = t;
+}
+
+
+bool JSONScanner::IsLetter(char ch) const {
+ return (('A' <= ch) && (ch <= 'Z')) || (('a' <= ch) && (ch <= 'z'));
+}
+
+
+bool JSONScanner::IsDigit(char ch) const {
+ return ('0' <= ch) && (ch <= '9');
+}
+
+
+bool JSONScanner::IsLiteral(const char* literal) {
+ int i = 0;
+ while ((literal[i] != '\0') && (current_pos_[i] == literal[i])) {
+ i++;
+ }
+ if ((literal[i] == '\0') && !IsLetter(current_pos_[i])) {
+ current_pos_ += i;
+ return true;
+ }
+ return false;
+}
+
+
+bool JSONScanner::IsStringLiteral(const char* literal) const {
+ if (token_ != TokenString) {
+ return false;
+ }
+ int i = 0;
+ while ((i < token_length_) && (token_start_[i] == literal[i])) {
+ i++;
+ }
+ return (i == token_length_) && (literal[i] == '\0');
+}
+
+
+void JSONScanner::Skip(Token matching_token) {
+ while (!EOM() && (token_ != TokenIllegal)) {
+ Scan();
+ if (token_ == TokenLBrace) {
+ Skip(TokenRBrace);
+ } else if (token_ == TokenLBrack) {
+ Skip(TokenRBrack);
+ } else if (token_ == matching_token) {
+ return;
+ } else if ((token_ == TokenRBrace) || (token_ == TokenRBrack)) {
+ // Mismatched brace or bracket.
+ token_ = TokenIllegal;
+ }
+ }
+}
+
+
+void JSONScanner::ScanString() {
+ ASSERT(*current_pos_ == '"');
+ ++current_pos_;
+ token_start_ = current_pos_;
+ while (*current_pos_ != '"') {
+ if (*current_pos_ == '\0') {
+ token_length_ = 0;
+ token_ = TokenIllegal;
+ return;
+ } else if (*current_pos_ == '\\') {
+ // TODO(hausner): Implement escape sequence.
+ UNIMPLEMENTED();
+ } else if (*current_pos_ < 0) {
+ // UTF-8 not supported.
+ token_length_ = 0;
+ token_ = TokenIllegal;
+ return;
+ } else {
+ ++current_pos_;
+ }
+ }
+ token_ = TokenString;
+ token_length_ = current_pos_ - token_start_;
+ ++current_pos_;
+}
+
+
+void JSONScanner::ScanNumber() {
+ if (*current_pos_ == '-') {
+ ++current_pos_;
+ }
+ if (!IsDigit(*current_pos_)) {
+ token_ = TokenIllegal;
+ token_length_ = 0;
+ return;
+ }
+ while (IsDigit(*current_pos_)) {
+ ++current_pos_;
+ }
+ if ((*current_pos_ == '.') ||
+ (*current_pos_ == 'e') ||
+ (*current_pos_ == 'E')) {
+ // Floating point numbers not supported.
+ token_ = TokenIllegal;
+ token_length_ = 0;
+ return;
+ }
+ token_ = TokenInteger;
+ token_length_ = current_pos_ - token_start_;
+}
+
+
+void JSONScanner::Scan() {
+ while ((*current_pos_ == ' ') ||
+ (*current_pos_ == '\t') ||
+ (*current_pos_ == '\n')) {
+ ++current_pos_;
+ }
+ token_start_ = current_pos_;
+ if (*current_pos_ == '\0') {
+ token_length_ = 0;
+ token_ = TokenEOM;
+ return;
+ }
+ switch (*current_pos_) {
+ case '{':
+ Recognize(TokenLBrace);
+ break;
+ case '}':
+ Recognize(TokenRBrace);
+ break;
+ case '[':
+ Recognize(TokenLBrack);
+ break;
+ case ']':
+ Recognize(TokenRBrack);
+ break;
+ case ':':
+ Recognize(TokenColon);
+ break;
+ case ',':
+ Recognize(TokenComma);
+ break;
+ case '"':
+ ScanString();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ ScanNumber();
+ break;
+ default:
+ if (IsLiteral("true")) {
+ token_ = TokenTrue;
+ token_length_ = 4;
+ } else if (IsLiteral("false")) {
+ token_ = TokenFalse;
+ token_length_ = 5;
+ } else if (IsLiteral("null")) {
+ token_ = TokenNull;
+ token_length_ = 4;
+ } else {
+ token_length_ = 0;
+ token_ = TokenIllegal;
+ }
+ }
+}
+
+
+JSONReader::JSONReader(const char* json_object)
+: scanner_(json_object) {
+ Set(json_object);
+}
+
+void JSONReader::Set(const char* json_object) {
+ scanner_.SetText(json_object);
+ json_object_ = json_object;
+ error_ = false;
+}
+
+
+bool JSONReader::Seek(const char* name) {
+ error_ = false;
+ scanner_.SetText(json_object_);
+ scanner_.Scan();
+ if (scanner_.CurrentToken() != JSONScanner::TokenLBrace) {
+ error_ = true;
+ return false;
+ }
+ scanner_.Scan();
+ if (scanner_.CurrentToken() == JSONScanner::TokenRBrace) {
+ return false;
+ }
+ while (scanner_.CurrentToken() == JSONScanner::TokenString) {
+ bool found = scanner_.IsStringLiteral(name);
+ scanner_.Scan();
+ if (scanner_.CurrentToken() != JSONScanner::TokenColon) {
+ error_ = true;
+ return false;
+ }
+ scanner_.Scan();
+ switch (scanner_.CurrentToken()) {
+ case JSONScanner::TokenString:
+ case JSONScanner::TokenInteger:
+ case JSONScanner::TokenLBrace:
+ case JSONScanner::TokenLBrack:
+ case JSONScanner::TokenTrue:
+ case JSONScanner::TokenFalse:
+ case JSONScanner::TokenNull:
+ // Found a legal value.
+ if (found) {
+ return true;
+ }
+ break;
+ default:
+ error_ = true;
+ return false;
+ }
+ // Skip the value.
+ if (scanner_.CurrentToken() == JSONScanner::TokenLBrace) {
+ scanner_.Skip(JSONScanner::TokenRBrace);
+ if (scanner_.CurrentToken() != JSONScanner::TokenRBrace) {
+ error_ = true;
+ return false;
+ }
+ } else if (scanner_.CurrentToken() == JSONScanner::TokenLBrack) {
+ scanner_.Skip(JSONScanner::TokenRBrack);
+ if (scanner_.CurrentToken() != JSONScanner::TokenRBrack) {
+ error_ = true;
+ return false;
+ }
+ }
+ scanner_.Scan(); // Value or closing brace or bracket.
+ if (scanner_.CurrentToken() == JSONScanner::TokenComma) {
+ scanner_.Scan();
+ } else if (scanner_.CurrentToken() == JSONScanner::TokenRBrace) {
+ return false;
+ } else {
+ error_ = true;
+ return false;
+ }
+ }
+ error_ = true;
+ return false;
+}
+
+
+const char* JSONReader::EndOfObject() {
+ bool found = Seek("***"); // Look for illegally named value.
+ ASSERT(!found);
+ if (!found && !error_) {
+ const char* s = scanner_.TokenChars();
+ ASSERT(*s == '}');
+ return s;
+ }
+ return NULL;
+}
+
+
+JSONReader::JSONType JSONReader::Type() const {
+ if (error_) {
+ return kNone;
+ }
+ switch (scanner_.CurrentToken()) {
+ case JSONScanner::TokenString:
+ return kString;
+ case JSONScanner::TokenInteger:
+ return kInteger;
+ case JSONScanner::TokenLBrace:
+ return kObject;
+ case JSONScanner::TokenLBrack:
+ return kArray;
+ case JSONScanner::TokenTrue:
+ case JSONScanner::TokenFalse:
+ case JSONScanner::TokenNull:
+ return kLiteral;
+ default:
+ return kNone;
+ }
+}
+
+
+TextBuffer::TextBuffer(intptr_t buf_size) {
+ ASSERT(buf_size > 0);
+ buf_ = reinterpret_cast<char*>(malloc(buf_size));
+ buf_size_ = buf_size;
+ Clear();
+}
+
+
+TextBuffer::~TextBuffer() {
+ free(buf_);
+ buf_ = NULL;
+}
+
+
+void TextBuffer::Clear() {
+ msg_len_ = 0;
+ buf_[0] = '\0';
+}
+
+
+intptr_t TextBuffer::Printf(const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ intptr_t remaining = buf_size_ - msg_len_;
+ ASSERT(remaining >= 0);
+ intptr_t len = OS::VSNPrint(buf_ + msg_len_, remaining, format, args);
+ va_end(args);
+ if (len >= remaining) {
+ const int kBufferSpareCapacity = 64; // Somewhat arbitrary.
+ GrowBuffer(len + kBufferSpareCapacity);
+ remaining = buf_size_ - msg_len_;
+ ASSERT(remaining > len);
+ va_list args2;
+ va_start(args2, format);
+ intptr_t len2 = OS::VSNPrint(buf_ + msg_len_, remaining, format, args2);
+ va_end(args2);
+ ASSERT(len == len2);
+ }
+ msg_len_ += len;
+ buf_[msg_len_] = '\0';
+ return len;
+}
+
+
+void TextBuffer::GrowBuffer(intptr_t len) {
+ intptr_t new_size = buf_size_ + len;
+ char* new_buf = reinterpret_cast<char*>(realloc(buf_, new_size));
+ ASSERT(new_buf != NULL);
+ buf_ = new_buf;
+ buf_size_ = new_size;
+}
+
+} // namespace dart
« no previous file with comments | « runtime/platform/json.h ('k') | runtime/platform/platform_headers.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698