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/stringprintf.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kPrettyPrintLineEnding[] = "\r\n"; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kPrettyPrintLineEnding[] = "\n"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* JSONWriter::kEmptyArray = "[]"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JSONWriter::Write(const Value* const node, std::string* json) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteWithOptions(node, 0, json); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JSONWriter::WriteWithOptions(const Value* const node, int options, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* json) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json->clear(); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is there a better way to estimate the size of the output? 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json->reserve(1024); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool escape = !(options & OPTIONS_DO_NOT_ESCAPE); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool omit_double_type_preservation = 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !!(options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pretty_print = !!(options & OPTIONS_PRETTY_PRINT); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONWriter writer(escape, omit_binary_values, omit_double_type_preservation, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pretty_print, json); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.BuildJSONString(node, 0); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json->append(kPrettyPrintLineEnding); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JSONWriter::JSONWriter(bool escape, bool omit_binary_values, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool omit_double_type_preservation, bool pretty_print, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* json) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : escape_(escape), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) omit_binary_values_(omit_binary_values), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) omit_double_type_preservation_(omit_double_type_preservation), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pretty_print_(pretty_print), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_(json) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(json); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JSONWriter::BuildJSONString(const Value* const node, int depth) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (node->GetType()) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_NULL: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append("null"); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_BOOLEAN: 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool value; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = node->GetAsBoolean(&value); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(value ? "true" : "false"); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_INTEGER: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = node->GetAsInteger(&value); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringAppendF(json_string_, "%d", value); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_DOUBLE: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double value; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = node->GetAsDouble(&value); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (omit_double_type_preservation_ && 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value <= kint64max && 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value >= kint64min && 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::floor(value) == value) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(Int64ToString(static_cast<int64>(value))); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string real = DoubleToString(value); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the number has a .0 if there's no decimal or 'e'. This 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // makes sure that when we read the JSON back, it's interpreted as a 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // real rather than an int. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (real.find('.') == std::string::npos && 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real.find('e') == std::string::npos && 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real.find('E') == std::string::npos) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real.append(".0"); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The JSON spec requires that non-integer values in the range (-1,1) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have a zero before the decimal point - ".52" is not valid, "0.52" is. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (real[0] == '.') { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real.insert(0, "0"); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "-.1" bad "-0.1" good 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real.insert(1, "0"); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(real); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_STRING: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = node->GetAsString(&value); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (escape_) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JsonDoubleQuote(UTF8ToUTF16(value), true, json_string_); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JsonDoubleQuote(value, true, json_string_); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_LIST: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append("["); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(" "); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ListValue* list = static_cast<const ListValue*>(node); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < list->GetSize(); ++i) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Value* value = NULL; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = list->Get(i, &value); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != 0) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(","); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(" "); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildJSONString(value, depth); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(" "); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append("]"); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_DICTIONARY: 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append("{"); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(kPrettyPrintLineEnding); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue* dict = 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<const DictionaryValue*>(node); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool first_entry = true; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) itr.Advance(), first_entry = false) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (omit_binary_values_ && 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) itr.value().GetType() == Value::TYPE_BINARY) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!first_entry) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(","); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(kPrettyPrintLineEnding); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IndentLine(depth + 1); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AppendQuotedString(itr.key()); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(": "); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(":"); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BuildJSONString(&itr.value(), depth + 1); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pretty_print_) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(kPrettyPrintLineEnding); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IndentLine(depth); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append("}"); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append("}"); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Value::TYPE_BINARY: 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!omit_binary_values_) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Cannot serialize binary value."; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "unknown json type"; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JSONWriter::AppendQuotedString(const std::string& str) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have to convert it to UTF-16. This round-trip is suboptimal. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JSONWriter::IndentLine(int depth) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may be faster to keep an indent string so we don't have to keep 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reallocating. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string_->append(std::string(depth * 3, ' ')); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 234