// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/json/json_reader.h"

#include "base/json/json_parser.h"
#include "base/logging.h"

namespace base {

// Values 1000 and above are used by JSONFileValueSerializer::JsonFileError.
COMPILE_ASSERT(JSONReader::JSON_PARSE_ERROR_COUNT < 1000,
               json_reader_error_out_of_bounds);

const char JSONReader::kInvalidEscape[] =
    "Invalid escape sequence.";
const char JSONReader::kSyntaxError[] =
    "Syntax error.";
const char JSONReader::kUnexpectedToken[] =
    "Unexpected token.";
const char JSONReader::kTrailingComma[] =
    "Trailing comma not allowed.";
const char JSONReader::kTooMuchNesting[] =
    "Too much nesting.";
const char JSONReader::kUnexpectedDataAfterRoot[] =
    "Unexpected data after root element.";
const char JSONReader::kUnsupportedEncoding[] =
    "Unsupported encoding. JSON must be UTF-8.";
const char JSONReader::kUnquotedDictionaryKey[] =
    "Dictionary keys must be quoted.";

JSONReader::JSONReader()
    : parser_(new internal::JSONParser(JSON_PARSE_RFC)) {
}

JSONReader::JSONReader(int options)
    : parser_(new internal::JSONParser(options)) {
}

JSONReader::~JSONReader() {
}

// static
Value* JSONReader::Read(const StringPiece& json) {
  internal::JSONParser parser(JSON_PARSE_RFC);
  return parser.Parse(json);
}

// static
Value* JSONReader::Read(const StringPiece& json,
                        int options) {
  internal::JSONParser parser(options);
  return parser.Parse(json);
}

// static
Value* JSONReader::ReadAndReturnError(const StringPiece& json,
                                      int options,
                                      int* error_code_out,
                                      std::string* error_msg_out) {
  internal::JSONParser parser(options);
  Value* root = parser.Parse(json);
  if (root)
    return root;

  if (error_code_out)
    *error_code_out = parser.error_code();
  if (error_msg_out)
    *error_msg_out = parser.GetErrorMessage();

  return NULL;
}

// static
std::string JSONReader::ErrorCodeToString(JsonParseError error_code) {
  switch (error_code) {
    case JSON_NO_ERROR:
      return std::string();
    case JSON_INVALID_ESCAPE:
      return kInvalidEscape;
    case JSON_SYNTAX_ERROR:
      return kSyntaxError;
    case JSON_UNEXPECTED_TOKEN:
      return kUnexpectedToken;
    case JSON_TRAILING_COMMA:
      return kTrailingComma;
    case JSON_TOO_MUCH_NESTING:
      return kTooMuchNesting;
    case JSON_UNEXPECTED_DATA_AFTER_ROOT:
      return kUnexpectedDataAfterRoot;
    case JSON_UNSUPPORTED_ENCODING:
      return kUnsupportedEncoding;
    case JSON_UNQUOTED_DICTIONARY_KEY:
      return kUnquotedDictionaryKey;
    default:
      NOTREACHED();
      return std::string();
  }
}

Value* JSONReader::ReadToValue(const std::string& json) {
  return parser_->Parse(json);
}

JSONReader::JsonParseError JSONReader::error_code() const {
  return parser_->error_code();
}

std::string JSONReader::GetErrorMessage() const {
  return parser_->GetErrorMessage();
}

}  // namespace base
