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