/* * Copyright 2009, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // This file contains the definition of class JsonWriter. #include "utils/cross/json_writer.h" #include "base/logging.h" #include "base/string_util.h" using std::string; namespace o3d { JsonWriter::JsonWriter(TextWriter* writer, int indent_spaces) : writer_(writer), indent_spaces_(indent_spaces), compacting_level_(0), current_indentation_(0), new_line_pending_(false), comma_pending_(false) { DCHECK(writer_); } JsonWriter::~JsonWriter() { Close(); } void JsonWriter::OpenObject() { DCHECK(writer_); WritePending(); writer_->WriteChar('{'); IncreaseIndentation(); ScheduleNewLine(); } void JsonWriter::CloseObject() { DCHECK(writer_); CancelComma(); DecreaseIndentation(); WritePending(); writer_->WriteChar('}'); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::OpenArray() { DCHECK(writer_); WritePending(); writer_->WriteChar('['); IncreaseIndentation(); ScheduleNewLine(); } void JsonWriter::CloseArray() { DCHECK(writer_); CancelComma(); DecreaseIndentation(); WritePending(); writer_->WriteChar(']'); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::BeginCompacting() { WritePending(); ++compacting_level_; } void JsonWriter::EndCompacting() { DCHECK_GT(compacting_level_, 0); --compacting_level_; } void JsonWriter::WritePropertyName(const string& name) { DCHECK(writer_); WritePending(); writer_->WriteChar('\"'); WriteEscapedString(name); writer_->WriteChar('\"'); if (compacting_level_ > 0) { writer_->WriteChar(':'); } else { writer_->WriteString(string(": ")); } } void JsonWriter::WriteBool(bool value) { DCHECK(writer_); WritePending(); writer_->WriteBool(value); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::WriteInt(int value) { DCHECK(writer_); WritePending(); writer_->WriteInt(value); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::WriteUnsignedInt(unsigned int value) { DCHECK(writer_); WritePending(); writer_->WriteUnsignedInt(value); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::WriteFloat(float value) { DCHECK(writer_); WritePending(); writer_->WriteFloat(value); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::WriteString(const string& value) { DCHECK(writer_); WritePending(); writer_->WriteChar('\"'); WriteEscapedString(value); writer_->WriteChar('\"'); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::WriteNull() { DCHECK(writer_); WritePending(); writer_->WriteString(string("null")); ScheduleComma(); ScheduleNewLine(); } void JsonWriter::Close() { if (writer_) { CancelComma(); WritePending(); writer_->Close(); writer_ = NULL; } } void JsonWriter::IncreaseIndentation() { ++current_indentation_; } void JsonWriter::DecreaseIndentation() { DCHECK_GT(current_indentation_, 0); --current_indentation_; } void JsonWriter::ScheduleNewLine() { new_line_pending_ = true; } void JsonWriter::ScheduleComma() { comma_pending_ = true; } void JsonWriter::CancelComma() { comma_pending_ = false; } void JsonWriter::WritePending() { if (comma_pending_) { writer_->WriteChar(','); comma_pending_ = false; } if (new_line_pending_) { if (compacting_level_ == 0) { writer_->WriteNewLine(); for (int i = 0; i < current_indentation_ * indent_spaces_; ++i) { writer_->WriteChar(' '); } } new_line_pending_ = false; } } void JsonWriter::WriteEscapedString(const string& unescaped) { for (int i = 0; i < unescaped.length(); ++i) { char c = unescaped[i]; switch (c) { case '\"': writer_->WriteString("\\\""); break; case '\\': writer_->WriteString("\\\\"); break; case '\b': writer_->WriteString("\\b"); break; case '\f': writer_->WriteString("\\f"); break; case '\n': writer_->WriteString("\\n"); break; case '\r': writer_->WriteString("\\r"); break; case '\t': writer_->WriteString("\\t"); break; default: if (c < ' ') { writer_->WriteString(StringPrintf("\\u%04x", static_cast(c))); } else { writer_->WriteChar(c); } } } } } // namespace o3d