morm/src/baseexpression.h

890 lines
33 KiB
C++

/*
* This file is a part of morm
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2018-2023, 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.
*
*/
#ifndef headerfile_morm_src_baseexpression
#define headerfile_morm_src_baseexpression
#include <list>
#include <set>
#include <type_traits>
#include "textstream/textstream.h"
#include "date/date.h"
#include "morm_types.h"
#include "modelenv.h"
#include "ft.h"
#include "export.h"
#include "convert/text.h"
#ifdef MORM_HAS_EZC_LIBRARY
#include "funinfo.h"
#endif
namespace morm
{
class Model;
class ModelConnector;
class BaseExpression
{
public:
BaseExpression();
virtual ~BaseExpression();
BaseExpression(const BaseExpression &) = delete;
BaseExpression(BaseExpression &&) = delete;
virtual void set_work_mode(int work_mode);
virtual int get_work_mode();
virtual void set_output_type(int output_type);
virtual int get_output_type();
virtual pt::TextStream * get_text_stream();
virtual void set_text_stream(pt::TextStream * out_stream);
virtual void clear();
virtual void generate_from_model(pt::TextStream & stream, Model & model);
virtual void generate_from_model(pt::TextStream & stream, Model & model, const FT & field_type);
virtual pt::TextStream * get_current_stream();
// rename me
virtual void allow_to_use_prefix(bool use_prefix);
virtual bool get_allow_to_use_prefix();
template<typename FieldValue>
void field(const wchar_t * field_name, const FieldValue & field_value, const FT & field_type, ModelEnv * model_env)
{
field_generic(field_name, field_value, nullptr, field_type, model_env);
}
virtual void field(const wchar_t * field_name, void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env)
{
int tmp_object = 0;
field_generic(field_name, tmp_object, getter_method, field_type, model_env);
}
template<typename FieldValue>
void field_generic(const wchar_t * field_name, const FieldValue & field_value, void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env)
{
if( out_stream && can_field_be_generated(field_type) )
{
field_before();
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_SAVE_FIELDS )
{
save_foreign_key(field_name, field_type, model_env);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_VALUES )
{
put_field_value_or_null(field_value, getter_method, field_type, model_env);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{
put_field_name_and_value(field_name, field_value, getter_method, field_type, model_env);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
{
put_field_name_and_value_and_closing_name(field_name, field_value, getter_method, field_type, model_env);
}
field_after();
}
}
template<typename FieldValue>
void field_in(pt::TextStream & stream, const wchar_t * field_name, const std::set<FieldValue> & container, ModelEnv * model_env)
{
field_in_generic<FieldValue, std::set<FieldValue>>(stream, field_name, container, model_env);
}
template<typename FieldValue>
void field_in(pt::TextStream & stream, const wchar_t * field_name, const std::list<FieldValue> & container, ModelEnv * model_env)
{
field_in_generic<FieldValue, std::list<FieldValue>>(stream, field_name, container, model_env);
}
template<typename FieldValue>
void field_in(pt::TextStream & stream, const wchar_t * field_name, const std::vector<FieldValue> & container, ModelEnv * model_env)
{
field_in_generic<FieldValue, std::vector<FieldValue>>(stream, field_name, container, model_env);
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void field_list(const wchar_t * field_name, ModelContainer & field_value, ModelContainerType * model_container_type,
const FT & field_type, ModelConnector * model_connector, ModelEnv * model_env, IsContainerByValueRenameMe * foo)
{
if( out_stream && can_field_be_generated(field_type) && can_field_list_be_generated(field_type) )
{
field_before();
// if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
// {
// put_field_name_and_table_if_needed(field_name);
// }
// else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{
put_field_name_and_value_list(field_name, field_value, model_container_type, field_type, model_connector, model_env, foo);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
{
put_field_name_and_value_list_and_closing_name(field_name, field_value, model_container_type, field_type, model_connector, model_env, foo);
}
field_after();
}
}
template<typename ModelClass>
void field_model(const wchar_t * field_name, ModelClass & field_model, const FT & field_type, ModelEnv * model_env)
{
if( out_stream && can_field_be_generated(field_type) && can_field_model_be_generated(field_model.get_has_primary_key_set(), field_type) )
{
field_before();
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
{
if( output_type == MORM_OUTPUT_TYPE_FIELDS_RECURSIVE )
generate_from_model(field_model, field_type);
else
put_field_name_and_table_if_needed(field_name, field_type, model_env);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_VALUES )
{
generate_from_model(field_model, field_type);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{
put_field_name_and_value_model(field_name, field_model, field_type, model_env);
}
else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
{
put_field_name_and_value_model_and_closing_name(field_name, field_model, field_type, model_env);
}
field_after();
}
}
template<typename FieldValue>
void field_to_stream(pt::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, const FT & field_type, ModelEnv * model_env)
{
this->out_stream = &stream;
field(field_name, field_value, field_type, model_env);
this->out_stream = nullptr;
}
template<typename FieldValue>
void value_to_stream(pt::TextStream & stream, const FieldValue & field_value, const FT & field_type, ModelEnv * model_env = nullptr)
{
this->out_stream = &stream;
put_field_value(field_value, field_type, model_env);
this->out_stream = nullptr;
}
virtual void put_schema_table(const wchar_t * schema_name, const wchar_t * table_name);
virtual void put_schema_table(const pt::WTextStream & schema_name, const pt::WTextStream & table_name);
virtual void put_table(const wchar_t * table_name);
virtual void put_table(const pt::WTextStream & table_name);
virtual void put_table_with_index(const wchar_t * table_name, int index);
virtual void put_table_with_index(const pt::WTextStream & table_name, int index);
virtual void put_table_with_index_and_field(const wchar_t * table_name, int index, const wchar_t * field_name, const FT & field_type);
virtual void put_table_with_index_and_field(const pt::WTextStream & table_name, int index, const wchar_t * field_name, const FT & field_type);
virtual void put_table_and_field(const wchar_t * table_name, const wchar_t * field_name, const FT & field_type);
virtual void put_table_and_field(const pt::WTextStream & table_name, const wchar_t * field_name, const FT & field_type);
virtual void put_alias(const pt::WTextStream & alias_name, int index);
virtual void put_alias(const pt::WTextStream & alias_name_prefix, int index, const wchar_t * alias_name_postfix);
virtual void put_string(const char * str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void put_string(const wchar_t * str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void put_string(const std::string & str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void put_string(const std::wstring & str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void put_stream(const pt::TextStream & str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void put_stream(const pt::WTextStream & str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void schema_table_to_stream(pt::TextStream & stream, const wchar_t * schema_name, const wchar_t * table_name);
virtual void schema_table_to_stream(pt::TextStream & stream, const pt::WTextStream & schema_name, const pt::WTextStream & table_name);
virtual void table_to_stream(pt::TextStream & stream, const wchar_t * table_name);
virtual void table_to_stream(pt::TextStream & stream, const pt::WTextStream & table_name);
virtual void table_with_index_to_stream(pt::TextStream & stream, const wchar_t * table_name, int index);
virtual void table_with_index_to_stream(pt::TextStream & stream, const pt::WTextStream & table_name, int index);
virtual void table_with_index_and_field_to_stream(pt::TextStream & stream, const wchar_t * table_name, int index, const wchar_t * field_name, const FT & field_type);
virtual void table_with_index_and_field_to_stream(pt::TextStream & stream, const pt::WTextStream & table_name, int index, const wchar_t * field_name, const FT & field_type);
virtual void table_and_field_to_stream(pt::TextStream & stream, const wchar_t * table_name, const wchar_t * field_name, const FT & field_type);
virtual void table_and_field_to_stream(pt::TextStream & stream, const pt::WTextStream & table_name, const wchar_t * field_name, const FT & field_type);
virtual void alias_to_stream(pt::TextStream & stream, const pt::WTextStream & alias_name, int index);
virtual void alias_to_stream(pt::TextStream & stream, const pt::WTextStream & alias_name_prefix, int index, const wchar_t * alias_name_postfix);
virtual void string_to_stream(pt::TextStream & stream, const char * str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void string_to_stream(pt::TextStream & stream, const wchar_t * str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void string_to_stream(pt::TextStream & stream, const std::string & str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void string_to_stream(pt::TextStream & stream, const std::wstring & str, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void stream_to_stream(pt::TextStream & stream_out, const pt::TextStream & stream_in, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
virtual void stream_to_stream(pt::TextStream & stream_out, const pt::WTextStream & stream_in, const FT & field_type, bool add_quotes = false, ModelEnv * model_env = nullptr);
template<typename StringType>
void put_string_generic(const StringType * str, const FT & field_type, bool add_quotes, ModelEnv * model_env = nullptr)
{
if( out_stream )
{
if( add_quotes )
{
before_field_value_string(field_type, model_env);
}
esc(str, *out_stream, field_type, model_env);
if( add_quotes )
{
after_field_value_string(field_type, model_env);
}
}
}
template<typename StringOrStreamType>
void put_string_generic(const StringOrStreamType & str, const FT & field_type, bool add_quotes, ModelEnv * model_env = nullptr)
{
if( out_stream )
{
if( add_quotes )
{
before_field_value_string(field_type, model_env);
}
esc(str, *out_stream, field_type, model_env);
if( add_quotes )
{
after_field_value_string(field_type, model_env);
}
}
}
/*
* IMPLEMENT ME
* esc for: signed char, wchar_t, char16_t, char32_t
*
*/
virtual bool esc_char(char val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual bool esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(char val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(unsigned char val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(wchar_t val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const std::wstring & val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const wchar_t * val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const std::string & val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const char * val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(bool val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(short val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(unsigned short val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(int val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(unsigned int val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(long val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(unsigned long val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(long long val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(unsigned long long val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(float val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(double val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(long double val, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const pt::Date & date, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const pt::TextStream & val,pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const pt::WTextStream & val,pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
virtual void esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type = FT::default_type, ModelEnv * model_env = nullptr);
protected:
int work_mode; /* what to do: generating fields list, values list or fields-values list */
int output_type;
bool is_first_field;
pt::TextStream * out_stream;
bool use_prefix;
pt::TextStream scratch_buffer_local;
pt::TextStream * scratch_buffer;
virtual void generate_from_model(Model & model, const FT & field_type);
virtual void before_generate_from_model();
virtual void after_generate_from_model();
virtual bool can_field_be_generated(const FT &);
virtual bool can_field_model_be_generated(bool has_model_primary_key, const FT & field_type);
virtual bool can_field_list_be_generated(const FT &);
virtual bool should_field_model_be_generated_as_null(bool has_model_primary_key, const FT & field_type);
virtual void field_before();
virtual void field_after();
virtual void put_field_name_and_table_if_needed(const wchar_t * field_name, const FT & field_type, ModelEnv * model_env);
virtual void put_field_name(const wchar_t * field_name, const FT & field_type, ModelEnv * model_env);
virtual void put_field_closing_name(const wchar_t * field_name, const FT & field_type, ModelEnv * model_env);
virtual void put_value_list_opening_index(size_t index, const FT & field_type);
virtual void put_value_list_closing_index(size_t index, const FT & field_type);
virtual void save_foreign_key(const wchar_t * field_name, const FT & field_type, ModelEnv * model_env);
virtual void dump_additional_info(Model & model);
virtual void add_additional_columns(Model & model);
template<typename FieldValue>
void put_field_value(const FieldValue & field_value, const FT & field_type, ModelEnv * model_env = nullptr)
{
if( out_stream )
{
before_field_value(field_value, field_type, model_env);
esc(field_value, *out_stream, field_type, model_env);
after_field_value(field_value, field_type, model_env);
}
}
void put_field_value(void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env = nullptr)
{
if( out_stream && model_env && model_env->model && getter_method )
{
before_field_value_string(field_type, model_env);
if( scratch_buffer )
{
scratch_buffer->clear();
(model_env->model->*getter_method)(*scratch_buffer);
esc(*scratch_buffer, *out_stream, field_type, model_env);
scratch_buffer->clear();
}
after_field_value_string(field_type, model_env);
}
}
virtual void put_null_value()
{
(*out_stream) << "null";
}
virtual void before_field_value_list()
{
}
virtual void after_field_value_list()
{
}
virtual void field_value_list_separator()
{
(*out_stream) << ",";
}
virtual void put_statement_in_starts()
{
(*out_stream) << "(";
}
virtual void put_statement_in_ends()
{
(*out_stream) << ") ";
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void put_field_value_list(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type,
ModelConnector * model_connector, ModelEnv * model_env, IsContainerByValueRenameMe * foo)
{
if constexpr (std::is_base_of<Model, ModelContainerType>())
{
if constexpr (std::is_base_of<Model, IsContainerByValueRenameMe>())
{
put_field_value_list_model_by_value(field_value, model_container_type, field_type, model_connector, model_env);
}
else
{
put_field_value_list_model_by_pointer(field_value, model_container_type, field_type, model_connector, model_env);
}
}
else
{
put_field_value_list_non_model(field_value, model_connector, field_type);
}
}
template<typename ModelContainer, typename ModelContainerType>
void put_field_value_list_model_by_value(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type,
ModelConnector * model_connector, ModelEnv * model_env)
{
if( model_connector && model_env && out_stream )
{
before_field_value_list();
size_t index = 0;
for(auto & child_model_item : field_value)
{
if( can_field_model_be_generated(child_model_item.get_has_primary_key_set(), field_type) )
{
if( index > 0 )
{
field_value_list_separator();
}
put_value_list_opening_index(index, field_type);
put_field_value_list_model(child_model_item, model_connector, model_env);
put_value_list_closing_index(index, field_type);
index += 1;
}
}
after_field_value_list();
}
}
template<typename ModelContainer, typename ModelContainerType>
void put_field_value_list_model_by_pointer(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type,
ModelConnector * model_connector, ModelEnv * model_env)
{
if( model_connector && model_env && out_stream )
{
before_field_value_list();
size_t index = 0;
for(auto * child_model_item : field_value)
{
if( can_field_model_be_generated(child_model_item->get_has_primary_key_set(), field_type) )
{
if( index > 0 )
{
field_value_list_separator();
}
put_value_list_opening_index(index, field_type);
put_field_value_list_model(*child_model_item, model_connector, model_env);
put_value_list_closing_index(index, field_type);
index += 1;
}
}
after_field_value_list();
}
}
template<typename ModelContainerType>
void put_field_value_list_model(ModelContainerType & child_model, ModelConnector * model_connector, ModelEnv * model_env)
{
ModelEnv model_env_local(*model_env);
child_model.model_env = &model_env_local;
child_model.model_env->has_primary_key_set = child_model.get_has_primary_key_set();
child_model.model_env->model = &child_model;
child_model.set_connector(model_connector);
FT field_type = FT::default_type;
generate_from_model(child_model, field_type);
child_model.model_env = nullptr;
}
template<typename ModelContainer>
void put_field_value_list_non_model(ModelContainer & field_value, ModelConnector * model_connector, const FT & field_type)
{
if( model_connector && out_stream )
{
before_field_value_list();
size_t index = 0;
for(const auto & m : field_value)
{
if( index > 0 )
{
field_value_list_separator();
}
put_value_list_opening_index(index, field_type);
put_field_value(m, FT::default_type);
put_value_list_closing_index(index, field_type);
index += 1;
}
after_field_value_list();
}
}
// used in 'in()' statements, may should be renamed?
template<typename FieldValue, typename Container>
void field_in_generic(pt::TextStream & stream, const wchar_t * field_name, const Container & container, ModelEnv * model_env)
{
// IMPROVE ME
// what about if container is empty?
// only 'in()' statement would be generated
this->out_stream = &stream;
field_before();
put_field_name_and_table_if_needed(field_name, FT::default_type, model_env);
put_name_value_separator();
bool is_first = true;
put_statement_in_starts();
for(const FieldValue & v : container)
{
if( !is_first )
{
field_value_list_separator();
}
put_field_value(v, FT::default_type, model_env);
is_first = false;
}
put_statement_in_ends();
field_after();
this->out_stream = nullptr;
}
virtual void schema_table_separator();
virtual void table_field_separator();
virtual void alias_names_separator();
virtual void before_schema_name();
virtual void after_schema_name();
virtual void before_table_name();
virtual void after_table_name();
virtual void before_field_name();
virtual void after_field_name();
virtual void before_alias_name();
virtual void after_alias_name();
virtual void before_field_value(const std::wstring &, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const std::wstring &, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(const std::string &, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const std::string &, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(const wchar_t *, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const wchar_t *, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(const char *, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const char *, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(wchar_t, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(wchar_t, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(char, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(char, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(const pt::Date &, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const pt::Date &, const FT & field_type, ModelEnv * model_env);
virtual void before_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env);
template<typename FieldValue>
void before_field_value(const FieldValue &, const FT & field_type, ModelEnv * model_env)
{
}
template<typename FieldValue>
void after_field_value(const FieldValue &, const FT & field_type, ModelEnv * model_env)
{
}
virtual void put_name_value_separator();
/*
* IMPLEMENT ME
* put_type for: signed char, wchar_t, char16_t, char32_t
*
*/
// virtual void put_type(char val, pt::TextStream & stream);
// virtual void put_type(unsigned char val, pt::TextStream & stream);
//
// virtual void put_type(const std::wstring & val, pt::TextStream & stream);
// virtual void put_type(const wchar_t * val, pt::TextStream & stream);
//
// virtual void put_type(const std::string & val, pt::TextStream & stream);
// virtual void put_type(const char * val, pt::TextStream & stream);
//
// virtual void put_type(bool val, pt::TextStream & stream);
// virtual void put_type(short val, pt::TextStream & stream);
// virtual void put_type(unsigned short val, pt::TextStream & stream);
// virtual void put_type(int val, pt::TextStream & stream);
// virtual void put_type(unsigned int val, pt::TextStream & stream);
// virtual void put_type(long val, pt::TextStream & stream);
// virtual void put_type(unsigned long val, pt::TextStream & stream);
// virtual void put_type(long long val, pt::TextStream & stream);
// virtual void put_type(unsigned long long val, pt::TextStream & stream);
// virtual void put_type(float val, pt::TextStream & stream);
// virtual void put_type(double val, pt::TextStream & stream);
// virtual void put_type(long double val, pt::TextStream & stream);
//virtual void put_type(void* val, pt::TextStream & stream);
// virtual void put_type(const pt::Date & date, pt::TextStream & stream);
// virtual void put_type(const Model & model, pt::TextStream & stream);
//
// template<typename ListType>
// void put_type(const std::list<ListType> & model, pt::TextStream & stream)
// {
// stream << "table"; // may just use std::list?
// }
//
// template<typename ListType>
// void put_type(const std::vector<ListType> & model, pt::TextStream & stream)
// {
// stream << "table"; // may just just std::vector?
// }
virtual void before_field_value_string(const FT & field_type, ModelEnv * model_env);
virtual void after_field_value_string(const FT & field_type, ModelEnv * model_env);
char char_to_hex_part(char c);
void char_to_hex(char c, pt::TextStream & stream);
void char_to_hex(wchar_t c, pt::TextStream & stream);
void esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env);
void esc(const char * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env);
bool is_empty_field(const wchar_t * value);
template<typename CharType>
void esc_normal_string(CharType * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env)
{
for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i)
{
esc(val[i], stream, field_type, model_env);
}
}
template<typename CharType>
void esc_numeric_string(CharType * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env)
{
bool was_comma = false;
bool was_something_printed = false;
bool was_digit_printed = false;
for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i)
{
typename std::remove_const<CharType>::type c = val[i];
if( c == ',' )
c = '.';
if( (c=='.' && !was_comma) || (c>='0' && c<='9') || (c=='-' && !was_something_printed) )
{
if( c=='.' )
{
if( !was_digit_printed )
{
esc(static_cast<CharType>('0'), stream, field_type, model_env);
was_digit_printed = true;
}
was_comma = true;
}
esc(c, stream, field_type, model_env);
was_something_printed = true;
if( c>='0' && c<='9' )
{
was_digit_printed = true;
}
}
}
if( !was_digit_printed )
{
esc(static_cast<CharType>('0'), stream, field_type, model_env);
}
}
template<typename FieldValue>
void put_field_value_or_null(const FieldValue & field_value, void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env)
{
if( getter_method )
{
put_field_value(getter_method, field_type, model_env);
}
else
{
if( field_type.is_primary_key() )
{
if( model_env && model_env->has_primary_key_set )
put_field_value(field_value, field_type, model_env);
else
put_null_value();
}
else
{
put_field_value(field_value, field_type, model_env);
}
}
}
template<typename FieldValue>
void put_field_name_and_value(const wchar_t * field_name, const FieldValue & field_value, void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env)
{
bool allow_to_put_value = (get_output_type() != MORM_OUTPUT_TYPE_WHERE_IS_NULL && get_output_type() != MORM_OUTPUT_TYPE_WHERE_IS_NOT_NULL);
if( model_env && model_env->set_field_name_helper )
{
if( (size_t)model_env->field_index < model_env->set_field_name_helper->size() )
{
put_field_name_and_table_if_needed((*model_env->set_field_name_helper)[model_env->field_index], field_type, model_env);
put_name_value_separator();
if( allow_to_put_value )
put_field_value_or_null(field_value, getter_method, field_type, model_env);
}
model_env->field_index += 1;
}
else
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator();
if( allow_to_put_value )
put_field_value_or_null(field_value, getter_method, field_type, model_env);
}
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void put_field_name_and_value_list(const wchar_t * field_name, ModelContainer & field_value, ModelContainerType * model_container_type,
const FT & field_type, ModelConnector * model_connector, ModelEnv * model_env, IsContainerByValueRenameMe * foo)
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator();
put_field_value_list(field_value, model_container_type, field_type, model_connector, model_env, foo);
}
template<typename ModelClass>
void put_field_name_and_value_model(const wchar_t * field_name, ModelClass & field_model, const FT & field_type, ModelEnv * model_env)
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator();
generate_from_model(field_model, field_type);
}
template<typename FieldValue>
void put_field_name_and_value_and_closing_name(const wchar_t * field_name, const FieldValue & field_value, void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env)
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator();
put_field_value_or_null(field_value, getter_method, field_type, model_env);
put_name_value_separator();
put_field_closing_name(field_name, field_type, model_env);
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void put_field_name_and_value_list_and_closing_name(const wchar_t * field_name, ModelContainer & field_value, ModelContainerType * model_container_type,
const FT & field_type, ModelConnector * model_connector, ModelEnv * model_env, IsContainerByValueRenameMe * foo)
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator();
put_field_value_list(field_value, model_container_type, field_type, model_connector, model_env, foo);
put_name_value_separator();
put_field_closing_name(field_name, field_type, model_env);
}
template<typename ModelClass>
void put_field_name_and_value_model_and_closing_name(const wchar_t * field_name, ModelClass & field_model, const FT & field_type, ModelEnv * model_env)
{
put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator();
generate_from_model(field_model, field_type);
put_name_value_separator();
put_field_closing_name(field_name, field_type, model_env);
}
};
}
#endif