Files
ezc/src/val.cpp

1013 lines
15 KiB
C++

/*
* This file is a part of EZC -- Easy templating in C++ library
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2024, 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 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 HOLDER 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 "val.h"
#ifdef EZC_HAS_MORM_LIBRARY
#include "model.h"
#endif
namespace Ezc
{
Val::Val()
{
output_stream = nullptr;
output_stream_original_size = 0;
initialize_empty();
}
Val::Val(pt::Stream * output_stream)
{
this->output_stream = output_stream;
this->output_stream_original_size = output_stream->size();
initialize_empty();
}
Val::Val(const Val & val)
{
initialize_empty();
copy(val);
}
Val & Val::operator=(const Val & val)
{
clear();
copy(val);
return *this;
}
void Val::copy(const Val & val)
{
type = val.type;
user_function = val.user_function;
model = val.model;
model_container_wrapper = val.model_container_wrapper;
date = val.date;
space_wrapper = val.space_wrapper;
space_local = val.space_local;
stream = val.stream;
space = val.space;
output_stream = val.output_stream;
output_stream_original_size = val.output_stream_original_size;
if( model_container_wrapper )
{
model_container_wrapper->increment_reference_counter();
}
if( space_wrapper )
{
space_wrapper->increment_reference_counter();
}
// childs_map don't need to be copied
}
Val::~Val()
{
clear();
}
// output_stream can be a nullpointer
void Val::set_output_stream(pt::Stream * output_stream)
{
this->output_stream = output_stream;
this->output_stream_original_size = (output_stream) ? output_stream->size() : 0;
}
void Val::set_output_stream(pt::Stream & output_stream)
{
set_output_stream(&output_stream);
}
void Val::initialize_empty()
{
type = TYPE_VOID;
user_function = nullptr;
model = nullptr;
model_container_wrapper = nullptr;
date = nullptr;
space_wrapper = nullptr;
space = nullptr;
stream = nullptr;
item_block = nullptr;
}
void Val::clear()
{
if( model_container_wrapper )
{
model_container_wrapper->decrement_reference_counter();
if( model_container_wrapper->get_reference_counter() == 0 && model_container_wrapper->should_be_auto_removed() )
{
delete model_container_wrapper;
}
}
if( space_wrapper )
{
space_wrapper->decrement_reference_counter();
if( space_wrapper->get_reference_counter() == 0 && space_wrapper->should_be_auto_removed() )
{
delete space_wrapper;
}
}
initialize_empty();
space_local.clear();
clear_childs();
}
void Val::clear_childs()
{
childs_map.clear();
}
Val * Val::add_child(const std::wstring & child_name, const Val & val)
{
Val & v = childs_map[child_name];
v.clear();
v = val;
return &v;
}
Val * Val::find_child(const std::wstring & child_name)
{
auto i = childs_map.find(child_name);
if( i != childs_map.end() )
{
return &i->second;
}
return nullptr;
}
bool Val::has_object()
{
return type != TYPE_VOID;
}
bool Val::has_model_object()
{
return model || model_container_wrapper;
}
bool Val::to_bool() const
{
switch(type)
{
case TYPE_VOID:
return false;
case TYPE_SPACE_LOCAL:
return space_local.to_bool();
case TYPE_STREAM:
return !stream->empty();
case TYPE_FUNCTION:
case TYPE_DATE: // date can be evaluated to true if it's different than the Unix epoch
case TYPE_MODEL:
case TYPE_ITEM_BLOCK:
break;
case TYPE_SPACE_WRAPPER:
return space_wrapper->get_space()->to_bool();
case TYPE_SPACE:
return space->to_bool();
case TYPE_MODEL_CONTAINER_WRAPPER:
return !model_container_wrapper->is_container_empty();
case TYPE_OUTPUT_STREAM:
return output_stream->size() != output_stream_original_size;
}
return false;
}
void Val::set(const char * str)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(str);
}
void Val::set(const wchar_t * str)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(str);
}
void Val::set(const std::string & str)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(str);
}
void Val::set(const std::wstring & str)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(str);
}
void Val::set(bool val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(short val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(int val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(long val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(long long val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(unsigned short val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(unsigned int val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(unsigned long val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(unsigned long long val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(float val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(double val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(long double val)
{
clear();
type = TYPE_SPACE_LOCAL;
space_local.set(val);
}
void Val::set(pt::Stream & str)
{
clear();
type = TYPE_STREAM;
this->stream = &str;
}
void Val::set(UserFunction user_function)
{
clear();
type = TYPE_FUNCTION;
this->user_function = user_function;
}
void Val::set(pt::Date & date)
{
clear();
type = TYPE_DATE;
this->date = &date;
}
void Val::set(morm::Model & model)
{
clear();
type = TYPE_MODEL;
this->model = &model;
}
void Val::set(morm::ModelContainerWrapper & model_container_wrapper)
{
clear();
type = TYPE_MODEL_CONTAINER_WRAPPER;
this->model_container_wrapper = &model_container_wrapper;
this->model_container_wrapper->increment_reference_counter();
}
template<typename ModelType>
void Val::set(std::vector<ModelType> & model_container)
{
clear();
type = TYPE_MODEL_CONTAINER_WRAPPER;
this->model_container_wrapper = new morm::ModelWrapperVector<ModelType>(&model_container);
}
template<typename ModelType>
void Val::set(std::list<ModelType> & model_container)
{
clear();
type = TYPE_MODEL_CONTAINER_WRAPPER;
this->model_container_wrapper = new morm::ModelWrapperList<ModelType>(&model_container);
}
template<typename ModelType>
void Val::set(std::vector<ModelType*> & model_container)
{
clear();
type = TYPE_MODEL_CONTAINER_WRAPPER;
this->model_container_wrapper = new morm::ModelWrapperVectorPointer<ModelType>(&model_container);
}
template<typename ModelType>
void Val::set(std::list<ModelType*> & model_container)
{
clear();
type = TYPE_MODEL_CONTAINER_WRAPPER;
this->model_container_wrapper = new morm::ModelWrapperListPointer<ModelType>(&model_container);
}
void Val::set(morm::SpaceWrapper & space_wrapper)
{
clear();
type = TYPE_SPACE_WRAPPER;
this->space_wrapper = &space_wrapper;
this->space_wrapper->increment_reference_counter();
}
void Val::set(pt::Space & space, bool create_wrapper)
{
clear();
if( create_wrapper )
{
type = TYPE_SPACE_WRAPPER;
this->space_wrapper = new morm::SpaceWrapper(&space);
}
else
{
type = TYPE_SPACE;
this->space = &space;
}
}
void Val::set(Val & val)
{
clear();
switch(val.type)
{
case TYPE_VOID:
break;
case TYPE_SPACE_LOCAL:
space_local = val.space_local;
break;
case TYPE_STREAM:
stream = val.stream;
break;
case TYPE_FUNCTION:
user_function = val.user_function;
break;
case TYPE_DATE:
date = val.date;
break;
case TYPE_MODEL:
model = val.model;
break;
case TYPE_SPACE_WRAPPER:
space_wrapper = val.space_wrapper;
break;
case TYPE_SPACE:
space = val.space;
break;
case TYPE_MODEL_CONTAINER_WRAPPER:
model_container_wrapper = val.model_container_wrapper;
break;
case TYPE_OUTPUT_STREAM:
output_stream = val.output_stream;
break;
case TYPE_ITEM_BLOCK:
item_block = val.item_block;
break;
}
}
void Val::set(Item & item_block)
{
clear();
type = TYPE_ITEM_BLOCK;
this->item_block = &item_block;
}
// bool Val::is_equal(const char * str) const
// {
// switch(type)
// {
// case TYPE_SPACE_LOCAL:
// if( space_local.is_str() || space_local.is_wstr() )
// return is_equal_string(str);
// if( space_local.is_bool() )
// return is_equal_bool(str);
// // IMPLEMENTME
// // implement the rest of conversion methods
// return false;
// case TYPE_VOID:
// case TYPE_STREAM:
// case TYPE_FUNCTION:
// case TYPE_DATE:
// case TYPE_MODEL:
// case TYPE_MODEL_CONTAINER_WRAPPER:
// case TYPE_SPACE_WRAPPER:
// case TYPE_SPACE:
// // IMPLEMENTME
// break;
// }
// return false;
// }
// bool Val::is_equal(const wchar_t * str) const
// {
// switch(type)
// {
// case TYPE_SPACE_LOCAL:
// if( space_local.is_str() || space_local.is_wstr() )
// return is_equal_string(str);
// if( space_local.is_bool() )
// return is_equal_bool(str);
// // IMPLEMENTME
// // implement the rest of conversion methods
// return false;
// case TYPE_VOID:
// case TYPE_STREAM:
// case TYPE_FUNCTION:
// case TYPE_DATE:
// case TYPE_MODEL:
// case TYPE_MODEL_CONTAINER_WRAPPER:
// case TYPE_SPACE_WRAPPER:
// case TYPE_SPACE:
// // IMPLEMENTME
// break;
// }
// return false;
// }
// bool Val::is_equal(const std::string & str) const
// {
// return is_equal(str.c_str());
// }
// bool Val::is_equal(const std::wstring & str) const
// {
// return is_equal(str.c_str());
// }
// bool Val::is_equal_bool(const char * str) const
// {
// if( space_local.to_bool() )
// {
// return str[0] != 0;
// }
// else
// {
// return str[0] == 0;
// }
// }
// bool Val::is_equal_string(const char * str) const
// {
// if( space_local.is_str() )
// {
// return space_local.is_equal(str);
// }
// else
// if( space_local.is_wstr() )
// {
// std::string space_str_utf8;
// pt::wide_to_utf8(*space_local.get_wstr(), space_str_utf8);
// return space_str_utf8 == str;
// }
// return false;
// }
// bool Val::is_equal_bool(const wchar_t * str) const
// {
// if( space_local.to_bool() )
// {
// return str[0] != 0;
// }
// else
// {
// return str[0] == 0;
// }
// }
// bool Val::is_equal_string(const wchar_t * str) const
// {
// if( space_local.is_wstr() )
// {
// return space_local.is_equal(str);
// }
// else
// if( space_local.is_str() )
// {
// std::string str_utf8;
// pt::wide_to_utf8(str, str_utf8);
// return space_local.is_equal(str_utf8);
// }
// return false;
// }
void Val::serialize_to(pt::Stream & str)
{
str.escape_input(true);
morm::Model * m;
switch(type)
{
case TYPE_SPACE_LOCAL:
space_local.serialize_to_string(str);
break;
case TYPE_STREAM:
str << stream; // operator(void*) will be taken? !!!!
break;
case TYPE_DATE:
date->SerializeISO(str);
break;
case TYPE_MODEL:
model->to_text(str);
break;
case TYPE_MODEL_CONTAINER_WRAPPER:
m = model_container_wrapper->get_model();
if( m )
m->to_text(str);
break;
case TYPE_SPACE_WRAPPER:
space_wrapper->get_space()->serialize_to_string(str);
break;
case TYPE_SPACE:
space->serialize_to_string(str);
break;
case TYPE_VOID:
case TYPE_FUNCTION:
case TYPE_OUTPUT_STREAM:
case TYPE_ITEM_BLOCK:
break;
}
}
void Val::assert_type_output_stream()
{
if( type != Val::TYPE_OUTPUT_STREAM )
{
clear();
type = TYPE_OUTPUT_STREAM;
}
}
Val & Val::operator<<(const char * str)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << str;
}
return *this;
}
Val & Val::operator<<(const wchar_t * str)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << str;
}
return *this;
}
Val & Val::operator<<(const std::string & str)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << str;
}
return *this;
}
Val & Val::operator<<(const std::wstring & str)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << str;
}
return *this;
}
Val & Val::operator<<(char val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(unsigned char val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(wchar_t val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(bool val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(short val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(int val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(long val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(long long val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(unsigned short val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(unsigned int val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(unsigned long val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(unsigned long long val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(float val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(double val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(long double val)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << val;
}
return *this;
}
Val & Val::operator<<(const pt::Stream & str)
{
assert_type_output_stream();
if( output_stream )
{
*output_stream << str;
}
return *this;
}
Val & Val::operator=(bool res)
{
set(res);
return *this;
}
} // namespace Ezc