/*
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/*
  <file> UlsFactory.cpp </file>
  <brief>
   This implements ULS API based on C++.NET
  </brief>
  <author>
    Stanley Hong <link2next@gmail.com>, April 2017.
  </author>
*/
#include "Stdafx.h"

#include <io.h>
#include <direct.h>
#include <errno.h>
#include <sys/types.h>

#include "UlsFactory.h"

using namespace System;

namespace uls {
	namespace polaris {
		//
		// Class: UlsFactory
		//
#define ULS_CLASS_NAME UlsFactory

#define _uls_log_primitive(proc) _log_->proc
#define _uls_log_static(proc) UlsLog::proc##_static

#define _uls_log(proc) _log_->proc
#define _uls_log_(proc) _log_->uls_##proc

#define _uls_tool(proc) _tool_->proc
#define _uls_tool_(proc) _tool_->uls_##proc
#define __uls_tool_(proc) _tool_->_uls_##proc

#define _uls_sysinfo_(attr) _sysprops_->attr

#define ULS_EXCLUDE_HFILES

#define uls_sysprn_tabs(n,fmt,...) do { \
	_uls_log_(sysprn_puttabs)(n); _uls_log_(sysprn)(fmt,##__VA_ARGS__); } while (0)

#include "uls_tokdef.c"
#include "litesc.c"
#include "litstr.c"

#include "uls_langs.c"
#include "idkeyw.c"
#include "onechar.c"
#include "twoplus.c"
#include "uls_freq.c"
#include "uls_util.c"

#include "utf_file.c"
#include "uls_input.c"
#include "uls_stream.c"
#include "uls_context.c"
#include "uls_dump.c"
#include "uls_conf.c"
#include "uld_conf.c"
#include "uls_emit.c"

#include "uls_core.c"
#include "unget.c"
#include "uls_istream.c"
#include "uls_lex.c"
#include "uls_ostream.c"
#include "uls_init.c"
#undef ULS_EXCLUDE_HFILES

	ULS_CLASS_NAME::ULS_CLASS_NAME()
	{
		_tool_ = gcnew UlsToolbase();
		_log_ = _tool_->getUlsLog();
		_sysprops_ = _tool_->getUlsSysprops();

		// delegate
		_uls_alloc_callback(__keyw_strncmp_case_sensitive, strcmp_proc);
		_uls_alloc_callback(__keyw_strncmp_case_insensitive, strcmp_proc);

		_uls_alloc_callback(__keyw_hashfunc_case_sensitive, hashfunc);
		_uls_alloc_callback(__keyw_hashfunc_case_insensitive, hashfunc);

		_uls_alloc_callback(dfl_lit_analyzer_escape0, litstr_analyzer);
		_uls_alloc_callback(dfl_lit_analyzer_escape1, litstr_analyzer);
		_uls_alloc_callback(dfl_lit_analyzer_escape2, litstr_analyzer);

		_uls_alloc_callback(nothing_lit_analyzer, litstr_analyzer);

		_uls_alloc_callback(uls_gettok_raw, gettok);
		_uls_alloc_callback(uls_gettok_bin, gettok);

		_uls_alloc_callback(__print_uld_lineproc_1, proc_uld_line);
		_uls_alloc_callback(__print_uld_lineproc_2, proc_uld_line);
		_uls_alloc_callback(__print_uld_lineproc_3cpp, proc_uld_line);
		_uls_alloc_callback(__print_uld_lineproc_3cs, proc_uld_line);

		_uls_alloc_callback(uls_input_refill_null, input_refill);
		_uls_alloc_callback(uls_input_refill_buffer, input_refill);
		_uls_alloc_callback(uls_input_refill_cr2lf, input_refill);

		_uls_alloc_callback(uls_fill_null_source, fill_isource);
		_uls_alloc_callback(uls_fill_fd_source_utf8, fill_isource);
		_uls_alloc_callback(uls_fill_fd_source_utf16, fill_isource);
		_uls_alloc_callback(uls_fill_fd_source_utf32, fill_isource);
		_uls_alloc_callback(uls_fill_fd_stream, fill_isource);

		_uls_alloc_callback(uls_ungrab_null_source, ungrab_isource);
		_uls_alloc_callback(uls_ungrab_linecheck, ungrab_isource);
		_uls_alloc_callback(uls_ungrab_fd_utf, ungrab_isource);
		_uls_alloc_callback(uls_ungrab_fd_stream, ungrab_isource);

		_uls_alloc_callback(uls_fd_ungrabber, input_ungrabber);

		_uls_alloc_callback(xcontext_raw_filler, xcontext_filler);
		_uls_alloc_callback(xcontext_binfd_filler, xcontext_filler);
		_uls_alloc_callback(xcontext_txtfd_filler, xcontext_filler);

		_uls_alloc_callback(check_rec_boundary_null, xctx_boundary_checker);
		_uls_alloc_callback(check_rec_boundary_host_order, xctx_boundary_checker);
		_uls_alloc_callback(check_rec_boundary_reverse_order, xctx_boundary_checker);

		_uls_alloc_callback(__check_rec_boundary_host_order, xctx_boundary_checker2);
		_uls_alloc_callback(__check_rec_boundary_reverse_order, xctx_boundary_checker2);

		_uls_alloc_callback(uls_make_pkt__null, make_packet);
		_uls_alloc_callback(uls_make_pkt__bin, make_packet);
		_uls_alloc_callback(uls_make_pkt__txt, make_packet);

		_uls_alloc_callback(uls_make_pkt__bin_lno, make_packet);
		_uls_alloc_callback(uls_make_pkt__txt_lno, make_packet);

		_uls_alloc_callback(uls_reorder_bytes_null, reorder_bytes);
		_uls_alloc_callback(uls_reorder_bytes_binle, reorder_bytes);
		_uls_alloc_callback(uls_reorder_bytes_binbe, reorder_bytes);

		_uls_alloc_ns_callback(keyw_stat_comp_by_keyw, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(cmp_twoplus_by_length, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(cmp_twoplus_vx_by_keyword, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(cnst_suffixes_by_len, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(comp_vx_by_tokid, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(comp_vx_by_toknam, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(comp_by_tokid_vx, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(commtype_by_length_dsc, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(quotetype_by_length_dsc, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(keyw_stat_comp_by_freq, UlsToolbase, sort_cmpfunc);
		_uls_alloc_ns_callback(numpfx_by_length_dsc, UlsToolbase, sort_cmpfunc);

		_uls_alloc_ns_callback(srch_vx_by_id, UlsToolbase, bi_comp);
		_uls_alloc_ns_callback(id_range_comp, UlsToolbase, bi_comp);
		_uls_alloc_ns_callback(srch_vx_by_toknam, UlsToolbase, bi_comp);

		_uls_alloc_ns_callback(read_config__CASE_SENSITIVE, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__CHAR_TOK, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__COMMENT_TYPE, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__DECIMAL_SEPARATOR, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__DOMAIN, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__ID_CHARS, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__ID_FIRST_CHARS, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__ID_MAX_LENGTH, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__LINEFEED_GUARD, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__NOT_CHAR_TOK, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__NUMBER_PREFIXES, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__NUMBER_SUFFIXES, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__QUOTE_TYPE, UlsToolbase, cmd_proc);
		_uls_alloc_ns_callback(read_config__RENAME, UlsToolbase, cmd_proc);


		if (__initialize_uls() < 0) {
			Console::WriteLine("Failed to initialize at UlsFactory::UlsFactory!");
		}

		isDisposed = isFinalized = false;
#ifdef _MANAGE_ULS_OBJECTS
		addUlsObject2List(objs_list);
#endif
	}

	void ULS_CLASS_NAME::finalizer()
	{
		if (isFinalized) return;
		__finalize_uls();
		isFinalized = true;
	}

	ULS_CLASS_NAME::~ULS_CLASS_NAME()
	{
		if (isDisposed) return;

		finalizer();
#ifdef _MANAGE_ULS_OBJECTS
		delUlsObject2List(objs_list);
#endif
		// delegate
		_uls_dealloc_callback(__keyw_strncmp_case_sensitive);
		_uls_dealloc_callback(__keyw_strncmp_case_insensitive);

		_uls_dealloc_callback(__keyw_hashfunc_case_sensitive);
		_uls_dealloc_callback(__keyw_hashfunc_case_insensitive);

		_uls_dealloc_callback(dfl_lit_analyzer_escape0);
		_uls_dealloc_callback(dfl_lit_analyzer_escape1);
		_uls_dealloc_callback(dfl_lit_analyzer_escape2);

		_uls_dealloc_callback(nothing_lit_analyzer);

		_uls_dealloc_callback(uls_gettok_raw);
		_uls_dealloc_callback(uls_gettok_bin);

		_uls_dealloc_callback(__print_uld_lineproc_1);
		_uls_dealloc_callback(__print_uld_lineproc_2);
		_uls_dealloc_callback(__print_uld_lineproc_3cpp);
		_uls_dealloc_callback(__print_uld_lineproc_3cs);

		_uls_dealloc_callback(uls_input_refill_null);
		_uls_dealloc_callback(uls_input_refill_buffer);
		_uls_dealloc_callback(uls_input_refill_cr2lf);

		_uls_dealloc_callback(uls_fill_null_source);
		_uls_dealloc_callback(uls_fill_fd_source_utf8);
		_uls_dealloc_callback(uls_fill_fd_source_utf16);
		_uls_dealloc_callback(uls_fill_fd_source_utf32);
		_uls_dealloc_callback(uls_fill_fd_stream);

		_uls_dealloc_callback(uls_ungrab_null_source);
		_uls_dealloc_callback(uls_ungrab_linecheck);
		_uls_dealloc_callback(uls_ungrab_fd_utf);
		_uls_dealloc_callback(uls_ungrab_fd_stream);

		_uls_dealloc_callback(uls_fd_ungrabber);

		_uls_dealloc_callback(xcontext_raw_filler);
		_uls_dealloc_callback(xcontext_binfd_filler);
		_uls_dealloc_callback(xcontext_txtfd_filler);

		_uls_dealloc_callback(check_rec_boundary_null);
		_uls_dealloc_callback(check_rec_boundary_host_order);
		_uls_dealloc_callback(check_rec_boundary_reverse_order);
		_uls_dealloc_callback(__check_rec_boundary_host_order);
		_uls_dealloc_callback(__check_rec_boundary_reverse_order);

		_uls_dealloc_callback(uls_make_pkt__null);
		_uls_dealloc_callback(uls_make_pkt__bin);
		_uls_dealloc_callback(uls_make_pkt__txt);

		_uls_dealloc_callback(uls_make_pkt__bin_lno);
		_uls_dealloc_callback(uls_make_pkt__txt_lno);

		_uls_dealloc_callback(uls_reorder_bytes_null);
		_uls_dealloc_callback(uls_reorder_bytes_binle);
		_uls_dealloc_callback(uls_reorder_bytes_binbe);

		_uls_dealloc_callback(keyw_stat_comp_by_keyw);
		_uls_dealloc_callback(cmp_twoplus_by_length);
		_uls_dealloc_callback(cmp_twoplus_vx_by_keyword);
		_uls_dealloc_callback(cnst_suffixes_by_len);
		_uls_dealloc_callback(comp_vx_by_tokid);
		_uls_dealloc_callback(comp_vx_by_toknam);
		_uls_dealloc_callback(comp_by_tokid_vx);
		_uls_dealloc_callback(commtype_by_length_dsc);
		_uls_dealloc_callback(quotetype_by_length_dsc);
		_uls_dealloc_callback(keyw_stat_comp_by_freq);
		_uls_dealloc_callback(numpfx_by_length_dsc);

		_uls_dealloc_callback(srch_vx_by_id);
		_uls_dealloc_callback(id_range_comp);
		_uls_dealloc_callback(srch_vx_by_toknam);

		_uls_dealloc_callback(read_config__CASE_SENSITIVE);
		_uls_dealloc_callback(read_config__CHAR_TOK);
		_uls_dealloc_callback(read_config__COMMENT_TYPE);
		_uls_dealloc_callback(read_config__DECIMAL_SEPARATOR);
		_uls_dealloc_callback(read_config__DOMAIN);
		_uls_dealloc_callback(read_config__ID_CHARS);
		_uls_dealloc_callback(read_config__ID_FIRST_CHARS);
		_uls_dealloc_callback(read_config__ID_MAX_LENGTH);
		_uls_dealloc_callback(read_config__LINEFEED_GUARD);
		_uls_dealloc_callback(read_config__NOT_CHAR_TOK);
		_uls_dealloc_callback(read_config__NUMBER_PREFIXES);
		_uls_dealloc_callback(read_config__NUMBER_SUFFIXES);
		_uls_dealloc_callback(read_config__QUOTE_TYPE);
		_uls_dealloc_callback(read_config__RENAME);

		_sysprops_ = nullptr;
		_log_ = nullptr;
		delete _tool_;
		isDisposed = true;
	}

	ULS_CLASS_NAME::!ULS_CLASS_NAME()
	{
		finalizer();
	}

#undef ULS_CLASS_NAME

	} //  End of polaris
} //  End of uls
