pikotools/space/space.cpp

1161 lines
18 KiB
C++

/*
* This file is a part of PikoTools
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* 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 <cstdlib>
#include <wchar.h>
#include <limits>
#include "space.h"
//#include "textstream/textstream.h"
#include "utf8/utf8.h"
#include "convert/convert.h"
namespace PT
{
Space::Space()
{
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()
{
remove_value();
}
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<long long>(val));
}
void Space::set(int val)
{
set(static_cast<long long>(val));
}
void Space::set(long val)
{
set(static_cast<long long>(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<long long>(val));
}
void Space::set(unsigned int val)
{
set(static_cast<long long>(val));
}
void Space::set(unsigned long val)
{
set(static_cast<long long>(val));
}
void Space::set(unsigned long long val)
{
set(static_cast<long long>(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_value_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<Space*>(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<short>();
}
int Space::to_int() const
{
return to_generic_numeric_signed_value<int>();
}
long Space::to_long() const
{
return to_generic_numeric_signed_value<long>();
}
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<long long>(value.value_float);
case type_double:
return static_cast<long long>(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 short>();
}
unsigned int Space::to_uint() const
{
return to_generic_numeric_unsigned_value<unsigned int>();
}
unsigned long Space::to_ulong() const
{
return to_generic_numeric_unsigned_value<unsigned long>();
}
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<unsigned long long>(value.value_long);
case type_float:
return static_cast<unsigned long long>(value.value_float);
case type_double:
return static_cast<unsigned long long>(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() 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::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_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::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;
}
} // namespace