/* * This file is a part of PikoTools * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2008-2021, 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. */ //#include #include #include #include "space.h" //#include "textstream/textstream.h" #include "utf8/utf8.h" #include "convert/convert.h" namespace PT { Space::Space() { type = type_null; child_spaces = nullptr; name = nullptr; } Space::Space(const Space & space) { copy_from(space); } Space & Space::operator=(const Space & space) { copy_from(space); return *this; } Space::~Space() { remove_value(); remove_child_spaces(); remove_space_name(); } Space::Space(bool val) { set(val); } Space::Space(short val) { set(val); } Space::Space(int val) { set(val); } Space::Space(long val) { set(val); } Space::Space(long long val) { set(val); } Space::Space(unsigned short val) { set(val); } Space::Space(unsigned int val) { set(val); } Space::Space(unsigned long val) { set(val); } Space::Space(unsigned long long val) { set(val); } Space::Space(float val) { set(val); } Space::Space(double val) { set(val); } Space::Space(const char * str) { set(str); } Space::Space(const wchar_t * str) { set(str); } Space::Space(const std::string & str) { set(str); } Space::Space(const std::wstring & str) { set(str); } Space::Space(const Space * space) { set(space); } void Space::clear() { set_null(); } void Space::set_null() { initialize_value_null_if_needed(); } void Space::set_empty_string() { initialize_value_string_if_needed(); } void Space::set_empty_wstring() { initialize_value_wstring_if_needed(); } void Space::set_empty_table() { initialize_value_table_if_needed(); } void Space::set_empty_object() { initialize_value_object_if_needed(); } void Space::set(bool val) { initialize_value_bool_if_needed(); value.value_bool = val; } void Space::set(short val) { set(static_cast(val)); } void Space::set(int val) { set(static_cast(val)); } void Space::set(long val) { set(static_cast(val)); } void Space::set(long long val) { initialize_value_long_if_needed(); value.value_long = val; } void Space::set(unsigned short val) { set(static_cast(val)); } void Space::set(unsigned int val) { set(static_cast(val)); } void Space::set(unsigned long val) { set(static_cast(val)); } void Space::set(unsigned long long val) { set(static_cast(val)); } void Space::set(float val) { initialize_value_float_if_needed(); value.value_float = val; } void Space::set(double val) { initialize_value_double_if_needed(); value.value_double = val; } void Space::set(const char * str) { if( str == nullptr ) { initialize_value_null_if_needed(); } else { initialize_value_string_if_needed(); value.value_string = str; } } void Space::set(const wchar_t * str) { if( str == nullptr ) { initialize_value_null_if_needed(); } else { initialize_value_wstring_if_needed(); value.value_wstring = str; } } void Space::set(const std::string & str) { initialize_value_string_if_needed(); value.value_string = str; } void Space::set(const std::wstring & str) { initialize_value_wstring_if_needed(); value.value_wstring = str; } void Space::set(const Space * space) { if( space == nullptr ) { initialize_value_null_if_needed(); } else { copy_from(*space); } } Space & Space::add(bool val) { return add_generic(val); } Space & Space::add(short val) { return add_generic(val); } Space & Space::add(int val) { return add_generic(val); } Space & Space::add(long val) { return add_generic(val); } Space & Space::add(long long val) { return add_generic(val); } Space & Space::add(unsigned short val) { return add_generic(val); } Space & Space::add(unsigned int val) { return add_generic(val); } Space & Space::add(unsigned long val) { return add_generic(val); } Space & Space::add(unsigned long long val) { return add_generic(val); } Space & Space::add(float val) { return add_generic(val); } Space & Space::add(double val) { return add_generic(val); } Space & Space::add(const char * val) { return add_generic(val); } Space & Space::add(const wchar_t * val) { return add_generic(val); } Space & Space::add(const std::string & val) { return add_generic(val); } Space & Space::add(const std::wstring & val) { return add_generic(val); } Space & Space::add(const Space * space) { return add_generic(space); } Space & Space::add(const wchar_t * field, bool val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, short val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, int val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, long val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, long long val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, unsigned short val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, unsigned int val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, unsigned long val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, unsigned long long val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, float val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, double val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, const char * val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, const wchar_t * val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, const std::string & val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, const std::wstring & val) { return add_generic(field, val); } Space & Space::add(const wchar_t * field, const Space * space) { return add_generic(field, space); } Space & Space::add_empty_space(const wchar_t * field) { return add_generic(field, static_cast(nullptr)); } Space & Space::add_child_space(const wchar_t * space_name) { initialize_child_spaces_if_needed(); child_spaces->push_back(new Space()); Space * last_space = child_spaces->back(); last_space->initialize_space_name_if_needed(); last_space->name->append(space_name); return *last_space; } bool Space::is_null() const { return type == type_null; } bool Space::is_bool() const { return type == type_bool; } bool Space::is_llong() const { return is_long_long(); } bool Space::is_long_long() const { return type == type_long; } bool Space::is_float() const { return type == type_float; } bool Space::is_double() const { return type == type_double; } bool Space::is_numeric() const { return is_long_long() || is_float() || is_double(); } bool Space::is_str() const { return type == type_string; } bool Space::is_wstr() const { return type == type_wstring; } bool Space::is_text() const { return is_str() || is_wstr(); } bool Space::is_object() const { return type == type_object; } bool Space::is_table() const { return type == type_table; } bool Space::to_bool() const { long long val = to_long_long(); return (val != 0) ? true : false; } short Space::to_short() const { return to_generic_numeric_signed_value(); } int Space::to_int() const { return to_generic_numeric_signed_value(); } long Space::to_long() const { return to_generic_numeric_signed_value(); } long long Space::to_llong() const { return to_long_long(); } long long Space::to_long_long() const { switch(type) { case type_null: case type_object: case type_table: return 0; case type_bool: return value.value_bool ? 1 : 0; case type_long: return value.value_long; case type_float: return static_cast(value.value_float); case type_double: return static_cast(value.value_double); case type_string: return convert_string_to_long_long(); case type_wstring: return convert_wstring_to_long_long(); } return 0; } unsigned long long Space::to_ullong() const { return to_ulong_long(); } long long Space::convert_string_to_long_long() const { bool was_overflow = false; const char * after_str; long long val = Toll(value.value_string.c_str(), 10, &after_str, &was_overflow, true); return was_overflow ? 0 : val; } long long Space::convert_wstring_to_long_long() const { bool was_overflow = false; const wchar_t * after_str; long long val = Toll(value.value_wstring.c_str(), 10, &after_str, &was_overflow, true); return was_overflow ? 0 : val; } unsigned long long Space::convert_string_to_ulong_long() const { bool was_overflow = false; const char * after_str; unsigned long long val = Toull(value.value_string.c_str(), 10, &after_str, &was_overflow, true); return was_overflow ? 0 : val; } unsigned long long Space::convert_wstring_to_ulong_long() const { bool was_overflow = false; const wchar_t * after_str; unsigned long long val = Toull(value.value_wstring.c_str(), 10, &after_str, &was_overflow, true); return was_overflow ? 0 : val; } unsigned short Space::to_ushort() const { return to_generic_numeric_unsigned_value(); } unsigned int Space::to_uint() const { return to_generic_numeric_unsigned_value(); } unsigned long Space::to_ulong() const { return to_generic_numeric_unsigned_value(); } unsigned long long Space::to_ulong_long() const { switch(type) { case type_null: case type_object: case type_table: return 0; case type_bool: return value.value_bool ? 1 : 0; case type_long: return static_cast(value.value_long); case type_float: return static_cast(value.value_float); case type_double: return static_cast(value.value_double); case type_string: return convert_string_to_ulong_long(); case type_wstring: return convert_wstring_to_ulong_long(); } return 0; } std::string Space::to_str() const { if( type == type_string ) return value.value_string; std::string str; if( type == type_wstring ) { PT::TextStream stream; serialize_string_buffer(value.value_wstring.c_str(), stream, Escape::no_escape); stream.to_string(str); return str; } serialize_to_json_to(str); return str; } std::wstring Space::to_wstr() const { if( type == type_wstring ) return value.value_wstring; std::wstring str; if( type == type_string ) { PT::WTextStream stream; serialize_string_buffer(value.value_string.c_str(), stream, Escape::no_escape); stream.to_string(str); return str; } serialize_to_json_to(str); return str; } std::string Space::serialize_to_space_str(bool pretty_print) const { std::string str; serialize_to_space_to(str, pretty_print); return str; } std::wstring Space::serialize_to_space_wstr(bool pretty_print) const { std::wstring str; serialize_to_space_to(str, pretty_print); return str; } void Space::serialize_to_space_to(std::string & str, bool pretty_print) const { PT::TextStream stream; serialize_to_space_stream(stream, pretty_print); stream.to_string(str); } void Space::serialize_to_space_to(std::wstring & str, bool pretty_print) const { PT::WTextStream stream; serialize_to_space_stream(stream, pretty_print); stream.to_string(str); } std::string Space::serialize_to_json_str() const { std::string str; serialize_to_json_to(str); return str; } std::wstring Space::serialize_to_json_wstr() const { std::wstring str; serialize_to_json_to(str); return str; } void Space::serialize_to_json_to(std::string & str) const { PT::TextStream stream; serialize_to_json_stream(stream); stream.to_string(str); } void Space::serialize_to_json_to(std::wstring & str) const { PT::WTextStream stream; serialize_to_json_stream(stream); stream.to_string(str); } bool * Space::get_bool() { return type == type_bool ? &value.value_bool : nullptr; } long long * Space::get_llong() { return get_long_long(); } long long * Space::get_long_long() { return type == type_long ? &value.value_long : nullptr; } float * Space::get_float() { return type == type_float ? &value.value_float : nullptr; } double * Space::get_double() { return type == type_double ? &value.value_double : nullptr; } std::string * Space::get_string() { return type == type_string ? &value.value_string : nullptr; } std::wstring * Space::get_wstring() { return type == type_wstring ? &value.value_wstring : nullptr; } Space::ObjectType * Space::get_object() { return type == type_object ? &value.value_object : nullptr; } Space::TableType * Space::get_table() { return type == type_table ? &value.value_table : nullptr; } const bool * Space::get_bool() const { return type == type_bool ? &value.value_bool : nullptr; } const long long * Space::get_llong() const { return get_long_long(); } const long long * Space::get_long_long() const { return type == type_long ? &value.value_long : nullptr; } const float * Space::get_float() const { return type == type_float ? &value.value_float : nullptr; } const double * Space::get_double() const { return type == type_double ? &value.value_double : nullptr; } const std::string * Space::get_string() const { return type == type_string ? &value.value_string : nullptr; } const std::wstring * Space::get_wstring() const { return type == type_wstring ? &value.value_wstring : nullptr; } const Space::ObjectType * Space::get_object() const { return type == type_object ? &value.value_object : nullptr; } const Space::TableType * Space::get_table() const { return type == type_table ? &value.value_table : nullptr; } void Space::copy_value_from(const Space & space) { switch(space.type) { case type_null: initialize_value_null_if_needed(); break; case type_bool: initialize_value_bool_if_needed(); value.value_bool = space.value.value_bool; break; case type_long: initialize_value_long_if_needed(); value.value_long = space.value.value_long; break; case type_float: initialize_value_float_if_needed(); value.value_float = space.value.value_float; break; case type_double: initialize_value_double_if_needed(); value.value_double = space.value.value_double; break; case type_string: initialize_value_string_if_needed(); value.value_string = space.value.value_string; break; case type_wstring: initialize_value_wstring_if_needed(); value.value_wstring = space.value.value_wstring; break; case type_object: copy_value_object(space.value); break; case type_table: copy_value_table(space.value); break; } } void Space::copy_child_spaces_from(const Space & space) { if( space.child_spaces ) { initialize_child_spaces_if_needed(); child_spaces->clear(); for(size_t i = 0 ; i < space.child_spaces->size() ; ++i) { child_spaces->push_back(new Space((*space.child_spaces)[i])); } } else if( child_spaces ) { remove_child_spaces(); } } void Space::copy_space_name_from(const Space & space) { if( space.name ) { initialize_space_name_if_needed(); *name = *space.name; } else if( name ) { remove_space_name(); } } void Space::copy_from(const Space & space) { copy_value_from(space); copy_child_spaces_from(space); copy_space_name_from(space); } void Space::copy_value_object(const Value & value_from) { initialize_value_object_if_needed(); value.value_object.clear(); for(auto map_item : value_from.value_object) { Space * new_space = new Space(*map_item.second); value.value_object.insert(std::make_pair(map_item.first, new_space)); } } void Space::copy_value_table(const Value & value_from) { initialize_value_table_if_needed(); value.value_table.clear(); for(Space * space : value_from.value_table) { Space * new_space = new Space(*space); value.value_table.push_back(new_space); } } void Space::initialize_value_null_if_needed() { if( type != type_null ) { remove_value(); type = type_null; } } void Space::initialize_value_bool_if_needed() { if( type != type_bool ) { remove_value(); new (&value) bool; type = type_bool; } } void Space::initialize_value_long_if_needed() { if( type != type_long ) { remove_value(); new (&value) long long; type = type_long; } } void Space::initialize_value_float_if_needed() { if( type != type_float ) { remove_value(); new (&value) float; type = type_float; } } void Space::initialize_value_double_if_needed() { if( type != type_double ) { remove_value(); new (&value) double; type = type_double; } } void Space::initialize_value_string_if_needed() { if( type != type_string ) { remove_value(); new (&value) std::string; type = type_string; } } void Space::initialize_value_wstring_if_needed() { if( type != type_wstring ) { remove_value(); new (&value) std::wstring; type = type_wstring; } } void Space::initialize_value_object_if_needed() { if( type != type_object ) { remove_value(); new (&value) ObjectType; type = type_object; } } void Space::initialize_value_table_if_needed() { if( type != type_table ) { remove_value(); new (&value) TableType; type = type_table; } } void Space::initialize_child_spaces_if_needed() { if( child_spaces == nullptr ) { child_spaces = new TableType(); } } void Space::initialize_space_name_if_needed() { if( name == nullptr ) { name = new std::wstring(); } } void Space::remove_value() { switch(type) { case type_null: break; case type_bool: case type_long: case type_float: case type_double: type = type_null; break; case type_string: { remove_value_string(); break; } case type_wstring: { remove_value_wstring(); break; } case type_object: { remove_value_object(); break; } case type_table: remove_value_table(); break; } } void Space::remove_value_string() { value.value_string.~basic_string(); type = type_null; } void Space::remove_value_wstring() { value.value_wstring.~basic_string(); type = type_null; } void Space::remove_value_object() { for(auto map_item : value.value_object) { delete map_item.second; map_item.second = nullptr; } value.value_object.~ObjectType(); type = type_null; } void Space::remove_value_table() { for(size_t i = 0 ; i < value.value_table.size() ; ++i) { delete value.value_table[i]; value.value_table[i] = nullptr; } value.value_table.~TableType(); type = type_null; } void Space::remove_child_spaces() { if( child_spaces ) { for(size_t i = 0 ; i < child_spaces->size() ; ++i) { delete (*child_spaces)[i]; (*child_spaces)[i] = nullptr; } delete child_spaces; child_spaces = nullptr; } } void Space::remove_space_name() { if( name ) { delete name; name = nullptr; } } } // namespace