/* * This file is a part of PikoTools * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2012, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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. */ #ifndef headerfile_picotools_space_spacetojson #define headerfile_picotools_space_spacetojson #include #include #include #include "space.h" namespace PT { class SpaceToJSON { public: void Clear(); void TreatAsTable(const wchar_t * space_name); void TreatAsTable(const std::wstring & space_name); void TreatAsNumeric(const wchar_t * name); void TreatAsNumeric(const std::wstring & name); void TreatAsBool(const wchar_t * name); void TreatAsBool(const std::wstring & name); template void Serialize(Space & space, Stream & out, bool use_indents = false); private: std::set numeric, boolean, table; template void Serialize(Space & space, Stream & out, bool use_indents, int level, bool use_comma, bool treat_as_table, bool skip_name); template void SerializeTableSingle(Space & space, Stream & out, bool use_indents, int level, bool use_comma); template void SerializeTableMulti(Space & space, Stream & out, bool use_indents, int level, bool use_comma); template void PrintToken(Stream & out, const StringType & str, bool check_specials = false); template void PrintLevel(Stream & out, bool use_indents, int level); bool IsNumeric(const std::wstring & name); bool IsBool(const std::wstring & name); bool IsTable(const std::wstring & name); }; template void SpaceToJSON::PrintLevel(Stream & out, bool use_indents, int level) { if( use_indents ) { for(int i=0 ; i void SpaceToJSON::PrintToken(Stream & out, const StringType & str, bool is_special) { if( !is_special ) out << '\"'; for(size_t i=0 ; i void SpaceToJSON::SerializeTableSingle(Space & space, Stream & out, bool use_indents, int level, bool use_comma) { Space::TableSingle::const_iterator i; size_t index = 0; bool is_special; if( use_comma && !space.table_single.empty() ) { PrintLevel(out, use_indents, level); out << L",\n"; } for(i=space.table_single.begin() ; i != space.table_single.end() ; ++i, ++index) { is_special = IsNumeric(i->first) || IsBool(i->first); PrintLevel(out, use_indents, level); PrintToken(out, i->first); out << L": "; PrintToken(out, i->second, is_special); if( index + 1 < space.table_single.size() ) out << ','; out << '\n'; } } template void SpaceToJSON::SerializeTableMulti(Space & space, Stream & out, bool use_indents, int level, bool use_comma) { Space::Table::const_iterator i2; size_t v; size_t index = 0; bool is_special; if( use_comma && !space.table.empty() ) { PrintLevel(out, use_indents, level); out << L",\n"; } for(i2 = space.table.begin() ; i2 != space.table.end() ; ++i2, ++index) { is_special = IsNumeric(i2->first) || IsBool(i2->first); PrintLevel(out, use_indents, level); PrintToken(out, i2->first); out << L": "; out << '['; for(v = 0 ; v < i2->second.size() ; ++v) { if( v > 0 ) PrintLevel(out, use_indents, level + i2->first.size() + 3); PrintToken(out, i2->second[v], is_special); if( v + 1 < i2->second.size() ) out << L",\n"; } out << ']'; if( index + 1 < space.table.size() ) out << ','; out << '\n'; } } template void SpaceToJSON::Serialize(Space & space, Stream & out, bool use_indents, int level, bool use_comma, bool treat_as_table, bool skip_name) { if( use_comma ) { PrintLevel(out, use_indents, level); out << L",\n"; } PrintLevel(out, use_indents, level); if( !skip_name ) { if( space.name.empty() ) { out << L"\"empty\": "; } else { PrintToken(out, space.name); out << L": "; } } if( treat_as_table ) out << L"[\n"; else out << L"{\n"; bool printed_something = false; if( !treat_as_table ) { SerializeTableSingle(space, out, use_indents, level, false); SerializeTableMulti(space, out, use_indents, level, !space.table_single.empty()); if( !space.table_single.empty() || !space.table.empty() ) printed_something = true; } /* * !! IMPROVE ME when serializing a table * we can make a test whether a space is empty and has a name * in such a case put it as a string * this is the same way as the json parser works * */ for(size_t i=0 ; iname); Serialize(*space.spaces[i], out, use_indents, level+1, printed_something, next_is_table, next_skip_name); printed_something = true; } PrintLevel(out, use_indents, level); if( treat_as_table ) out << L"]\n"; else out << L"}\n"; } template void SpaceToJSON::Serialize(Space & space, Stream & out, bool use_indents) { bool treat_as_table = IsTable(space.name); Serialize(space, out, use_indents, 0, false, treat_as_table, true); } } // namespace #endif