15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/string_escape.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kPrettyPrintLineEnding[] = "\r\n";
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kPrettyPrintLineEnding[] = "\n";
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool JSONWriter::Write(const Value* const node, std::string* json) {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return WriteWithOptions(node, 0, json);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool JSONWriter::WriteWithOptions(const Value* const node, int options,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  std::string* json) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  json->clear();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Is there a better way to estimate the size of the output?
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  json->reserve(1024);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  JSONWriter writer(options, json);
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool result = writer.BuildJSONString(node, 0U);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (options & OPTIONS_PRETTY_PRINT)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    json->append(kPrettyPrintLineEnding);
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)JSONWriter::JSONWriter(int options, std::string* json)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : omit_binary_values_((options & OPTIONS_OMIT_BINARY_VALUES) != 0),
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      omit_double_type_preservation_(
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          (options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION) != 0),
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pretty_print_((options & OPTIONS_PRETTY_PRINT) != 0),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      json_string_(json) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(json);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool JSONWriter::BuildJSONString(const Value* const node, size_t depth) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (node->GetType()) {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_NULL: {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      json_string_->append("null");
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_BOOLEAN: {
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool value;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool result = node->GetAsBoolean(&value);
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(result);
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->append(value ? "true" : "false");
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return result;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_INTEGER: {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int value;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool result = node->GetAsInteger(&value);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(result);
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->append(IntToString(value));
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return result;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_DOUBLE: {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      double value;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool result = node->GetAsDouble(&value);
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(result);
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (omit_double_type_preservation_ &&
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          value <= kint64max &&
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          value >= kint64min &&
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          std::floor(value) == value) {
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        json_string_->append(Int64ToString(static_cast<int64>(value)));
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return result;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string real = DoubleToString(value);
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Ensure that the number has a .0 if there's no decimal or 'e'.  This
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // makes sure that when we read the JSON back, it's interpreted as a
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // real rather than an int.
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (real.find('.') == std::string::npos &&
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          real.find('e') == std::string::npos &&
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          real.find('E') == std::string::npos) {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        real.append(".0");
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // The JSON spec requires that non-integer values in the range (-1,1)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // have a zero before the decimal point - ".52" is not valid, "0.52" is.
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (real[0] == '.') {
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        real.insert(static_cast<size_t>(0), static_cast<size_t>(1), '0');
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // "-.1" bad "-0.1" good
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        real.insert(static_cast<size_t>(1), static_cast<size_t>(1), '0');
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->append(real);
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return result;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_STRING: {
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string value;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool result = node->GetAsString(&value);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(result);
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EscapeJSONString(value, true, json_string_);
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return result;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_LIST: {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->push_back('[');
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (pretty_print_)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        json_string_->push_back(' ');
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const ListValue* list = NULL;
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool first_value_has_been_output = false;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool result = node->GetAsList(&list);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(result);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (ListValue::const_iterator it = list->begin(); it != list->end();
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           ++it) {
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const Value* value = *it;
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          continue;
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (first_value_has_been_output) {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          json_string_->push_back(',');
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          if (pretty_print_)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            json_string_->push_back(' ');
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!BuildJSONString(value, depth))
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          result = false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        first_value_has_been_output = true;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (pretty_print_)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        json_string_->push_back(' ');
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->push_back(']');
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return result;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_DICTIONARY: {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->push_back('{');
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (pretty_print_)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        json_string_->append(kPrettyPrintLineEnding);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const DictionaryValue* dict = NULL;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool first_value_has_been_output = false;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool result = node->GetAsDictionary(&dict);
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(result);
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd();
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           itr.Advance()) {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (omit_binary_values_ &&
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            itr.value().GetType() == Value::TYPE_BINARY) {
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          continue;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (first_value_has_been_output) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          json_string_->push_back(',');
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          if (pretty_print_)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            json_string_->append(kPrettyPrintLineEnding);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (pretty_print_)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          IndentLine(depth + 1U);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EscapeJSONString(itr.key(), true, json_string_);
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        json_string_->push_back(':');
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (pretty_print_)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          json_string_->push_back(' ');
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!BuildJSONString(&itr.value(), depth + 1U))
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          result = false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        first_value_has_been_output = true;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (pretty_print_) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        json_string_->append(kPrettyPrintLineEnding);
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        IndentLine(depth);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      json_string_->push_back('}');
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return result;
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case Value::TYPE_BINARY:
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Successful only if we're allowed to omit it.
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value.";
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return omit_binary_values_;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void JSONWriter::IndentLine(size_t depth) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  json_string_->append(depth * 3U, ' ');
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
208