/* * This file is a part of EZC -- Easy templating in C++ library * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * 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 void Val::set(std::vector & model_container) { clear(); type = TYPE_MODEL_CONTAINER_WRAPPER; this->model_container_wrapper = new morm::ModelWrapperVector(&model_container); } template void Val::set(std::list & model_container) { clear(); type = TYPE_MODEL_CONTAINER_WRAPPER; this->model_container_wrapper = new morm::ModelWrapperList(&model_container); } template void Val::set(std::vector & model_container) { clear(); type = TYPE_MODEL_CONTAINER_WRAPPER; this->model_container_wrapper = new morm::ModelWrapperVectorPointer(&model_container); } template void Val::set(std::list & model_container) { clear(); type = TYPE_MODEL_CONTAINER_WRAPPER; this->model_container_wrapper = new morm::ModelWrapperListPointer(&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