diff options
Diffstat (limited to 'chromium/base/json/json_writer.cc')
-rw-r--r-- | chromium/base/json/json_writer.cc | 300 |
1 files changed, 144 insertions, 156 deletions
diff --git a/chromium/base/json/json_writer.cc b/chromium/base/json/json_writer.cc index d6006638219..d14c92c06e5 100644 --- a/chromium/base/json/json_writer.cc +++ b/chromium/base/json/json_writer.cc @@ -9,211 +9,199 @@ #include "base/json/string_escape.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" namespace base { #if defined(OS_WIN) -static const char kPrettyPrintLineEnding[] = "\r\n"; +const char kPrettyPrintLineEnding[] = "\r\n"; #else -static const char kPrettyPrintLineEnding[] = "\n"; +const char kPrettyPrintLineEnding[] = "\n"; #endif // static -void JSONWriter::Write(const Value* const node, std::string* json) { - WriteWithOptions(node, 0, json); +bool JSONWriter::Write(const Value* const node, std::string* json) { + return WriteWithOptions(node, 0, json); } // static -void JSONWriter::WriteWithOptions(const Value* const node, int options, +bool 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 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(options, json); + bool result = writer.BuildJSONString(node, 0U); - JSONWriter writer(omit_binary_values, omit_double_type_preservation, - pretty_print, json); - writer.BuildJSONString(node, 0); - - if (pretty_print) + if (options & OPTIONS_PRETTY_PRINT) json->append(kPrettyPrintLineEnding); + + return result; } -JSONWriter::JSONWriter(bool omit_binary_values, - bool omit_double_type_preservation, bool pretty_print, - std::string* json) - : omit_binary_values_(omit_binary_values), - omit_double_type_preservation_(omit_double_type_preservation), - pretty_print_(pretty_print), +JSONWriter::JSONWriter(int options, std::string* json) + : omit_binary_values_((options & OPTIONS_OMIT_BINARY_VALUES) != 0), + omit_double_type_preservation_( + (options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION) != 0), + pretty_print_((options & OPTIONS_PRETTY_PRINT) != 0), json_string_(json) { DCHECK(json); } -void JSONWriter::BuildJSONString(const Value* const node, int depth) { +bool JSONWriter::BuildJSONString(const Value* const node, size_t depth) { switch (node->GetType()) { - case Value::TYPE_NULL: + 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; + return true; + } + + case Value::TYPE_BOOLEAN: { + bool value; + bool result = node->GetAsBoolean(&value); + DCHECK(result); + json_string_->append(value ? "true" : "false"); + return result; + } + + case Value::TYPE_INTEGER: { + int value; + bool result = node->GetAsInteger(&value); + DCHECK(result); + json_string_->append(IntToString(value)); + return result; + } + + 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))); + return result; } - - 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; + 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"); } - - case Value::TYPE_STRING: - { - std::string value; - bool result = node->GetAsString(&value); - DCHECK(result); - EscapeJSONString(value, true, json_string_); - break; + // 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(static_cast<size_t>(0), static_cast<size_t>(1), '0'); + } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { + // "-.1" bad "-0.1" good + real.insert(static_cast<size_t>(1), static_cast<size_t>(1), '0'); } + json_string_->append(real); + return result; + } + + case Value::TYPE_STRING: { + std::string value; + bool result = node->GetAsString(&value); + DCHECK(result); + EscapeJSONString(value, true, json_string_); + return result; + } + + case Value::TYPE_LIST: { + json_string_->push_back('['); + if (pretty_print_) + json_string_->push_back(' '); + + const ListValue* list = NULL; + bool first_value_has_been_output = false; + bool result = node->GetAsList(&list); + DCHECK(result); + for (ListValue::const_iterator it = list->begin(); it != list->end(); + ++it) { + const Value* value = *it; + if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY) + continue; + + if (first_value_has_been_output) { + json_string_->push_back(','); + if (pretty_print_) + json_string_->push_back(' '); + } - 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 (!BuildJSONString(value, depth)) + result = false; - if (omit_binary_values_ && value->GetType() == Value::TYPE_BINARY) { - continue; - } + first_value_has_been_output = true; + } - if (i != 0) { - json_string_->append(","); - if (pretty_print_) - json_string_->append(" "); - } + if (pretty_print_) + json_string_->push_back(' '); + json_string_->push_back(']'); + return result; + } + + case Value::TYPE_DICTIONARY: { + json_string_->push_back('{'); + if (pretty_print_) + json_string_->append(kPrettyPrintLineEnding); + + const DictionaryValue* dict = NULL; + bool first_value_has_been_output = false; + bool result = node->GetAsDictionary(&dict); + DCHECK(result); + for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); + itr.Advance()) { + if (omit_binary_values_ && + itr.value().GetType() == Value::TYPE_BINARY) { + continue; + } - BuildJSONString(value, depth); + if (first_value_has_been_output) { + json_string_->push_back(','); + if (pretty_print_) + json_string_->append(kPrettyPrintLineEnding); } if (pretty_print_) - json_string_->append(" "); - json_string_->append("]"); - break; - } + IndentLine(depth + 1U); - case Value::TYPE_DICTIONARY: - { - json_string_->append("{"); + EscapeJSONString(itr.key(), true, json_string_); + json_string_->push_back(':'); if (pretty_print_) - json_string_->append(kPrettyPrintLineEnding); - - const DictionaryValue* dict = - static_cast<const DictionaryValue*>(node); - bool first_entry = true; - for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); - itr.Advance(), first_entry = false) { - if (omit_binary_values_ && - itr.value().GetType() == Value::TYPE_BINARY) { - continue; - } - - if (!first_entry) { - json_string_->append(","); - if (pretty_print_) - json_string_->append(kPrettyPrintLineEnding); - } + json_string_->push_back(' '); - if (pretty_print_) - IndentLine(depth + 1); - - EscapeJSONString(itr.key(), true, json_string_); - if (pretty_print_) { - json_string_->append(": "); - } else { - json_string_->append(":"); - } - BuildJSONString(&itr.value(), depth + 1); - } + if (!BuildJSONString(&itr.value(), depth + 1U)) + result = false; - if (pretty_print_) { - json_string_->append(kPrettyPrintLineEnding); - IndentLine(depth); - json_string_->append("}"); - } else { - json_string_->append("}"); - } - break; + first_value_has_been_output = true; } - case Value::TYPE_BINARY: - { - if (!omit_binary_values_) { - NOTREACHED() << "Cannot serialize binary value."; - } - break; + if (pretty_print_) { + json_string_->append(kPrettyPrintLineEnding); + IndentLine(depth); } - default: - NOTREACHED() << "unknown json type"; + json_string_->push_back('}'); + return result; + } + + case Value::TYPE_BINARY: + // Successful only if we're allowed to omit it. + DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value."; + return omit_binary_values_; } + NOTREACHED(); + return false; } -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, ' ')); +void JSONWriter::IndentLine(size_t depth) { + json_string_->append(depth * 3U, ' '); } } // namespace base |