//
//  chnlib.h
//  AI003
//
//  Created by 西田　耀 on 13/01/28.
//  Copyright (c) 2013年 Hikaru Nishida. All rights reserved.
//

#ifndef AI003_chnlib_h
#define AI003_chnlib_h

//
//Set compile environment
//

#define CHNLIB_MAKE_GCC_MAC
//#define CHNLIB_MAKE_BCC_WIN

#ifdef CHNLIB_MAKE_BCC_WIN
#define DEBUG
#ifndef __FUNCTION__
#define __FUNCTION__	"Unknown"
#endif
#endif

#define CHNLIB_DEBUG_ARGUMENTS  __FILE__, __LINE__, __FUNCTION__

#ifdef DEBUG
//#define DEBUG_MEMORY_ALLOCATION
//#define DEBUG_MEMORY_REFERENCE_COUNT
//#define DEBUG_STRING_STRICT
#endif

//
//Define types
//

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;

typedef struct CHNLIB_STRUCTURE_HEADER CHNLIB_StructureHeader;
struct CHNLIB_STRUCTURE_HEADER {
    //ライブラリ共通構造体ヘッダ
    uint signature;
    uint typeid;
    uint referenceCount;
    void (*destructor)(void **structrue);
    uint (*getHash)(const void *structure);
};

//@chnlib00.c
typedef struct CHNLIB_UIPARRAY CHNLIB_UIPArray;
//@chnlib01.c
typedef struct CHNLIB_STRING CHNLIB_String;
//@chnlib05.c
typedef struct CHNLIB_RANDOM_GENERATOR_MT CHNLIB_RandomGeneratorMT;
//@chnlib06.c
typedef struct CHNLIB_UniversallyUniqueIDentifier CHNLIB_UUID;

//
//Define library values
//

#define CHNLIB_STRUCTURE_SIGNATURE  ((uint)0x4C4E4843)  //"CHNL"(Little Endian)

#define False   0
#define True    1

#define CHNLIB_STRUCT_ID_Null               0
#define CHNLIB_STRUCT_ID_UIPArray           1
#define CHNLIB_STRUCT_ID_String             2
#define CHNLIB_STRUCT_ID_RandomGeneratorMT  3
#define CHNLIB_STRUCT_ID_UUID               4

#define CHNLIB_MAX_STRING_LENGTH	4096

#define CHNLIB_UIPArray_INDEX_NOTFOUND  -1

#define retain(structure)   CHNLIB_Retain((void **) &structure)
#define release(structure)  CHNLIB_Release((void **) &structure)
#define autorelease(structure)  CHNLIB_AutoRelease(structure)

//
//Declare library functions
//
//@chnlib.c
void CHNLIB_Debug(const char format[], const char filename[], int line, const char funcname[], ...);
void CHNLIB_Debug_PrintStructureData(void *structure, uint level);
void CHNLIB_ReportError(const char format[], const char filename[], int line, const char funcname[], ...);  //("", CHNLIB_DEBUG_ARGUMENTS);
void CHNLIB_StructureHeader_Initialize(CHNLIB_StructureHeader *header, uint typeid);
uint CHNLIB_StructureHeader_GetTypeID(const void *structure);
uint CHNLIB_StructureHeader_GetHash(const void *structure);
void *CHNLIB_System_AllocateMemory_Strict(int size, const char filename[], int line, const char funcname[]);
void CHNLIB_System_FreeMemory(void *p, const char filename[], int line, const char funcname[]);
void CHNLIB_Retain(void **structure);
void CHNLIB_Release(void **structure);
void *CHNLIB_AutoRelease(void *structure);
//@chnlib00.c
//----配列の初期化
CHNLIB_UIPArray *CHNLIB_UIPArray_Initialize(void);
//----データの追加
int CHNLIB_UIPArray_AppendLast(CHNLIB_UIPArray **array, uint data32, void *pointer);
int CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(CHNLIB_UIPArray **array, uint data32, void *pointer, int (*IsDuplicated)(const void *listtag, const void *newtag));
//----データの削除
int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index);
//----配列の解放
void CHNLIB_UIPArray_FreeOnlyArray(CHNLIB_UIPArray **array);
void CHNLIB_UIPArray_FreeOnlyAllPointer(CHNLIB_UIPArray *array);
void CHNLIB_UIPArray_FreeOnlySelectedPointer(CHNLIB_UIPArray *array);
void CHNLIB_UIPArray_FreeAll(CHNLIB_UIPArray **array);
void CHNLIB_UIPArray_FreeSelectedAll(CHNLIB_UIPArray **array);
//----配列要素数取得
int CHNLIB_UIPArray_GetNumberOfDatas(const CHNLIB_UIPArray *array);
//----Data32取得・設定
uint CHNLIB_UIPArray_GetData32ByIndex(const CHNLIB_UIPArray *array, int index);
uint CHNLIB_UIPArray_SetData32ByIndex(CHNLIB_UIPArray *array, int index, uint data32);
//----Pointer取得・設定
void *CHNLIB_UIPArray_GetPointerByIndex(const CHNLIB_UIPArray *array, int index);
void *CHNLIB_UIPArray_GetPointerByData32(const CHNLIB_UIPArray *array, uint data32);
//----Index取得
int CHNLIB_UIPArray_GetIndexByData32(const CHNLIB_UIPArray *array, uint data32);
//----配列のコピー
CHNLIB_UIPArray *CHNLIB_UIPArray_CopyArray(const CHNLIB_UIPArray *source);
//----配列のソートしたものを新たに取得
CHNLIB_UIPArray *CHNLIB_UIPArray_GetSortedInDescendingOrderByData32(const CHNLIB_UIPArray *array);

//@chnlib01.c
//----文字列の初期化
CHNLIB_String *CHNLIB_String_Initialize(const char str[]);
CHNLIB_String *CHNLIB_String_InitializeWithFormat(const char format[], ...);
//----文字列の解放
void CHNLIB_String_Free(CHNLIB_String *strtag);
//----文字列の設定
int CHNLIB_String_SetStringFromCString(CHNLIB_String *strtag, const char s[]);
//----文字列の表示
int CHNLIB_String_Print(CHNLIB_String *strtag);
//----文字列の参照の取得
const char *CHNLIB_String_GetReferencePointerOfCString(const CHNLIB_String *strtag);
//----文字列の切り出し
CHNLIB_String *CHNLIB_String_ExtractByLength(const CHNLIB_String *strtag, int start, int len);
//----文字列の連結
CHNLIB_String *CHNLIB_String_Concatenate(const CHNLIB_String *s1, const CHNLIB_String *s2);
//----文字列の長さを取得
int CHNLIB_String_GetLength(const CHNLIB_String *strtag);
//----末尾の改行文字を削除
void CHNLIB_String_DeleteLastCRLF(CHNLIB_String *strtag);
//----文字列の比較
int CHNLIB_String_CompareStringWithCString(const CHNLIB_String *s, const char search[]);
int CHNLIB_String_CompareString_Strict(const CHNLIB_String *s, const CHNLIB_String *search);
//----文字列の出現回数を取得
uint CHNLIB_String_GetCountOfContain(const CHNLIB_String *s, const CHNLIB_String *search);
//----文字列のコピーを作成
CHNLIB_String *CHNLIB_String_Copy(const CHNLIB_String *s);
//----低レベルCString関数
int CHNLIB_CString_GetByteLength(const char s[]);
void CHNLIB_CString_DeleteLastCRLF(char s[]);
char *CHNLIB_CString_ExtractByLength(const char s[], int start, int len);
int CHNLIB_CString_CompareString(const char s[], const char search[]);
int CHNLIB_CString_CompareString_Strict(const char s[], const char search[]);
int CHNLIB_CString_CompareString_LeftHand(const char s[], const char search[]);
char *CHNLIB_CString_Copy(const char s[]);
char *CHNLIB_CString_Concatenate(const char s1[], const char s2[]);
//@chnlib02.c
int CHNLIB_String_Search_UIPArrayStringLocation(const CHNLIB_String *s, int s_start, const CHNLIB_UIPArray *list, int *location);
int CHNLIB_UIPArray_GetSeparatedStringByUIPArray(CHNLIB_UIPArray **separated, const CHNLIB_UIPArray *list, const CHNLIB_String *s);
int CHNLIB_UIPArray_GetSeparatedUTF8Character(CHNLIB_UIPArray **separated, const CHNLIB_String *s);
CHNLIB_String *CHNLIB_ReadLine(FILE *fp);
CHNLIB_UUID *CHNLIB_GenerateUUIDVersion4WithRandomGeneratorMT(CHNLIB_RandomGeneratorMT *mt);

//@chnlib03.c
void CHNLIB_Environment_SetCurrentWorkingDirectory(const char apppath[]);
const char *CHNLIB_Environment_GetFilenameFromPath(const char path[]);

//@chnlib04.c
int CHNLIB_UTF8_GetCharacterType(char c);
int CHNLIB_UTF8_GetStringLengthByCharacter(const char s[]);
uint CHNLIB_UTF8_GetNextUnicodeOfCharacter(const char s[], const char **next);
int CHNLIB_UTF8_CompareString(const char s[], const char search[]);
int CHNLIB_UTF8_CompareString_LeftHand(const char s[], const char search[]);
int CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(const char s[], int start, int end);
uint CHNLIB_UTF8_GetCountOfContain(const char s[], const char search[]);

//@chnlib05.c
CHNLIB_RandomGeneratorMT *CHNLIB_RandomGeneratorMT_Initialise(void);
void CHNLIB_RandomGeneratorMT_Free(CHNLIB_RandomGeneratorMT *env);
void CHNLIB_RandomGeneratorMT_SetSeed(CHNLIB_RandomGeneratorMT *env, unsigned long s);
void CHNLIB_RandomGeneratorMT_SetSeedFromArray(CHNLIB_RandomGeneratorMT *env, unsigned long init_key[], int key_length);
uint CHNLIB_RandomGeneratorMT_GetRandomUnsignedInteger32(CHNLIB_RandomGeneratorMT *env);

//@chnlib06.c
CHNLIB_UUID *CHNLIB_UUID_Initialise(void);
void CHNLIB_UUID_Free(CHNLIB_UUID *uuid);
void CHNLIB_UUID_Print(const CHNLIB_UUID *uuid);
int CHNLIB_UUID_IsEqualToUUID(const CHNLIB_UUID *uuid1, const CHNLIB_UUID *uuid2);
void CHNLIB_UUID_SetValueAsUUIDVersion4CompatibleWithRFC4122(CHNLIB_UUID *uuid, uint random1, uint random2, uint random3, uint random4);
void CHNLIB_UUID_SetNullUUID(CHNLIB_UUID *uuid);
CHNLIB_UUID *CHNLIB_UUID_Copy(const CHNLIB_UUID *uuidBase);
#endif
