root/src/JsonWriter.cpp

////////////////////////////////////////////////////////////////////////
// Copyright (c) Nehmulos 2011-2014
// This file is part of N0 Strain Serialization Library.
//
// N0Strain-Serialization-Library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// N0Strain-Serialization-Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with N0Strain-Serialization-Library.  If not, see https://gnu.org/licenses/lgpl-3.0
////////////////////////////////////////////////////////////////////////




#include "JsonWriter.h"

namespace nw
{

JsonWriter::JsonWriter(std::ostream& output) : MarkupWriter(output) {

}

JsonWriter::JsonWriter(const String filepath) : MarkupWriter(filepath) {

}

JsonWriter::~JsonWriter() {
        if (!didWrite) {
                this->close();
        }
}

void JsonWriter::writeToOutput()
{
        static_cast<JsonTag*>(motherTag)->writeAsJson(output);
}

void JsonWriter::describeArray(const String arrayName, const String elementsName, unsigned int size)
{
        if(!arrayName.empty())
        {
                currentTag = static_cast<JsonTag*>(currentTag)->addJsonChild(arrayName, JsonType::Array);
        }

        MetaArray newArray;
        newArray.nameOfArray = arrayName;
        newArray.nameOfElements = elementsName;
        newArray.size = size;
        newArray.isValueArray = false;
        openArrays.push(newArray);
}

bool JsonWriter::enterNextElement(unsigned int iterator)
{
        if(!openArrays.empty() && openArrays.top().isValueArray)
        {
                if(iterator < openArrays.top().size)
                {
                        describeName("");
                        return true;
                }
                openArrays.pop();
                pop();
                return false;
        }

        if(iterator != 0)
                pop();
        if(iterator < openArrays.top().size)
        {
                if(!openArrays.top().isValueArray)
                        push("");
                return true;
        }
        else
        {
                if(!openArrays.top().nameOfArray.empty())
                        pop(); //Close array wrapper with arrayName

                openArrays.pop();
                return false;
        }

}

void JsonWriter::describeValueConst(const String& ref)
{
        String stringValue = ref;

        // escape forbidden control characters according to json.org
        size_t foundPosition = stringValue.find('\\', 0);
        while (foundPosition != std::string::npos) {
                if (foundPosition+1 >= stringValue.length() ||
                        (stringValue.at(foundPosition +1) != '\\' &&
                         stringValue.at(foundPosition +1) !='/')) {

                        stringValue.replace(foundPosition, 1, "\\\\");
                }
                foundPosition = stringValue.find('\\', foundPosition+2);
        }

        nw::utils::replaceAll(stringValue, "\"", "\\\"");
        //nw::utils::replaceAll(stringValue, '\/', "\\/"); //valid?
        nw::utils::replaceAll(stringValue, '\b', "\\b");
        nw::utils::replaceAll(stringValue, '\f', "\\f");
        nw::utils::replaceAll(stringValue, '\n', "\\n");
        nw::utils::replaceAll(stringValue, '\r', "\\r");
        nw::utils::replaceAll(stringValue, '\t', "\\t");
        //resolves to unicode and unicode is a valid char. \\u is caught by \\ rep
        //nw::utils::replaceAll(stringValue, '\u', "\\u");

        selectedTag->setValue(stringValue);
        static_cast<JsonTag*>(selectedTag)->setType(JsonType::String);
}
void JsonWriter::describeValueConst(const double& ref)
{
        setJsonValue(ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const char& ref)
{
        short numValue = ref;
        setJsonValue( numValue, JsonType::Number);

}
void JsonWriter::describeValueConst(const unsigned char& ref)
{
        short numValue = ref;
        setJsonValue( numValue, JsonType::Number);
}
void JsonWriter::describeValueConst(const int& ref)
{
        setJsonValue(ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const unsigned int& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const float& ref)
{
        setJsonValue(ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const bool& ref)
{
        if(ref)
                setJsonValue("true", JsonType::Boolean);
        else
                setJsonValue("false", JsonType::Boolean);
}
void JsonWriter::describeValueConst(const  Pointer ref)
{
        unsigned int id = Describer::getIDForSerializedObject(ref);
        setJsonValue( id, JsonType::Number);
}

void JsonWriter::describeValueConst(const  signed char& ref)
{
        short numValue = ref;
        setJsonValue( numValue, JsonType::Number);
}
void JsonWriter::describeValueConst(const  short& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const  unsigned short& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const  long& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const  unsigned long& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const  long long& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeValueConst(const  long double& ref)
{
        setJsonValue( ref, JsonType::Number);
}
void JsonWriter::describeName(const String childName)
{
        selectedTag = static_cast<JsonTag*>(currentTag)->addJsonChild(childName);
}

void JsonWriter::comment(const String text)
{

}

template<class T>
void JsonWriter::setJsonValue(T value, JsonType::Enum type)
{
        String stringValue;
        std::stringstream ss;
        ss << value;
        ss >> stringValue;

        selectedTag->setValue(stringValue);
        static_cast<JsonTag*>(selectedTag)->setType(type);
}

}