From f65d934e8cf012769a23e5b6238518acf87e1b20 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 15 Mar 2021 19:36:49 +0100 Subject: [PATCH] start working on a new version of Space struct - better support for JSON format now we have a correct model, some methods for setting/getting values and serialization to json (no serialization to Space yet) --- space/space.cpp | 1812 ++++++++++++++++++++++++----------------------- space/space.h | 957 +++++++++++++++---------- 2 files changed, 1513 insertions(+), 1256 deletions(-) diff --git a/space/space.cpp b/space/space.cpp index 0798dd5..203eca2 100644 --- a/space/space.cpp +++ b/space/space.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2008-2018, Tomasz Sowa + * Copyright (c) 2008-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,1047 +37,1075 @@ //#include #include +#include #include "space.h" +//#include "textstream/textstream.h" #include "utf8/utf8.h" -#include "textstream/textstream.h" #include "convert/convert.h" namespace PT { - - Space::Space() { - parent = nullptr; + type = type_null; +} + + +Space::Space(const Space & space) +{ + copy_value_from(space); +} + +Space & Space::operator=(const Space & space) +{ + copy_value_from(space); + return *this; } Space::~Space() { - Clear(); + remove_value(); } -Space::Space(const Space & s) + +Space::Space(bool val) { - operator=(s); + set(val); +} + +Space::Space(short val) +{ + set(val); +} + +Space::Space(int val) +{ + set(val); +} + +Space::Space(long val) +{ + set(val); } -Space & Space::operator=(const Space & s) +Space::Space(long long val) { - Clear(); + set(val); +} - name = s.name; - table = s.table; - parent = s.parent; +Space::Space(unsigned short val) +{ + set(val); +} - for(size_t i=0 ; i(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) +{ + initialize_value_string_if_needed(); + value.value_string = str; +} + +void Space::set(const wchar_t * str) +{ + 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 ) { - Space * pspace = new Space(*s.spaces[i]); - pspace->parent = this; - spaces.push_back(pspace); - } - -return *this; -} - - - - - - -void Space::Clear() -{ - name.clear(); - table.clear(); - - for(size_t i=0 ; isecond; + copy_value_from(*space); } } -const Space::Value * Space::GetValue(const wchar_t * name) const +Space & Space::add(bool val) { - tmp_name = name; - return GetValue(tmp_name); + 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); } -const Space::Value * Space::GetValue(const std::wstring & name) const -{ - Table::const_iterator t = table.find(name); - if( t == table.cend() ) + + +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)); +} + + + +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) { - return nullptr; + 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(); } - else + + 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) { - return &t->second; + 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; } - -Space::Value * Space::GetValueNoCase(const wchar_t * name) +std::string Space::to_str() const { - tmp_name = name; - return GetValueNoCase(tmp_name); -} + if( type == type_string ) + return value.value_string; + std::string str; -Space::Value * Space::GetValueNoCase(const std::wstring & name) -{ - Table::iterator t = table.begin(); - - for( ; t != table.end() ; ++t) + if( type == type_wstring ) { - if( PT::EqualNoCase(t->first, name) ) - { - return &t->second; - } + PT::TextStream stream; + serialize_string_buffer(value.value_wstring.c_str(), stream, Escape::no_escape); + stream.to_string(str); + return str; } - return nullptr; + serialize_to_json_to(str); + return str; } - -const Space::Value * Space::GetValueNoCase(const wchar_t * name) const +std::wstring Space::to_wstr() const { - tmp_name = name; - return GetValueNoCase(tmp_name); -} + if( type == type_wstring ) + return value.value_wstring; + std::wstring str; -const Space::Value * Space::GetValueNoCase(const std::wstring & name) const -{ - Table::const_iterator t = table.begin(); - - for( ; t != table.end() ; ++t) + if( type == type_string ) { - if( PT::EqualNoCase(t->first, name) ) - { - return &t->second; - } + PT::WTextStream stream; + serialize_string_buffer(value.value_string.c_str(), stream, Escape::no_escape); + stream.to_string(str); + return str; } - return nullptr; + serialize_to_json_to(str); + return str; +} + + +std::string Space::serialize_to_space_str() const +{ + std::string str; + serialize_to_space_to(str); + return str; +} + + +std::wstring Space::serialize_to_space_wstr() const +{ + std::wstring str; + serialize_to_space_to(str); + return str; +} + + +void Space::serialize_to_space_to(std::string & str) const +{ + PT::TextStream stream; + serialize_to_space_stream(stream); + + stream.to_string(str); +} + + +void Space::serialize_to_space_to(std::wstring & str) const +{ + PT::WTextStream stream; + serialize_to_space_stream(stream); + + stream.to_string(str); } -std::wstring * Space::GetFirstValue(const wchar_t * name) +std::string Space::serialize_to_json_str() const { - tmp_name = name; - return GetFirstValue(tmp_name); + 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); } -std::wstring * Space::GetFirstValue(const std::wstring & name) +bool * Space::get_bool() { - Table::iterator t = table.find(name); + return type == type_bool ? &value.value_bool : nullptr; +} - if( t == table.end() || t->second.empty() ) +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) { - return nullptr; + 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; } - else +} + + + + +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) { - return &t->second[0]; + Space * new_space = new Space(*map_item.second); + value.value_object.insert(std::make_pair(map_item.first, new_space)); } } -// CHECK ME -const std::wstring * Space::GetFirstValue(const wchar_t * name) const +void Space::copy_value_table(const Value & value_from) { - tmp_name = name; - return GetFirstValue(tmp_name); -} + initialize_value_table_if_needed(); + value.value_table.clear(); -const std::wstring * Space::GetFirstValue(const std::wstring & name) const -{ - Table::const_iterator t = table.find(name); - - if( t == table.end() || t->second.empty() ) + for(Space * space : value_from.value_table) { - return nullptr; + Space * new_space = new Space(*space); + value.value_table.push_back(new_space); } - else +} + + +void Space::initialize_value_null_if_needed() +{ + if( type != type_null ) { - return &t->second[0]; + remove_value(); + type = type_null; } } - - -bool Space::HasValue(const wchar_t * name, const wchar_t * value) +void Space::initialize_value_bool_if_needed() { - tmp_name = name; - tmp_value_text = value; - -return HasValue(tmp_name, tmp_value_text); -} - -bool Space::HasValue(const wchar_t * name, const std::wstring & value) -{ - tmp_name = name; - -return HasValue(tmp_name, value); -} - - -bool Space::HasValue(const std::wstring & name, const wchar_t * value) -{ - tmp_value_text = value; - -return HasValue(name, tmp_value_text); -} - - -bool Space::HasValue(const std::wstring & name, const std::wstring & value) -{ - Table::const_iterator t = table.find(name); - - if( t != table.end() ) + if( type != type_bool ) { - for(size_t i=0 ; i < t->second.size() ; ++i) - if( t->second[i] == value ) - return true; + remove_value(); + new (&value) bool; + type = type_bool; } - -return false; } - - - -//std::wstring Space::Text(const wchar_t * name) const -//{ -// tmp_name = name; -// return Text(tmp_name, L""); -//} - - - -std::wstring Space::Text(const wchar_t * name, const wchar_t * def) const +void Space::initialize_value_long_if_needed() { - tmp_name = name; - return Text(tmp_name, def); -} - - -std::wstring Space::Text(const std::wstring & name, const wchar_t * def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) + if( type != type_long ) { - return *value; + remove_value(); + new (&value) long long; + type = type_long; } - else +} + + +void Space::initialize_value_float_if_needed() +{ + if( type != type_float ) { - if( def ) - return std::wstring(def); - else - return std::wstring(); + remove_value(); + new (&value) float; + type = type_float; } } -std::wstring Space::Text(const std::wstring & name, const std::wstring & def) const +void Space::initialize_value_double_if_needed() { - const std::wstring * value = GetFirstValue(name); - - if( value ) + if( type != type_double ) { - return *value; + remove_value(); + new (&value) double; + type = type_double; } - else +} + + +void Space::initialize_value_string_if_needed() +{ + if( type != type_string ) { - return def; + remove_value(); + new (&value) std::string; + type = type_string; } } - - -//std::wstring & Space::TextRef(const wchar_t * name) -//{ -// tmp_name = name; -// return TextRef(tmp_name, L""); -//} - - -std::wstring & Space::TextRef(const wchar_t * name, const wchar_t * def) +void Space::initialize_value_wstring_if_needed() { - tmp_name = name; - return TextRef(tmp_name, def); -} - -std::wstring & Space::TextRef(const std::wstring & name, const wchar_t * def) -{ - Value * value; - Table::iterator t = table.find(name); - - if( t != table.end() ) + if( type != type_wstring ) { - value = &t->second; + remove_value(); + new (&value) std::wstring; + type = type_wstring; } - else +} + + +void Space::initialize_value_object_if_needed() +{ + if( type != type_object ) { - value = &table[name]; + remove_value(); + new (&value) ObjectType; + type = type_object; } +} - if( value->empty() ) + +void Space::initialize_value_table_if_needed() +{ + if( type != type_table ) { - if( def ) - value->push_back(def); - else - value->push_back(std::wstring()); + remove_value(); + new (&value) TableType; + type = type_table; } - - return (*value)[0]; } -std::wstring & Space::TextRef(const std::wstring & name, const std::wstring & def) +void Space::remove_value() { - return TextRef(name, def.c_str()); -} - - - - -//std::string Space::TextA(const wchar_t * name) const -//{ -// tmp_name = name; -// return TextA(tmp_name, ""); -//} - - - -std::string Space::TextA(const wchar_t * name, const char * def) const -{ - tmp_name = name; - return TextA(tmp_name, def); -} - - -std::string Space::TextA(const std::wstring & name, const char * def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) + switch(type) { - std::string res; - PT::WideToUTF8(*value, res); - return res; - } - else + case type_null: + break; + + case type_bool: + case type_long: + case type_float: + case type_double: + type = type_null; + break; + + case type_string: { - if( def ) - return std::string(def); - else - return std::string(); + remove_value_string(); + break; } -} - -std::string Space::TextA(const std::wstring & name, const std::string & def) const -{ - return TextA(name, def.c_str()); -} - - - -std::string Space::TextA(const wchar_t * name, const wchar_t * def) const -{ - tmp_name = name; - return TextA(tmp_name, def); -} - - -std::string Space::TextA(const std::wstring & name, const wchar_t * def) const -{ - const std::wstring * value = GetFirstValue(name); - std::string res; - - if( value ) + case type_wstring: { - PT::WideToUTF8(*value, res); - return res; + remove_value_wstring(); + break; } - else + + case type_object: { - PT::WideToUTF8(def, res); - return res; + remove_value_object(); + break; + } + + case type_table: + remove_value_table(); + break; } } -std::string Space::TextA(const std::wstring & name, const std::wstring & def) const + +void Space::remove_value_string() { - return TextA(name, def.c_str()); + value.value_string.~basic_string(); + type = type_null; } - - -unsigned int Space::ToUInt(const std::wstring & value) +void Space::remove_value_wstring() { - return Toui_b(value.c_str()); -} - -int Space::ToInt(const std::wstring & value) -{ - return Toi_b(value.c_str()); + value.value_wstring.~basic_string(); + type = type_null; } -unsigned long Space::ToULong(const std::wstring & value) +void Space::remove_value_object() { - return Toul_b(value.c_str()); -} - -long Space::ToLong(const std::wstring & value) -{ - return Tol_b(value.c_str()); -} - - -unsigned long long Space::ToULongLong(const std::wstring & value) -{ - return Toull_b(value.c_str()); -} - -long long Space::ToLongLong(const std::wstring & value) -{ - return Toll_b(value.c_str()); -} - - -size_t Space::ToSize(const std::wstring & value) -{ - if( sizeof(size_t) == sizeof(unsigned int) ) - return ToUInt(value); - else - if( sizeof(size_t) == sizeof(unsigned long) ) - return ToULong(value); - else - return ToULongLong(value); -} - - -bool Space::ToBool(const std::wstring & value) -{ - const wchar_t * str_begin = SkipWhite(value.c_str()); - const wchar_t * str_end = SkipWhiteFromBack(str_begin); - - return (PT::EqualNoCase(str_begin, str_end, L"true") || - PT::EqualNoCase(str_begin, str_end, L"yes") || - PT::EqualNoCase(str_begin, str_end, L"1") - ); -} - - - - - - -int Space::Int(const wchar_t * name, int def) const -{ - tmp_name = name; - return Int(tmp_name, def); -} - - - - -int Space::Int(const std::wstring & name, int def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToInt(*value); - -return def; -} - - - -unsigned int Space::UInt(const wchar_t * name, unsigned int def) const -{ - tmp_name = name; - return UInt(tmp_name, def); -} - - -unsigned int Space::UInt(const std::wstring & name, unsigned int def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToUInt(*value); - -return def; -} - - - - - -long Space::Long(const wchar_t * name, long def) const -{ - tmp_name = name; - return Long(tmp_name, def); -} - - -long Space::Long(const std::wstring & name, long def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToLong(*value); - -return def; -} - - -unsigned long Space::ULong(const wchar_t * name, unsigned long def) const -{ - tmp_name = name; - return ULong(tmp_name, def); -} - - -unsigned long Space::ULong(const std::wstring & name, unsigned long def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToULong(*value); - -return def; -} - - - -long long Space::LongLong(const wchar_t * name, long long def) const -{ - tmp_name = name; - return LongLong(tmp_name, def); -} - -long long Space::LongLong(const std::wstring & name, long long def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToLongLong(*value); - -return def; -} - -unsigned long long Space::ULongLong(const wchar_t * name, unsigned long long def) const -{ - tmp_name = name; - return ULongLong(tmp_name, def); -} - -unsigned long long Space::ULongLong(const std::wstring & name, unsigned long long def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToULongLong(*value); - -return def; -} - - - - - -size_t Space::Size(const wchar_t * name, size_t def) const -{ - tmp_name = name; - return Size(tmp_name, def); -} - - -size_t Space::Size(const std::wstring & name, size_t def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToSize(*value); - -return def; -} - - - - -bool Space::Bool(const wchar_t * name, bool def) const -{ - tmp_name = name; - return Bool(tmp_name, def); -} - - - -bool Space::Bool(const std::wstring & name, bool def) const -{ - const std::wstring * value = GetFirstValue(name); - - if( value ) - return ToBool(*value); - -return def; -} - - -// !! CHECKME -std::wstring & Space::FindAdd(const std::wstring & name) -{ - Value * value; - - Table::iterator t = table.find(name); - - if( t != table.end() ) + for(auto map_item : value.value_object) { - value = &t->second; + delete map_item.second; + map_item.second = nullptr; } - else + + value.value_object.~ObjectType(); + type = type_null; +} + + +void Space::remove_value_table() +{ + for(size_t i = 0 ; i < value.value_table.size() ; ++i) { - value = &table[name]; + delete value.value_table[i]; + value.value_table[i] = nullptr; } - if( value->empty() ) - value->push_back(std::wstring()); - - return (*value)[0]; + value.value_table.~TableType(); + type = type_null; } -// !! CHECKME -std::wstring & Space::FindAdd(const wchar_t * name) -{ - tmp_name = name; - return FindAdd(tmp_name); -} - - -// !! CHECKME -std::wstring & Space::FindAdd(const WTextStream & name) -{ - name.to_string(tmp_name); - return FindAdd(tmp_name); -} - - - - - - -/* - * - * - * - * - * CHECKME !! - */ -std::wstring & Space::Add(const std::wstring & name, const std::wstring & value, bool replace_existing) -{ - Table::iterator i = table.find(name); - - if( i == table.end() ) - { - Value & val = table[name]; - val.push_back(value); - return val.back(); - } - else - { - Value & val = i->second; - - if( replace_existing ) - val.clear(); - - val.push_back(value); - return val.back(); - } -} - - -// CHECKME !! -std::wstring & Space::Add(const std::wstring & name, const wchar_t * value, bool replace_existing) -{ - tmp_value = value; - return Add(name, tmp_value, replace_existing); -} - - -// CHECKME !! -std::wstring & Space::Add(const wchar_t * name, const wchar_t * value, bool replace_existing) -{ - tmp_name = name; - tmp_value = value; - return Add(tmp_name, tmp_value, replace_existing); -} - - -// CHECKME !! -std::wstring & Space::Add(const wchar_t * name, const std::wstring & value, bool replace_existing) -{ - tmp_name = name; - return Add(tmp_name, value, replace_existing); -} - - - - -// CHECKME !! -std::wstring & Space::Add(const wchar_t * name, const WTextStream & value, bool replace_existing) -{ - tmp_name = name; - value.to_string(tmp_value); - return Add(tmp_name, tmp_value, replace_existing); -} - - -// CHECKME !! -std::wstring & Space::Add(const std::wstring & name, const WTextStream & value, bool replace_existing) -{ - value.to_string(tmp_value); - return Add(name, tmp_value, replace_existing); -} - - -// CHECKME !! -std::wstring & Space::Add(const WTextStream & name, const WTextStream & value, bool replace_existing) -{ - name.to_string(tmp_name); - value.to_string(tmp_value); - return Add(tmp_name, tmp_value, replace_existing); -} - - - - -/* - * - * - * - * - * - */ -// CHECKME -std::wstring & Space::Add(const std::wstring & name, bool value, bool replace_existing) -{ - if( value ) - return Add(name, L"true", replace_existing); - else - return Add(name, L"false", replace_existing); -} - - -// CHECKME -std::wstring & Space::Add(const wchar_t * name, bool value, bool replace_existing) -{ - tmp_name = name; - return Add(tmp_name, value, replace_existing); -} - - - -// CHECKME -std::wstring & Space::Add(const std::wstring & name, int value, bool replace_existing) -{ -wchar_t value_str[50]; - -#if defined _WIN32 || defined _WIN64 - swprintf(value_str, L"%d", value); -#else - swprintf(value_str, sizeof(value_str)/sizeof(wchar_t), L"%d", value); -#endif - - return Add(name, value_str, replace_existing); -} - - -// CHECKME -std::wstring & Space::Add(const wchar_t * name, int value, bool replace_existing) -{ - tmp_name = name; - return Add(tmp_name, value, replace_existing); -} - - - - - -// CHECKME -std::wstring & Space::Add(const std::wstring & name, long value, bool replace_existing) -{ -wchar_t value_str[50]; - -#if defined _WIN32 || defined _WIN64 - swprintf(value_str, L"%ld", value); -#else - swprintf(value_str, sizeof(value_str)/sizeof(wchar_t), L"%ld", value); -#endif - - return Add(name, value_str, replace_existing); -} - - - -// CHECKME -std::wstring & Space::Add(const wchar_t * name, long value, bool replace_existing) -{ - tmp_name = name; - return Add(tmp_name, value, replace_existing); -} - - - -std::wstring & Space::Add(const std::wstring & name, size_t value, bool replace_existing) -{ -wchar_t value_str[50]; - -#if defined _WIN32 || defined _WIN64 - // see http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.71%29.aspx - swprintf(value_str, L"%Iu", value); -#else - swprintf(value_str, sizeof(value_str)/sizeof(wchar_t), L"%zu", value); -#endif - - return Add(name, value_str, replace_existing); -} - - -std::wstring & Space::Add(const wchar_t * name, size_t value, bool replace_existing) -{ - tmp_name = name; - return Add(tmp_name, value, replace_existing); -} - - - - - - -void Space::Remove(const std::wstring & name) -{ - table.erase(name); -} - - -void Space::Remove(const wchar_t * name) -{ - tmp_name = name; - Remove(tmp_name); -} - - - - - -// CHECKME -Space & Space::AddSpace(const std::wstring & name) -{ - spaces.push_back(new Space()); - spaces.back()->name = name; - spaces.back()->parent = this; - -return *spaces.back(); -} - - -// CHECKME -Space & Space::AddSpace(const wchar_t * name) -{ - tmp_name = name; - return AddSpace(tmp_name); -} - - - - -Space * Space::FindSpace(const wchar_t * name) -{ - for(size_t i=0 ; iname == name ) // there is a special == operator in string class taking c-string as an argument - return spaces[i]; - } - -return nullptr; -} - - -Space * Space::FindSpace(const std::wstring & name) -{ - for(size_t i=0 ; iname == name ) - return spaces[i]; - } - -return nullptr; -} - - -Space & Space::FindAddSpace(const wchar_t * name) -{ - Space * space = FindSpace(name); - - if( space ) - return *space; - -return AddSpace(name); -} - - -Space & Space::FindAddSpace(const std::wstring & name) -{ - Space * space = FindSpace(name); - - if( space ) - return *space; - -return AddSpace(name); -} - - - -void Space::RemoveSpace(const wchar_t * name) -{ - for(size_t i=0 ; iname == name ) - RemoveSpace(i); - else - ++i; - } -} - - -void Space::RemoveSpace(const std::wstring & name) -{ - for(size_t i=0 ; iname == name ) - RemoveSpace(i); - else - ++i; - } -} - - -void Space::RemoveSpace(size_t child_index) -{ - if( child_index < spaces.size() ) - { - delete spaces[child_index]; - spaces.erase(spaces.begin() + child_index); - } -} - - - - - - - -bool Space::ListText(const std::wstring & name, std::vector & list) -{ - list.clear(); - - Table::iterator t = table.find(name); - - if( t != table.end() ) - { - list = t->second; - return true; - } - -return false; -} - - - -// in lists we don't use default values -bool Space::ListText(const wchar_t * name, std::vector & list) -{ - tmp_name = name; - return ListText(tmp_name, list); -} - - - - -/* - those white characters here should be the same as in spaceparser.cpp -*/ -bool Space::IsWhite(int c) -{ - // dont use '\n' here - // 13 (\r) is at the end of a line in a dos file \r\n - // 160 is an unbreakable space - if( c==' ' || c=='\t' || c==13 || c==160 ) - return true; - -return false; -} - - -bool Space::HasWhite(const std::wstring & str) -{ - for(size_t i=0 ; i #include #include +#include +#include #include "textstream/types.h" +#include "convert/inttostr.h" +//#include "utf8/utf8.h" @@ -165,400 +169,625 @@ class Space { public: + typedef std::map ObjectType; + typedef std::vector TableType; + + enum Escape + { + no_escape, + escape_space, + escape_json, + }; + + enum Type + { + type_null, + type_bool, + type_long, + type_float, + type_double, + type_string, + type_wstring, + type_object, + type_table, + }; + + union Value + { + bool value_bool; + long long value_long; + float value_float; + double value_double; + std::string value_string; + std::wstring value_wstring; + ObjectType value_object; + TableType value_table; + + Value() + { + } + + ~Value() + { + } + }; + + + Type type; + Value value; - /* - this is the table which represents your config file - in the Table map: the first (key) is your 'option' and the second is 'list' - */ - typedef std::vector Value; - typedef std::map Table; Space(); + Space(const Space & space); + Space & operator=(const Space & space); + // add move cctor ~Space(); - Space(const Space & s); - Space & operator=(const Space & s); - - // IMPROVE ME - // add move cctor - - - void Clear(); - - - - /* - returns true if such an option has 'value' - useful when testing lists (they don't have to be copied out) - */ - bool HasValue(const wchar_t * name, const wchar_t * value); - bool HasValue(const wchar_t * name, const std::wstring & value); - bool HasValue(const std::wstring & name, const wchar_t * value); - bool HasValue(const std::wstring & name, const std::wstring & value); - - - - /* - * - * methods for getting/finding a value - * - * - */ - - /* - * - * their working in O(log) - * can return a null pointer - * - */ - Value * GetValue(const wchar_t * name); - Value * GetValue(const std::wstring & name); - const Value * GetValue(const wchar_t * name) const; - const Value * GetValue(const std::wstring & name) const; - - - - // O(n) complexity - Value * GetValueNoCase(const wchar_t * name); - Value * GetValueNoCase(const std::wstring & name); - const Value * GetValueNoCase(const wchar_t * name) const; - const Value * GetValueNoCase(const std::wstring & name) const; - - - // they can return a null pointer if there is not such a 'name' - std::wstring * GetFirstValue(const wchar_t * name); - std::wstring * GetFirstValue(const std::wstring & name); - - const std::wstring * GetFirstValue(const wchar_t * name) const; - const std::wstring * GetFirstValue(const std::wstring & name) const; - - - /* - those methods are used to extract information from space.table - as a parameter they take the name of an option - and a default value (if there is no such a parameter), - they return appropriate value (either text, int or boolean) - (in lists they return the first item if exists) - - when calling Text(...) and AText(...) you should copy the object to whom a reference is returned - it will be cleared in a next call to one of these methods (as well to Int() Size() and Bool()) - - AText(...) always returns a reference to UTF-8 string - */ - //std::wstring Text(const wchar_t * name) const; - std::wstring Text(const wchar_t * name, const wchar_t * def = 0) const; - std::wstring Text(const std::wstring & name, const wchar_t * def = 0) const; - std::wstring Text(const std::wstring & name, const std::wstring & def) const; - - // returns a reference - // if there is no such an option then a new one (def value) is inserted - //std::wstring & TextRef(const wchar_t * name); - std::wstring & TextRef(const wchar_t * name, const wchar_t * def = 0); - std::wstring & TextRef(const std::wstring & name, const wchar_t * def = 0); - std::wstring & TextRef(const std::wstring & name, const std::wstring & def); - - - // returns UTF-8 string - //std::string TextA(const wchar_t * name) const; - std::string TextA(const wchar_t * name, const char * def) const; - std::string TextA(const std::wstring & name, const char * def) const; - std::string TextA(const std::wstring & name, const std::string & def) const; - - std::string TextA(const wchar_t * name, const wchar_t * def) const; - std::string TextA(const std::wstring & name, const wchar_t * def) const; - std::string TextA(const std::wstring & name, const std::wstring & def) const; - - - - int Int(const wchar_t * name, int def = 0) const; - int Int(const std::wstring & name, int def = 0) const; - unsigned int UInt(const wchar_t * name, unsigned int def = 0) const; - unsigned int UInt(const std::wstring & name, unsigned int def = 0) const; - - long Long(const wchar_t * name, long def = 0) const; - long Long(const std::wstring & name, long def = 0) const; - unsigned long ULong(const wchar_t * name, unsigned long def = 0) const; - unsigned long ULong(const std::wstring & name, unsigned long def = 0) const; - - long long LongLong(const wchar_t * name, long long def = 0) const; - long long LongLong(const std::wstring & name, long long def = 0) const; - unsigned long long ULongLong(const wchar_t * name, unsigned long long def = 0) const; - unsigned long long ULongLong(const std::wstring & name, unsigned long long def = 0) const; - - size_t Size(const wchar_t * name, size_t def = 0) const; - size_t Size(const std::wstring & name, size_t def = 0) const; - - bool Bool(const wchar_t * name, bool def = false) const; - bool Bool(const std::wstring & name, bool def = false) const; - - - - /* - * - * methods for adding a new value - * - * - */ - - - std::wstring & FindAdd(const wchar_t * name); - std::wstring & FindAdd(const std::wstring & name); - std::wstring & FindAdd(const WTextStream & name); - - std::wstring & Add(const wchar_t * name, bool value, bool replace_existing = true); - std::wstring & Add(const std::wstring & name, bool value, bool replace_existing = true); - std::wstring & Add(const wchar_t * name, int value, bool replace_existing = true); - std::wstring & Add(const std::wstring & name, int value, bool replace_existing = true); - std::wstring & Add(const wchar_t * name, long value, bool replace_existing = true); - std::wstring & Add(const std::wstring & name, long value, bool replace_existing = true); - std::wstring & Add(const wchar_t * name, size_t value, bool replace_existing = true); - std::wstring & Add(const std::wstring & name, size_t value, bool replace_existing = true); - - std::wstring & Add(const std::wstring & name, const std::wstring & value, bool replace_existing = true); - std::wstring & Add(const std::wstring & name, const wchar_t * value, bool replace_existing = true); - std::wstring & Add(const wchar_t * name, const wchar_t * value, bool replace_existing = true); - std::wstring & Add(const wchar_t * name, const std::wstring & value, bool replace_existing = true); - - std::wstring & Add(const wchar_t * name, const WTextStream & value, bool replace_existing = true); - std::wstring & Add(const std::wstring & name, const WTextStream & value, bool replace_existing = true); - std::wstring & Add(const WTextStream & name, const WTextStream & value, bool replace_existing = true); - - void Remove(const wchar_t * name); - void Remove(const std::wstring & name); - - - - Space & AddSpace(const wchar_t * name); - Space & AddSpace(const std::wstring & name); - - // looking for the first space with the specified name - // if there is not such a space those methods return a null pointer - Space * FindSpace(const wchar_t * name); - Space * FindSpace(const std::wstring & name); - - // looking for the first space with the specified name - // if there is not such a space then this methods adds such a space - Space & FindAddSpace(const wchar_t * name); - Space & FindAddSpace(const std::wstring & name); - - void RemoveSpace(const wchar_t * name); - void RemoveSpace(const std::wstring & name); - void RemoveSpace(size_t child_index); - - - /* - * - * - raw access to the parsed values - * - * - */ - - std::wstring name; // space name - Table table; // std::map > - - // childs - typedef std::vector Spaces; - Spaces spaces; - - // a parent space - // null means a root space - Space * parent; - - - - /* - those methods are used to extract lists - return true if such an option exists (but value can be an empty list) - */ - bool ListText(const wchar_t * name, std::vector & list); - bool ListText(const std::wstring & name, std::vector & list); - - - /* - serialize the content - */ - template - void Serialize(Stream & out, bool use_indents = false, bool use_comments = false, int level = 0) const; - - template - void SerializeTableMulti(Stream & out, bool use_indents, int level) const; - - template - static void PrintValue(Stream & out, const StringType & str, bool use_quote = true); - - template - static void PrintKey(Stream & out, const std::wstring & str); - - template - static void PrintLevel(Stream & out, bool use_indents, int level); - - - -private: - - mutable std::wstring tmp_name; - - std::wstring tmp_value; - std::wstring tmp_value_text; - std::string tmp_value_text_ascii; - - static unsigned int ToUInt(const std::wstring & value); - static int ToInt(const std::wstring & value); - static unsigned long ToULong(const std::wstring & value); - static long ToLong(const std::wstring & value); - static unsigned long long ToULongLong(const std::wstring & value); - static long long ToLongLong(const std::wstring & value); - static size_t ToSize(const std::wstring & value); - static bool ToBool(const std::wstring & value); - - static bool IsWhite(int c); - static bool HasWhite(const std::wstring & str); - -}; - - - -template -void Space::PrintLevel(Stream & out, bool use_indents, int level) -{ - if( use_indents ) + Space(bool val); + Space(short val); + Space(int val); + Space(long val); + Space(long long val); + Space(unsigned short val); + Space(unsigned int val); + Space(unsigned long val); + Space(unsigned long long val); + Space(float val); + Space(double val); + Space(const char * str); + Space(const wchar_t * str); + Space(const std::string & str); + Space(const std::wstring & str); + Space(const Space * space); + + + // set a new value + void set(bool val); + void set(short val); + void set(int val); + void set(long val); + void set(long long val); + void set(unsigned short val); + void set(unsigned int val); + void set(unsigned long val); + void set(unsigned long long val); + void set(float val); + void set(double val); + void set(const char * str); + void set(const wchar_t * str); + void set(const std::string & str); + void set(const std::wstring & str); + void set(const Space * space = nullptr); + + + // add a value to the table, change to table if needed, return the reference to the new inserted item + Space & add(bool val); + Space & add(short val); + Space & add(int val); + Space & add(long val); + Space & add(long long val); + Space & add(unsigned short val); + Space & add(unsigned int val); + Space & add(unsigned long val); + Space & add(unsigned long long val); + Space & add(float val); + Space & add(double val); + Space & add(const char * val); + Space & add(const wchar_t * val); + Space & add(const std::string & val); + Space & add(const std::wstring & val); + Space & add(const Space * space); + + // add a value to the object, change to object if needed, return the reference to the new inserted item + Space & add(const wchar_t * field, bool val); + Space & add(const wchar_t * field, short val); + Space & add(const wchar_t * field, int val); + Space & add(const wchar_t * field, long val); + Space & add(const wchar_t * field, long long val); + Space & add(const wchar_t * field, unsigned short val); + Space & add(const wchar_t * field, unsigned int val); + Space & add(const wchar_t * field, unsigned long val); + Space & add(const wchar_t * field, unsigned long long val); + Space & add(const wchar_t * field, float val); + Space & add(const wchar_t * field, double val); + Space & add(const wchar_t * field, const char * val); + Space & add(const wchar_t * field, const wchar_t * val); + Space & add(const wchar_t * field, const std::string & val); + Space & add(const wchar_t * field, const std::wstring & val); + Space & add(const wchar_t * field, const Space * space); + Space & add_empty_space(const wchar_t * field); // IMPROVEME rename me to something better + + + + bool is_null() const; + bool is_bool() const; + bool is_llong() const; + bool is_long_long() const; + bool is_float() const; + bool is_double() const; + bool is_numeric() const; + bool is_str() const; + bool is_wstr() const; + bool is_text() const; + bool is_object() const; + bool is_table() const; + + + + bool to_bool() const; + short to_short() const; + int to_int() const; + long to_long() const; + long long to_llong() const; + long long to_long_long() const; + unsigned short to_ushort() const; + unsigned int to_uint() const; + unsigned long to_ulong() const; + unsigned long long to_ullong() const; + unsigned long long to_ulong_long() const; + std::string to_str() const; + std::wstring to_wstr() const; + + + + bool * get_bool(); + long long * get_llong(); + long long * get_long_long(); + float * get_float(); + double * get_double(); + std::string * get_string(); + std::wstring * get_wstring(); + ObjectType * get_object(); + TableType * get_table(); + + + + const bool * get_bool() const; + const long long * get_llong() const; + const long long * get_long_long() const; + const float * get_float() const; + const double * get_double() const; + const std::string * get_string() const; + const std::wstring * get_wstring() const; + const ObjectType * get_object() const; + const TableType * get_table() const; + + + + std::string serialize_to_space_str() const; + std::wstring serialize_to_space_wstr() const; + void serialize_to_space_to(std::string & str) const; + void serialize_to_space_to(std::wstring & str) const; + + template + void serialize_to_space_stream(StreamType & str) const { - for(int i=0 ; i -void Space::PrintValue(Stream & out, const StringType & str, bool use_quote) -{ - if( use_quote ) - out << '\"'; - - for(size_t i=0 ; i + void serialize_to_json_stream(StreamType & str) const { - switch(str[i]) + switch(type) + { + case type_null: + serialize_json_null(str); + break; + + case type_bool: + serialize_json_bool(str); + break; + + case type_long: + serialize_json_long(str); + break; + + case type_float: + serialize_json_float(str); + break; + + case type_double: + serialize_json_double(str); + break; + + case type_string: + serialize_json_string(str); + break; + + case type_wstring: + serialize_json_wstring(str); + break; + + case type_object: + serialize_json_object(str); + break; + + case type_table: + serialize_json_table(str); + break; + } + } + + +protected: + + + template + Space & add_generic(ArgType val) + { + initialize_value_table_if_needed(); + + Space * new_space = new Space(val); + value.value_table.push_back(new_space); + + return *value.value_table.back(); + } + + + template + Space & add_generic(const wchar_t * field, ArgType val) + { + initialize_value_object_if_needed(); + + auto insert_res = value.value_object.insert(std::make_pair(field, nullptr)); + insert_res.first->second = new Space(val); + + return *(insert_res.first->second); + } + + + template + ArgType to_generic_numeric_signed_value() const + { + long long val = to_long_long(); + + if( val < std::numeric_limits::min() || val > std::numeric_limits::max() ) + val = 0; + + return val; + } + + template + ArgType to_generic_numeric_unsigned_value() const + { + unsigned long long val = to_ulong_long(); + + if( val > std::numeric_limits::max() ) + val = 0; + + return val; + } + + long long convert_string_to_long_long() const; + long long convert_wstring_to_long_long() const; + + unsigned long long convert_string_to_ulong_long() const; + unsigned long long convert_wstring_to_ulong_long() const; + + + + + template + void escape_to_space_format(int c, StreamType & out) const + { + // IMPLEMENT ME + } + + + template + void escape_to_json_format(int c, StreamType & out) const + { + switch(c) { case 0: out << '\\'; out << '0'; break; case '\r': out << '\\'; out << 'r'; break; case '\n': out << '\\'; out << 'n'; break; - case '\\': out << '\\'; out << '\\'; break; - case '"': out << '\\'; out << '\"'; break; - case '(': out << '\\'; out << '('; break; - case ')': out << '\\'; out << ')'; break; - case '=': out << '\\'; out << '='; break; + case '\\': out << '\\'; out << '\\'; break; + case '"': out << '\\'; out << '\"'; break; + //case '(': out << '\\'; out << '('; break; + //case ')': out << '\\'; out << ')'; break; + //case '=': out << '\\'; out << '='; break; default: - out << str[i]; + out << static_cast(c); } } - if( use_quote ) - out << '\"'; -} -template -void Space::PrintKey(Stream & out, const std::wstring & str) -{ -bool use_quote = false; - - // CHECK ME - // HasWhite doesn't take a new line into account, is it correct to use it here? - if( str.empty() || HasWhite(str) ) - use_quote = true; - - PrintValue(out, str, use_quote); -} - - - - -template -void Space::SerializeTableMulti(Stream & out, bool use_indents, int level) const -{ -Table::const_iterator i2; -size_t v; - - for(i2 = table.begin() ; i2 != table.end() ; ++i2) + template + void copy_input_string_to_output(const CharT * input_str, StreamType & out_str, Escape escape) const { - PrintLevel(out, use_indents, level); - PrintKey(out, i2->first); - out << L" = "; - - if( i2->second.size() != 1 ) - out << '('; - - for(v = 0 ; v < i2->second.size() ; ++v) + while( *input_str ) { - if( v > 0 ) - PrintLevel(out, use_indents, level + i2->first.size() + 3); - - PrintValue(out, i2->second[v]); - - if( v + 1 < i2->second.size() ) - out << '\n'; - } - - if( i2->second.size() != 1 ) - out << ')'; - - out << '\n'; - } -} - - -template -void Space::Serialize(Stream & out, bool use_indents, bool use_comments, int level) const -{ - if( level > 0 ) - { - out << '\n'; - PrintLevel(out, use_indents, level); - - if( !name.empty() ) - { - PrintKey(out, name); - out << ' '; - } - - out << L"(\n"; - - if( use_comments ) - { - PrintLevel(out, use_indents, level); - out << L"# space level " << level << '\n'; - } - } - - SerializeTableMulti(out, use_indents, level); - - for(size_t i=0 ; iSerialize(out, use_indents, use_comments, level+1); - - if( level > 0 ) - { - PrintLevel(out, use_indents, level); - out << ')'; - - if( use_comments ) - { - if( name.empty() ) - out << L" # end of unnamed space"; + if( escape == Escape::no_escape ) + out_str << static_cast(*input_str); else - out << L" # end of space: " << name; + if( escape == Escape::escape_space ) + escape_to_space_format(*input_str, out_str); + else + if( escape == Escape::escape_json ) + escape_to_json_format(*input_str, out_str); - out << L" (level " << level << L")"; + input_str += 1; + } + } + + template + void copy_input_stream_to_output(const StreamType & input_str, StreamType & out_str, Escape escape) const + { + typename StreamType::const_iterator i = input_str.begin(); + + while( i != input_str.end() ) + { + if( escape == Escape::no_escape ) + out_str << static_cast(*i); + else + if( escape == Escape::escape_space ) + escape_to_space_format(*i, out_str); + else + if( escape == Escape::escape_json ) + escape_to_json_format(*i, out_str); + + ++i; + } + } + + + template + void serialize_string_buffer(const char * input_str, StreamType & out_str, Escape escape) const + { + if constexpr ( sizeof(char) == sizeof(typename StreamType::char_type) ) + { + // input and output are char (we assume it is utf8) + copy_input_string_to_output(input_str, out_str, escape); + } + else + { + StreamType temp_stream; + + // input is utf8 but output is wide + UTF8ToWide(input_str, temp_stream, false); + copy_input_stream_to_output(temp_stream, out_str, escape); + } + } + + + template + void serialize_string_buffer(const wchar_t * input_str, StreamType & out_str, Escape escape) const + { + if constexpr ( sizeof(wchar_t) == sizeof(typename StreamType::char_type) ) + { + // input and output are wide characters + copy_input_string_to_output(input_str, out_str, escape); + } + else + { + StreamType temp_stream; + + // input is wide but output is utf8 + WideToUTF8(input_str, temp_stream, false); + copy_input_stream_to_output(temp_stream, out_str, escape); + } + } + + + template + void serialize_json_null(StreamType & str) const + { + serialize_string_buffer(L"null", str, Escape::escape_json); + } + + template + void serialize_json_bool(StreamType & str) const + { + if( value.value_bool ) + { + serialize_string_buffer(L"true", str, Escape::escape_json); + } + else + { + serialize_string_buffer(L"false", str, Escape::escape_json); + } + } + + + template + void serialize_json_long(StreamType & str) const + { + wchar_t buffer[50]; + size_t buffer_len = sizeof(buffer) / sizeof(char); + + PT::Toa(value.value_long, buffer, buffer_len); + serialize_string_buffer(buffer, str, Escape::escape_json); + } + + template + void serialize_json_float(StreamType & str) const + { + wchar_t buffer[50]; + size_t buffer_len = sizeof(buffer) / sizeof(char); + + std::swprintf(buffer, buffer_len, L"%f", value.value_float); + serialize_string_buffer(buffer, str, Escape::escape_json); + } + + template + void serialize_json_double(StreamType & str) const + { + wchar_t buffer[50]; + size_t buffer_len = sizeof(buffer) / sizeof(char); + + std::swprintf(buffer, buffer_len, L"%f", value.value_double); + serialize_string_buffer(buffer, str, Escape::escape_json); + } + + template + void serialize_json_string(StreamType & str) const + { + str << '"'; + serialize_string_buffer(value.value_string.c_str(), str, Escape::escape_json); + str << '"'; + } + + template + void serialize_json_wstring(StreamType & str) const + { + str << '"'; + serialize_string_buffer(value.value_wstring.c_str(), str, Escape::escape_json); + str << '"'; + } + + template + void serialize_json_object(StreamType & str) const + { + str << '{'; + + bool is_first = true; + + for(auto & map_item : value.value_object) + { + if( !is_first ) + { + str << ','; + } + + str << '"'; + serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_json); + str << '"'; + str << ':'; + map_item.second->serialize_to_json_stream(str); + is_first = false; } - out << '\n'; + str << '}'; + } + + template + void serialize_json_table(StreamType & str) const + { + str << '['; + + bool is_first = true; + + for(Space * space : value.value_table) + { + if( !is_first ) + { + str << ','; + } + + space->serialize_to_json_stream(str); + is_first = false; + } + + str << ']'; } -} +public: + + + ///////////////////////////// remove me + template + void Serialize(Stream & out, bool use_indents = false, bool use_comments = false, int level = 0) const + { + } + + template + void SerializeTableMulti(Stream & out, bool use_indents, int level) const + { + } + + template + static void PrintValue(Stream & out, const StringType & str, bool use_quote = true) + { + } + + template + static void PrintKey(Stream & out, const std::wstring & str) + { + } + + template + static void PrintLevel(Stream & out, bool use_indents, int level) + { + } + ///////////////////////////// + + +protected: + + + void copy_value_from(const Space & space); + void copy_value_object(const Value & value_from); + void copy_value_table(const Value & value_from); + + void initialize_value_null_if_needed(); + void initialize_value_bool_if_needed(); + void initialize_value_long_if_needed(); + void initialize_value_float_if_needed(); + void initialize_value_double_if_needed(); + void initialize_value_string_if_needed(); + void initialize_value_wstring_if_needed(); + void initialize_value_object_if_needed(); + void initialize_value_table_if_needed(); + + void remove_value(); + void remove_value_string(); + void remove_value_wstring(); + void remove_value_object(); + void remove_value_table(); + + +}; } // namespace