/*
 *  ADP (Another Data Processor) www.adp.la
 *  Copyright (C) 2010 Katsuhisa Ohfuji <katsuhisa@ohfuji.name>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA 02110-1301, USA.
 */
 
#ifndef ADP_GLOBAL_H
#define ADP_GLOBAL_H

#ifdef ADP_COMMON_CPP
#define EXTERN 
#else
#define EXTERN	extern
#endif

// タイプ定義
// ODBC接続保存マップ
typedef map<string,kz_odbc*>	kz_odbc_map;
typedef pair<string,kz_odbc*>	kz_odbc_pair;
typedef vector<kz_odbc*>		kz_odbc_vector;
typedef map<string,char>		kz_odbc_quote;
typedef pair<string,char>		kz_odbc_quote_pair;

// グローバル関数
bool add_allowtags(const string &tag, const char *el1, int tp1, const char *el2, int tp2,  const char *el3, int tp3, const char *el4, int tp4, const char *el5, int tp5, const char *el6, int tp6, const char *el7, int tp7 );
void remove_allowtags(const string &tag);
void htmlescape( string &txt, bool awpescape);
void formatNumber(PINTEGER num, string &fmtnum);
void ej2sj( const unsigned char ej[2], unsigned char sj[3]);
void unicode_to_utf8(wchar_t unicode, string &dst);
bool utf8to(const string &src, string &dst);
void list2ssmap( const PList *ovalues, ssmap &values);
PList *ssmap2list( ssmap &values, ExecContextRoot *ec);
PList *stringstring2list( string_array &keys, string_array &values, ExecContextRoot *ec);
void convertstringvector( char **src, vector<string>&dest);
kz_odbc	*db_connect(const char *constr, char *quote_c_s, char *quote_c_e);
void db_disconnect();
bool make_temppath(const string &head, string &temppath);
bool createHash( const string &str, string &hash);
void mysrand();
void mysrand(int seed);
int myrand();
bool make_rkey(string &base, string &rkey);
bool createSessionID( string &sessionid, string &temppath, ssmap &env);
PArray *getSession( const string &sessionid, string &sessionpath);
bool setSessionItem(const PObject *item, const string &key, ssmap &env, PArray* &session, string &sessionid, string &sessionpath);
bool eraseSessionItem(const string &key, PArray* &session);
bool setGlobalItem(const PObject *item, const string &key, PArray* &global);
bool eraseGlobalItem(const string &key, PArray* &global);
void mySleep(long long nanosec);
void init_awpescapetags(void);
bool isawp( const char *fname);

// グローバル変数
EXTERN ssmap			envmap;
EXTERN ssmap			query;
EXTERN ssmap			cookies;
EXTERN PArray			*global;	// グローバル変数格納用
EXTERN PArray			*session;	// セッション変数格納用
EXTERN string			sessionid;
EXTERN string			sessionpath;
EXTERN string			session_cookie_domain;
EXTERN string			session_cookie_path;
EXTERN string			session_cookie_expires;
EXTERN string			session_cookie_secure;
EXTERN bool				sessionwriteflg;
EXTERN bool				session_cookie_out;
EXTERN string			header_string;
EXTERN bool				first_print;
EXTERN string			first_src_base_path; /* 最初のソースファイルのベースパス（ディレクトリ）*/
EXTERN kz_odbc_map		dbmap;		/* DBへの接続を持つ（グローバルなdbmapから接続を取得することによりホーン節で一環して同一の接続を用いることができる */
EXTERN kz_odbc_quote	quote_s;	/* クオート文字（開始) */
EXTERN kz_odbc_quote	quote_e;	/* クオート文字（終了) */
EXTERN kz_odbc_vector	dbvector;	/* DBリソース管理ベクター */
EXTERN char				default_quote_s;	/* クオート開始文字 */
EXTERN char				default_quote_e;	/* クオート終了文字 */
//EXTERN PObjectFactory	poFactory;	/* PObjectファクトリ（実行ファイルレベルの寿命を持つオブジェクトの管理） */
EXTERN PMemoryManager	pmm;		/* メモリマネージャ（上記以外の寿命を持つオブジェクトの管理） */
EXTERN vector<string>	argvector;	/* コマンドライン引数 */
//EXTERN __thread GlobalContext	*gc;/* GlboaContext */
#ifdef _WIN32
EXTERN __declspec( thread )	void *tls_ptr;
#else
EXTERN pthread_key_t	tsd_key;
#endif

EXTERN pcmap			pccache;	/* 述語評価キャッシュ */

EXTERN bool				compiletrace;	// 逆コンパイル結果を出力
EXTERN bool				dispwarn;		// ワーニング出力 
EXTERN bool				syntaxcheck;	// 構文チェックのみ 
EXTERN int				thread_count;	// スレッドカウント


// Object Header
#define BINARY_OBJECT_HEADER_1	"+ADP0070BIN_"
#define SIZE_BINARY_OBJECT_HEADER 12
#define ADP_SESSION_ID_STRING "ADP_SESSION_ID_STRING"

bool toBinary( const PObject *obj, string &cvobj, string &header);
template <class T> PObject *fromBinary( T sin, T end, PObjectArray *pobjs)
{
	string	header;
	string  body;
	string  object;
	int cnt = 0;
	
	// read header 
	while ( sin != end && cnt < 32 ) {
		header.push_back(*sin);
		++sin;
		++cnt;
	}
	// check!
	if ( memcmp( header.c_str(), BINARY_OBJECT_HEADER_1, SIZE_BINARY_OBJECT_HEADER) != 0 ) return 0;
	// 長さの取得
	int length = atoi(header.substr( 12, 10).c_str());
	if ( length < 0 ) return 0;
	
	// read body
	cnt = 0;
	while ( sin != end && cnt < 16 ) {
		body.push_back(*sin);
		++sin;
		++cnt;
	}
	int code = BinaryObjectFormat::get_int(body, 0);
	long long objlen = BinaryObjectFormat::get_long_long(body, 4);

	// read object
	cnt = 0;
	while ( sin != end && cnt < objlen ) {
		object.push_back(*sin);
		++sin;
		++cnt;
	}
	if ( cnt < objlen ) return 0;
	PObject *po = get_gc()->factory.createPObjectBload( code, pobjs);
	if ( !po || !po->Bread(object, pobjs) ) return 0;
	
	return po;
}

#endif
