// 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_writer.h"

#include <cmath>

#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "base/utf_string_conversions.h"

namespace base {

#if defined(OS_WIN)
static const char kPrettyPrintLineEnding[] = "\r\n";
#else
static const char kPrettyPrintLineEnding[] = "\n";
#endif

/* static */
const char* JSONWriter::kEmptyArray = "[]";

/* static */
void JSONWriter::Write(const Value* const node, std::string* json) {
  WriteWithOptions(node, 0, json);
}

/* static */
void JSONWriter::WriteWithOptions(const Value* const node, int options,
                                  std::string* json) {
  json->clear();
  // Is there a better way to estimate the size of the output?
  json->reserve(1024);

  bool escape = !(options & OPTIONS_DO_NOT_ESCAPE);
  bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES);
  bool omit_double_type_preservation =
      !!(options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION);
  bool pretty_print = !!(options & OPTIONS_PRETTY_PRINT);

  JSONWriter writer(escape, omit_binary_values, omit_double_type_preservation,
                    pretty_print, json);
  writer.BuildJSONString(node, 0);

  if (pretty_print)
    json->append(kPrettyPrintLineEnding);
}

JSONWriter::JSONWriter(bool escape, bool omit_binary_values,
                       bool omit_double_type_preservation, bool pretty_print,
                       std::string* json)
    : escape_(escape),
      omit_binary_values_(omit_binary_values),
      omit_double_type_preservation_(omit_double_type_preservation),
      pretty_print_(pretty_print),
      json_string_(json) {
  DCHECK(json);
}

void JSONWriter::BuildJSONString(const Value* const node, int depth) {
  switch (node->GetType()) {
    case Value::TYPE_NULL:
      json_string_->append("null");
      break;

    case Value::TYPE_BOOLEAN:
      {
        bool value;
        bool result = node->GetAsBoolean(&value);
        DCHECK(result);
        json_string_->append(value ? "true" : "false");
        break;
      }

    case Value::TYPE_INTEGER:
      {
        int value;
        bool result = node->GetAsInteger(&value);
        DCHECK(result);
        base::StringAppendF(json_string_, "%d", value);
        break;
      }

    case Value::TYPE_DOUBLE:
      {
        double value;
        bool result = node->GetAsDouble(&value);
        DCHECK(result);
        if (omit_double_type_preservation_ &&
            value <= kint64max &&
            value >= kint64min &&
            std::floor(value) == value) {
          json_string_->append(Int64ToString(static_cast<int64>(value)));
          break;
        }
        std::string real = DoubleToString(value);
        // Ensure that the number has a .0 if there's no decimal or 'e'.  This
        // makes sure that when we read the JSON back, it's interpreted as a
        // real rather than an int.
        if (real.find('.') == std::string::npos &&
            real.find('e') == std::string::npos &&
            real.find('E') == std::string::npos) {
          real.append(".0");
        }
        // The JSON spec requires that non-integer values in the range (-1,1)
        // have a zero before the decimal point - ".52" is not valid, "0.52" is.
        if (real[0] == '.') {
          real.insert(0, "0");
        } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
          // "-.1" bad "-0.1" good
          real.insert(1, "0");
        }
        json_string_->append(real);
        break;
      }

    case Value::TYPE_STRING:
      {
        std::string value;
        bool result = node->GetAsString(&value);
        DCHECK(result);
        if (escape_) {
          JsonDoubleQuote(UTF8ToUTF16(value), true, json_string_);
        } else {
          JsonDoubleQuote(value, true, json_string_);
        }
        break;
      }

    case Value::TYPE_LIST:
      {
        json_string_->append("[");
        if (pretty_print_)
          json_string_->append(" ");

        const ListValue* list = static_cast<const ListValue*>(node);
        for (size_t i = 0; i < list->GetSize(); ++i) {
          const Value* value = NULL;
          bool result = list->Get(i, &value);
          DCHECK(result);

          if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY) {
            continue;
          }

          if (i != 0) {
            json_string_->append(",");
            if (pretty_print_)
              json_string_->append(" ");
          }

          BuildJSONString(value, depth);
        }

        if (pretty_print_)
          json_string_->append(" ");
        json_string_->append("]");
        break;
      }

    case Value::TYPE_DICTIONARY:
      {
        json_string_->append("{");
        if (pretty_print_)
          json_string_->append(kPrettyPrintLineEnding);

        const DictionaryValue* dict =
          static_cast<const DictionaryValue*>(node);
        for (DictionaryValue::key_iterator key_itr = dict->begin_keys();
             key_itr != dict->end_keys();
             ++key_itr) {
          const Value* value = NULL;
          bool result = dict->GetWithoutPathExpansion(*key_itr, &value);
          DCHECK(result);

          if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY) {
            continue;
          }

          if (key_itr != dict->begin_keys()) {
            json_string_->append(",");
            if (pretty_print_)
              json_string_->append(kPrettyPrintLineEnding);
          }

          if (pretty_print_)
            IndentLine(depth + 1);
          AppendQuotedString(*key_itr);
          if (pretty_print_) {
            json_string_->append(": ");
          } else {
            json_string_->append(":");
          }
          BuildJSONString(value, depth + 1);
        }

        if (pretty_print_) {
          json_string_->append(kPrettyPrintLineEnding);
          IndentLine(depth);
          json_string_->append("}");
        } else {
          json_string_->append("}");
        }
        break;
      }

    case Value::TYPE_BINARY:
      {
        if (!omit_binary_values_) {
          NOTREACHED() << "Cannot serialize binary value.";
        }
        break;
      }

    default:
      NOTREACHED() << "unknown json type";
  }
}

void JSONWriter::AppendQuotedString(const std::string& str) {
  // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we
  // have to convert it to UTF-16. This round-trip is suboptimal.
  JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_);
}

void JSONWriter::IndentLine(int depth) {
  // It may be faster to keep an indent string so we don't have to keep
  // reallocating.
  json_string_->append(std::string(depth * 3, ' '));
}

}  // namespace base
