1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2007-2011 Baptiste Lepilleur 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Distributed under MIT license, or public domain if desired and 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// recognized in your jurisdiction. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if !defined(JSON_IS_AMALGAMATION) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# include <json/assertions.h> 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# include <json/reader.h> 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# include <json/value.h> 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# include "json_tool.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif // if !defined(JSON_IS_AMALGAMATION) 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <utility> 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <cstdio> 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <cassert> 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <cstring> 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <stdexcept> 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string> 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <istream> 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if _MSC_VER >= 1400 // VC++ 8.0 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace Json { 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Implementation of class Features 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// //////////////////////////////// 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Features::Features() 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : allowComments_( true ) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) , strictRoot_( false ) 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Features 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Features::all() 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return Features(); 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Features 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Features::strictMode() 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Features features; 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) features.allowComments_ = false; 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) features.strictRoot_ = true; 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return features; 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Implementation of class Reader 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// //////////////////////////////// 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static inline bool 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return c == c1 || c == c2 || c == c3 || c == c4; 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static inline bool 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static bool 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)containsNewLine( Reader::Location begin, 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Reader::Location end ) 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for ( ;begin < end; ++begin ) 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( *begin == '\n' || *begin == '\r' ) 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Class Reader 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// ////////////////////////////////////////////////////////////////// 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::Reader() 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : errors_(), 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) document_(), 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) begin_(), 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) end_(), 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current_(), 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValueEnd_(), 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValue_(), 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) commentsBefore_(), 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) features_( Features::all() ), 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) collectComments_() 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::Reader( const Features &features ) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : errors_(), 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) document_(), 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) begin_(), 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) end_(), 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current_(), 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValueEnd_(), 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValue_(), 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) commentsBefore_(), 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) features_( features ), 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) collectComments_() 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::parse( const std::string &document, 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value &root, 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool collectComments ) 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) document_ = document; 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char *begin = document_.c_str(); 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char *end = begin + document_.length(); 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return parse( begin, end, root, collectComments ); 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::parse( std::istream& sin, 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value &root, 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool collectComments ) 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) //std::istream_iterator<char> begin(sin); 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) //std::istream_iterator<char> end; 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Those would allow streamed input from a file, if parse() were a 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // template function. 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Since std::string is reference-counted, this at least does not 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // create an extra copy. 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string doc; 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::getline(sin, doc, (char)EOF); 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return parse( doc, root, collectComments ); 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::parse( const char *beginDoc, const char *endDoc, 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value &root, 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool collectComments ) 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !features_.allowComments_ ) 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) collectComments = false; 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) begin_ = beginDoc; 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) end_ = endDoc; 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) collectComments_ = collectComments; 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current_ = begin_; 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValueEnd_ = 0; 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValue_ = 0; 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) commentsBefore_ = ""; 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) errors_.clear(); 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( !nodes_.empty() ) 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) nodes_.pop(); 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) nodes_.push( &root ); 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool successful = readValue(); 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token token; 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) skipCommentTokens( token ); 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( collectComments_ && !commentsBefore_.empty() ) 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) root.setComment( commentsBefore_, commentAfter ); 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( features_.strictRoot_ ) 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !root.isArray() && !root.isObject() ) 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Set error location to start of doc, ideally should be first token found in doc 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenError; 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.start_ = beginDoc; 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.end_ = endDoc; 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) addError( "A valid JSON document must be either an array or an object value.", 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token ); 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return successful; 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readValue() 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token token; 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) skipCommentTokens( token ); 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool successful = true; 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( collectComments_ && !commentsBefore_.empty() ) 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue().setComment( commentsBefore_, commentBefore ); 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) commentsBefore_ = ""; 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch ( token.type_ ) 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenObjectBegin: 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) successful = readObject( token ); 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenArrayBegin: 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) successful = readArray( token ); 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenNumber: 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) successful = decodeNumber( token ); 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenString: 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) successful = decodeString( token ); 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenTrue: 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = true; 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenFalse: 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = false; 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case tokenNull: 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = Value(); 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "Syntax error: value, object or array expected.", token ); 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( collectComments_ ) 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValueEnd_ = current_; 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValue_ = ¤tValue(); 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return successful; 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::skipCommentTokens( Token &token ) 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( features_.allowComments_ ) 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) do 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) readToken( token ); 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( token.type_ == tokenComment ); 247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) readToken( token ); 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::expectToken( TokenType type, Token &token, const char *message ) 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) readToken( token ); 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( token.type_ != type ) 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( message, token ); 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readToken( Token &token ) 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) skipSpaces(); 269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.start_ = current_; 270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = getNextChar(); 271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool ok = true; 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch ( c ) 273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '{': 275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenObjectBegin; 276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '}': 278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenObjectEnd; 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '[': 281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenArrayBegin; 282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case ']': 284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenArrayEnd; 285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '"': 287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenString; 288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = readString(); 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '/': 291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenComment; 292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = readComment(); 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '0': 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '1': 296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '2': 297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '3': 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '4': 299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '5': 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '6': 301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '7': 302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '8': 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '9': 304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '-': 305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenNumber; 306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) readNumber(); 307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 't': 309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenTrue; 310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = match( "rue", 3 ); 311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'f': 313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenFalse; 314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = match( "alse", 4 ); 315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'n': 317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenNull; 318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = match( "ull", 3 ); 319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case ',': 321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenArraySeparator; 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case ':': 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenMemberSeparator; 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 0: 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenEndOfStream; 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = false; 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !ok ) 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ = tokenError; 335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.end_ = current_; 336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::skipSpaces() 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current_ != end_ ) 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = *current_; 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++current_; 348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::match( Location pattern, 356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int patternLength ) 357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( end_ - current_ < patternLength ) 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int index = patternLength; 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( index-- ) 362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( current_[index] != pattern[index] ) 363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current_ += patternLength; 365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readComment() 371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location commentBegin = current_ - 1; 373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = getNextChar(); 374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool successful = false; 375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == '*' ) 376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) successful = readCStyleComment(); 377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( c == '/' ) 378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) successful = readCppStyleComment(); 379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !successful ) 380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( collectComments_ ) 383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CommentPlacement placement = commentBefore; 385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) 386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) 388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) placement = commentAfterOnSameLine; 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) addComment( commentBegin, current_, placement ); 392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::addComment( Location begin, 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location end, 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CommentPlacement placement ) 401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) assert( collectComments_ ); 403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( placement == commentAfterOnSameLine ) 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) assert( lastValue_ != 0 ); 406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastValue_->setComment( std::string( begin, end ), placement ); 407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !commentsBefore_.empty() ) 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) commentsBefore_ += "\n"; 412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) commentsBefore_ += std::string( begin, end ); 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readCStyleComment() 419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current_ != end_ ) 421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = getNextChar(); 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == '*' && *current_ == '/' ) 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return getNextChar() == '/'; 427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readCppStyleComment() 432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current_ != end_ ) 434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = getNextChar(); 436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == '\r' || c == '\n' ) 437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void 444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readNumber() 445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current_ != end_ ) 447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !(*current_ >= '0' && *current_ <= '9') && 449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !in( *current_, '.', 'e', 'E', '+', '-' ) ) 450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++current_; 452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readString() 457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = 0; 459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current_ != end_ ) 460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) c = getNextChar(); 462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == '\\' ) 463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) getNextChar(); 464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( c == '"' ) 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return c == '"'; 468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readObject( Token &/*tokenStart*/ ) 473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token tokenName; 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string name; 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = Value( objectValue ); 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( readToken( tokenName ) ) 478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool initialTokenOk = true; 480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( tokenName.type_ == tokenComment && initialTokenOk ) 481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) initialTokenOk = readToken( tokenName ); 482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !initialTokenOk ) 483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object 485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( tokenName.type_ != tokenString ) 487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) name = ""; 490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !decodeString( tokenName, name ) ) 491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return recoverFromError( tokenObjectEnd ); 492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token colon; 494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) 495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addErrorAndRecover( "Missing ':' after object member name", 497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) colon, 498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tokenObjectEnd ); 499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value &value = currentValue()[ name ]; 501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) nodes_.push( &value ); 502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool ok = readValue(); 503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) nodes_.pop(); 504a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !ok ) // error already set 505a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return recoverFromError( tokenObjectEnd ); 506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token comma; 508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !readToken( comma ) 509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) || ( comma.type_ != tokenObjectEnd && 510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) comma.type_ != tokenArraySeparator && 511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) comma.type_ != tokenComment ) ) 512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addErrorAndRecover( "Missing ',' or '}' in object declaration", 514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) comma, 515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tokenObjectEnd ); 516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool finalizeTokenOk = true; 518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( comma.type_ == tokenComment && 519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) finalizeTokenOk ) 520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) finalizeTokenOk = readToken( comma ); 521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( comma.type_ == tokenObjectEnd ) 522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addErrorAndRecover( "Missing '}' or object member name", 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tokenName, 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tokenObjectEnd ); 527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::readArray( Token &/*tokenStart*/ ) 532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = Value( arrayValue ); 534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) skipSpaces(); 535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( *current_ == ']' ) // empty array 536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token endArray; 538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) readToken( endArray ); 539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int index = 0; 542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (;;) 543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 544a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value &value = currentValue()[ index++ ]; 545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) nodes_.push( &value ); 546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool ok = readValue(); 547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) nodes_.pop(); 548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !ok ) // error already set 549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return recoverFromError( tokenArrayEnd ); 550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token token; 552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Accept Comment after last item in the array. 553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = readToken( token ); 554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( token.type_ == tokenComment && ok ) 555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ok = readToken( token ); 557a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 558a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool badTokenType = ( token.type_ != tokenArraySeparator && 559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token.type_ != tokenArrayEnd ); 560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !ok || badTokenType ) 561a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 562a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addErrorAndRecover( "Missing ',' or ']' in array declaration", 563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) token, 564a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tokenArrayEnd ); 565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 566a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( token.type_ == tokenArrayEnd ) 567a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 569a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 570a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 571a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 572a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 574a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::decodeNumber( Token &token ) 575a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 576a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool isDouble = false; 577a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) 578a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 579a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) isDouble = isDouble 580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) || in( *inspect, '.', 'e', 'E', '+' ) 581a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) || ( *inspect == '-' && inspect != token.start_ ); 582a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 583a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( isDouble ) 584a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return decodeDouble( token ); 585a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Attempts to parse the number as an integer. If the number is 586a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // larger than the maximum supported value of an integer then 587a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // we decode the number as a double. 588a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location current = token.start_; 589a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool isNegative = *current == '-'; 590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( isNegative ) 591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++current; 592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) 593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : Value::maxLargestUInt; 594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value::LargestUInt threshold = maxIntegerValue / 10; 595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value::LargestUInt value = 0; 596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current < token.end_ ) 597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = *current++; 599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c < '0' || c > '9' ) 600a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); 601a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Value::UInt digit(c - '0'); 602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( value >= threshold ) 603a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We've hit or exceeded the max value divided by 10 (rounded down). If 605a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // a) we've only just touched the limit, b) this is the last digit, and 606a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // c) it's small enough to fit in that rounding delta, we're okay. 607a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Otherwise treat this number as a double to avoid overflow. 608a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (value > threshold || 609a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) current != token.end_ || 610a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) digit > maxIntegerValue % 10) 611a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 612a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return decodeDouble( token ); 613a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 614a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 615a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) value = value * 10 + digit; 616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 617a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( isNegative ) 618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = -Value::LargestInt( value ); 619a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( value <= Value::LargestUInt(Value::maxInt) ) 620a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = Value::LargestInt( value ); 621a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 622a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = value; 623a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 624a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::decodeDouble( Token &token ) 629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) double value = 0; 631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const int bufferSize = 32; 632a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int count; 633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int length = int(token.end_ - token.start_); 634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 635a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Sanity check to avoid buffer overflow exploits. 636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (length < 0) { 637a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "Unable to parse token length", token ); 638a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 639a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 640a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Avoid using a string constant for the format control string given to 641a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // sscanf, as this can cause hard to debug crashes on OS X. See here for more 642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // info: 643a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // 644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html 645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) char format[] = "%lf"; 646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( length <= bufferSize ) 648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char buffer[bufferSize+1]; 650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memcpy( buffer, token.start_, length ); 651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) buffer[length] = 0; 652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) count = sscanf( buffer, format, &value ); 653a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 655a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string buffer( token.start_, token.end_ ); 657a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) count = sscanf( buffer.c_str(), format, &value ); 658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( count != 1 ) 661a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); 662a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = value; 663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 664a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 666a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 667a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::decodeString( Token &token ) 669a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string decoded; 671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !decodeString( token, decoded ) ) 672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) currentValue() = decoded; 674a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::decodeString( Token &token, std::string &decoded ) 680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decoded.reserve( token.end_ - token.start_ - 2 ); 682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location current = token.start_ + 1; // skip '"' 683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location end = token.end_ - 1; // do not include '"' 684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current != end ) 685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = *current++; 687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == '"' ) 688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( c == '\\' ) 690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( current == end ) 692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "Empty escape sequence in string", token, current ); 693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char escape = *current++; 694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch ( escape ) 695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '"': decoded += '"'; break; 697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '/': decoded += '/'; break; 698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case '\\': decoded += '\\'; break; 699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'b': decoded += '\b'; break; 700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'f': decoded += '\f'; break; 701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'n': decoded += '\n'; break; 702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'r': decoded += '\r'; break; 703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 't': decoded += '\t'; break; 704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case 'u': 705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned int unicode; 707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) 708a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 709a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decoded += codePointToUTF8(unicode); 710a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 711a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "Bad escape sequence in string", token, current ); 714a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 717a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decoded += c; 719a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 720a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 721a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 725a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::decodeUnicodeCodePoint( Token &token, 726a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location ¤t, 727a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location end, 728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned int &unicode ) 729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 730a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 731a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) 732a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (unicode >= 0xD800 && unicode <= 0xDBFF) 734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // surrogate pairs 736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (end - current < 6) 737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); 738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned int surrogatePair; 739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*(current++) == '\\' && *(current++)== 'u') 740a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 741a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) 742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); 750a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 751a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 752a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::decodeUnicodeEscapeSequence( Token &token, 756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location ¤t, 757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location end, 758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned int &unicode ) 759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 760a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( end - current < 4 ) 761a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); 762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unicode = 0; 763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for ( int index =0; index < 4; ++index ) 764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = *current++; 766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unicode *= 16; 767a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c >= '0' && c <= '9' ) 768a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unicode += c - '0'; 769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( c >= 'a' && c <= 'f' ) 770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unicode += c - 'a' + 10; 771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( c >= 'A' && c <= 'F' ) 772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unicode += c - 'A' + 10; 773a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); 775a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 776a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 777a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 778a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 779a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 780a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 781a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::addError( const std::string &message, 782a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token &token, 783a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location extra ) 784a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 785a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ErrorInfo info; 786a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) info.token_ = token; 787a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) info.message_ = message; 788a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) info.extra_ = extra; 789a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) errors_.push_back( info ); 790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 791a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 792a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 793a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::recoverFromError( TokenType skipUntilToken ) 796a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int errorCount = int(errors_.size()); 798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token skip; 799a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (;;) 800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( !readToken(skip) ) 802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) errors_.resize( errorCount ); // discard errors caused by recovery 803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) 804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 805a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 806a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) errors_.resize( errorCount ); 807a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 808a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 809a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 810a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool 812a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::addErrorAndRecover( const std::string &message, 813a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Token &token, 814a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TokenType skipUntilToken ) 815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 816a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) addError( message, token ); 817a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return recoverFromError( skipUntilToken ); 818a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Value & 822a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::currentValue() 823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return *(nodes_.top()); 825a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 826a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 827a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::Char 829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::getNextChar() 830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( current_ == end_ ) 832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return *current_++; 834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 836a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void 838a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::getLocationLineAndColumn( Location location, 839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int &line, 840a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int &column ) const 841a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 842a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location current = begin_; 843a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Location lastLineStart = current; 844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) line = 0; 845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while ( current < location && current != end_ ) 846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 847a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Char c = *current++; 848a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( c == '\r' ) 849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( *current == '\n' ) 851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++current; 852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastLineStart = current; 853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++line; 854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else if ( c == '\n' ) 856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 857a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) lastLineStart = current; 858a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++line; 859a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 861a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // column & line start at 1 862a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) column = int(location - lastLineStart) + 1; 863a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++line; 864a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 865a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 866a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 867a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string 868a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::getLocationLineAndColumn( Location location ) const 869a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 870a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int line, column; 871a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) getLocationLineAndColumn( location, line, column ); 872a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) char buffer[18+16+16+1]; 873a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sprintf( buffer, "Line %d, Column %d", line, column ); 874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return buffer; 875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 876a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 877a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 878a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Deprecated. Preserved for backward compatibility 879a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string 880a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::getFormatedErrorMessages() const 881a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 882a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return getFormattedErrorMessages(); 883a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 884a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 885a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 886a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Reader::getFormattedErrorMessages() const 888a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 889a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string formattedMessage; 890a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for ( Errors::const_iterator itError = errors_.begin(); 891a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) itError != errors_.end(); 892a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++itError ) 893a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 894a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const ErrorInfo &error = *itError; 895a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; 896a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) formattedMessage += " " + error.message_ + "\n"; 897a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ( error.extra_ ) 898a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; 899a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 900a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return formattedMessage; 901a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 902a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::istream& operator>>( std::istream &sin, Value &root ) 905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles){ 906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Json::Reader reader; 907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool ok = reader.parse(sin, root, true); 908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!ok) { 909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fprintf( 910a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stderr, 911a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Error from reader: %s", 912a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reader.getFormattedErrorMessages().c_str()); 913a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 914a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) JSON_FAIL_MESSAGE("reader error"); 915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 916a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return sin; 917a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 918a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 919a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 920a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace Json 921