Squashed 'third_party/jsont/' content from commit 1536152d7

Change-Id: I51a80190772b74ca0d45fd3fadc130e872b57cc0
git-subtree-dir: third_party/jsont
git-subtree-split: 1536152d7c1926448d42e4a691acd9a15940b20c
diff --git a/jsont.hh b/jsont.hh
new file mode 100644
index 0000000..3e86cad
--- /dev/null
+++ b/jsont.hh
@@ -0,0 +1,420 @@
+// JSON Tokenizer and builder. Copyright (c) 2012, Rasmus Andersson. All rights
+// reserved. Use of this source code is governed by a MIT-style license that can
+// be found in the LICENSE file.
+#ifndef JSONT_CXX_INCLUDED
+#define JSONT_CXX_INCLUDED
+
+#include <stdint.h>  // uint8_t, int64_t
+#include <stdlib.h>  // size_t
+#include <string.h>  // strlen
+#include <stdbool.h> // bool
+#include <math.h>
+#include <assert.h>
+#include <string>
+#include <stdexcept>
+
+// Can haz rvalue references with move semantics?
+#if (defined(_MSC_VER) && _MSC_VER >= 1600) || \
+    (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__) || \
+    (defined(__has_feature) && __has_feature(cxx_rvalue_references))
+  #define JSONT_CXX_RVALUE_REFS 1
+#else
+  #define JSONT_CXX_RVALUE_REFS 0
+#endif
+
+namespace jsont {
+
+// Tokens
+typedef enum {
+  End = 0,       // Input ended
+  ObjectStart,   // {
+  ObjectEnd,     // }
+  ArrayStart,    // [
+  ArrayEnd,      // ]
+  True,          // true
+  False,         // false
+  Null,          // null
+  Integer,       // number value without a fraction part
+  Float,         // number value with a fraction part
+  String,        // string value
+  FieldName,     // field name
+  Error,         // An error occured (see `error()` for details)
+  _Comma,
+} Token;
+
+// String encoding
+typedef enum {
+  UTF8TextEncoding = 0,
+} TextEncoding;
+
+// Name of `token`
+const char* token_name(jsont::Token token);
+
+class TokenizerInternal;
+
+// Reads a sequence of bytes and produces tokens and values while doing so
+class Tokenizer {
+public:
+  Tokenizer(const char* bytes, size_t length, TextEncoding encoding);
+  ~Tokenizer();
+
+  // Read next token
+  const Token& next();
+
+  // Access current token
+  const Token& current() const;
+
+  // Reset the tokenizer, making it possible to reuse this parser so to avoid
+  // unnecessary memory allocation and deallocation.
+  void reset(const char* bytes, size_t length, TextEncoding encoding);
+
+  // True if the current token has a value
+  bool hasValue() const;
+
+  // Returns a slice of the input which represents the current value, or nothing
+  // (returns 0) if the current token has no value (e.g. start of an object).
+  size_t dataValue(const char const** bytes) const;
+
+  // Returns a *copy* of the current string value.
+  std::string stringValue() const;
+
+  // Returns the current value as a double-precision floating-point number.
+  double floatValue() const;
+
+  // Returns the current value as a signed 64-bit integer.
+  int64_t intValue() const;
+
+  // Returns the current value as a boolean
+  bool boolValue() const;
+
+  // Error codes
+  typedef enum {
+    UnspecifiedError = 0,
+    UnexpectedComma,
+    UnexpectedTrailingComma,
+    InvalidByte,
+    PrematureEndOfInput,
+    MalformedUnicodeEscapeSequence,
+    MalformedNumberLiteral,
+    UnterminatedString,
+    SyntaxError,
+  } ErrorCode;
+
+  // Returns the error code of the last error
+  ErrorCode error() const;
+
+  // Returns a human-readable message for the last error. Never returns NULL.
+  const char* errorMessage() const;
+
+  // The byte offset into input where the tokenizer is currently looking. In the
+  // event of an error, this will point to the source of the error.
+  size_t inputOffset() const;
+
+  // Total number of input bytes
+  size_t inputSize() const;
+
+  // A pointer to the input data as passed to `reset` or the constructor.
+  const char* inputBytes() const;
+
+  friend class TokenizerInternal;
+private:
+  size_t availableInput() const;
+  size_t endOfInput() const;
+  const Token& setToken(Token t);
+  const Token& setError(ErrorCode error);
+
+  struct {
+    const uint8_t* bytes;
+    size_t length;
+    size_t offset;
+  } _input;
+  struct Value {
+    Value() : offset(0), length(0), buffered(false) {}
+    void beginAtOffset(size_t z);
+    size_t offset; // into _input.bytes
+    size_t length;
+    std::string buffer;
+    bool buffered; // if true, contents lives in buffer
+  } _value;
+  Token _token;
+  struct {
+    ErrorCode code;
+  } _error;
+};
+
+
+// Helps in building JSON, providing a final sequential byte buffer
+class Builder {
+public:
+  Builder() : _buf(0), _capacity(0), _size(0), _state(NeutralState) {}
+  ~Builder() { if (_buf) { free(_buf); _buf = 0; } }
+  Builder(const Builder& other);
+  Builder& operator=(const Builder& other);
+#if JSONT_CXX_RVALUE_REFS
+  Builder(Builder&& other);
+  Builder& operator=(Builder&& other);
+#endif
+
+  Builder& startObject();
+  Builder& endObject();
+  Builder& startArray();
+  Builder& endArray();
+  Builder& fieldName(const char* v, size_t length, TextEncoding e=UTF8TextEncoding);
+  Builder& fieldName(const std::string& name, TextEncoding enc=UTF8TextEncoding);
+  Builder& value(const char* v, size_t length, TextEncoding e=UTF8TextEncoding);
+  Builder& value(const char* v);
+  Builder& value(const std::string& v);
+  Builder& value(double v);
+  Builder& value(int64_t v);
+  Builder& value(int v);
+  Builder& value(unsigned int v);
+  Builder& value(long v);
+  Builder& value(bool v);
+  Builder& nullValue();
+
+  size_t size() const;
+  const char* bytes() const;
+  std::string toString() const;
+  const char* seizeBytes(size_t& size_out);
+  const void reset();
+
+private:
+  size_t available() const;
+  void reserve(size_t size);
+  void prefix();
+  Builder& appendString(const uint8_t* v, size_t length, TextEncoding enc);
+  Builder& appendChar(char byte);
+
+  char*  _buf;
+  size_t _capacity;
+  size_t _size;
+  enum {
+    NeutralState = 0,
+    AfterFieldName,
+    AfterValue,
+    AfterObjectStart,
+    AfterArrayStart,
+  } _state;
+};
+
+
+// Convenience function
+inline Builder build() { return Builder(); }
+
+
+// ------------------- internal ---------------------
+
+inline Tokenizer::Tokenizer(const char* bytes, size_t length,
+    TextEncoding encoding) : _token(End) {
+  reset(bytes, length, encoding);
+}
+
+inline const Token& Tokenizer::current() const { return _token; }
+
+inline bool Tokenizer::hasValue() const {
+  return _token >= Integer && _token <= FieldName;
+}
+
+inline std::string Tokenizer::stringValue() const {
+  const char* bytes;
+  size_t size = dataValue(&bytes);
+  return std::string(bytes, size);
+}
+
+inline bool Tokenizer::boolValue() const {
+  return _token == True;
+}
+
+inline size_t Tokenizer::availableInput() const {
+  return _input.length - _input.offset;
+}
+inline size_t Tokenizer::endOfInput() const {
+  return _input.offset == _input.length;
+}
+inline const Token& Tokenizer::setToken(Token t) {
+  return _token = t;
+}
+inline const Token& Tokenizer::setError(Tokenizer::ErrorCode error) {
+  _error.code = error;
+  return _token = Error;
+}
+inline size_t Tokenizer::inputOffset() const {
+  return _input.offset;
+}
+inline size_t Tokenizer::inputSize() const {
+  return _input.length;
+}
+inline const char* Tokenizer::inputBytes() const {
+  return (const char*)_input.bytes;
+}
+
+inline void Tokenizer::Value::beginAtOffset(size_t z) {
+  offset = z;
+  length = 0;
+  buffered = false;
+}
+
+inline Tokenizer::ErrorCode Tokenizer::error() const {
+  return _error.code;
+}
+
+
+inline Builder& Builder::startObject() {
+  prefix();
+  _state = AfterObjectStart;
+  return appendChar('{');
+}
+
+inline Builder& Builder::endObject() {
+  _state = AfterValue;
+  return appendChar('}');
+}
+
+inline Builder& Builder::startArray() {
+  prefix();
+  _state = AfterArrayStart;
+  return appendChar('[');
+}
+
+inline Builder& Builder::endArray() {
+  _state = AfterValue;
+  return appendChar(']');
+}
+
+inline Builder& Builder::fieldName(const std::string& name, TextEncoding enc) {
+  return fieldName(name.data(), name.size(), enc);
+}
+
+inline Builder& Builder::fieldName(const char* v, size_t length,
+    TextEncoding enc) {
+  prefix();
+  _state = AfterFieldName;
+  return appendString((const uint8_t*)v, length, enc);
+}
+
+inline Builder& Builder::value(const char* v, size_t length, TextEncoding enc) {
+  prefix();
+  _state = AfterValue;
+  return appendString((const uint8_t*)v, length, enc);
+}
+
+inline Builder& Builder::value(const char* v) {
+  return value(v, strlen(v));
+}
+
+inline Builder& Builder::value(const std::string& v) {
+  return value(v.data(), v.size());
+}
+
+inline Builder& Builder::value(double v) {
+  prefix();
+  reserve(256);
+  int z = snprintf(_buf+_size, 256, "%g", v);
+  assert(z < 256);
+  _size += z;
+  _state = AfterValue;
+  return *this;
+}
+
+inline Builder& Builder::value(int64_t v) {
+  prefix();
+  reserve(21);
+  int z = snprintf(_buf+_size, 21, "%lld", v);
+  assert(z < 21);
+  _size += z;
+  _state = AfterValue;
+  return *this;
+}
+
+inline Builder& Builder::value(int v) { return value((int64_t)v); }
+inline Builder& Builder::value(unsigned int v) { return value((int64_t)v); }
+inline Builder& Builder::value(long v) { return value((int64_t)v); }
+
+inline Builder& Builder::value(bool v) {
+  prefix();
+  if (v) {
+    reserve(4);
+    _buf[_size]   = 't';
+    _buf[++_size] = 'r';
+    _buf[++_size] = 'u';
+    _buf[++_size] = 'e';
+    ++_size;
+  } else {
+    reserve(5);
+    _buf[_size]   = 'f';
+    _buf[++_size] = 'a';
+    _buf[++_size] = 'l';
+    _buf[++_size] = 's';
+    _buf[++_size] = 'e';
+    ++_size;
+  }
+  _state = AfterValue;
+  return *this;
+}
+
+inline Builder& Builder::nullValue() {
+  prefix();
+  reserve(4);
+  _buf[_size]   = 'n';
+  _buf[++_size] = 'u';
+  _buf[++_size] = 'l';
+  _buf[++_size] = 'l';
+  ++_size;
+  _state = AfterValue;
+  return *this;
+}
+
+inline size_t Builder::size() const { return _size; }
+inline const char* Builder::bytes() const { return _buf; }
+inline std::string Builder::toString() const {
+  return std::string(bytes(), size());
+}
+inline const char* Builder::seizeBytes(size_t& size_out) {
+  const char* buf = _buf;
+  size_out = _size;
+  _buf = 0;
+  _capacity = 0;
+  reset();
+  return buf;
+}
+inline const void Builder::reset() {
+  _size = 0;
+  _state = NeutralState;
+}
+
+inline size_t Builder::available() const {
+  return _capacity - _size;
+}
+
+inline void Builder::reserve(size_t size) {
+  if (available() < size) {
+    #if 0
+    // exact allocation for debugging purposes
+    printf("DEBUG Builder::reserve: size=%zu available=%zu grow_by=%zu\n",
+      size, available(), (size - available()) );
+    _capacity += size - available();
+    #else
+    _capacity += size - available();
+    _capacity = (_capacity < 64) ? 64 : (_capacity * 1.5);
+    #endif
+    _buf = (char*)realloc((void*)_buf, _capacity);
+  }
+}
+
+inline void Builder::prefix() {
+  if (_state == AfterFieldName) {
+    appendChar(':');
+  } else if (_state == AfterValue) {
+    appendChar(',');
+  }
+}
+
+inline Builder& Builder::appendChar(char byte) {
+  reserve(1);
+  _buf[_size++] = byte;
+  return *this;
+}
+
+}
+
+#endif // JSONT_CXX_INCLUDED