5 // Created by 西田 耀 on 13/01/28.
\r
6 // Copyright (c) 2013年 Hikaru Nishida. All rights reserved.
\r
23 //Define static values
\r
25 int CHNLIB_Debug_PrintStructureData_RecursiveCounter;
\r
28 //Declare internal functions
\r
30 const char *CHNLIB_Debug_Internal_GetStructTypeNameByID(uint typeid);
\r
31 void CHNLIB_Debug_Internal_PrintStructureDataSub(void *structure, uint level);
\r
32 void CHNLIB_Debug_Internal_PrintIndent(int level);
\r
42 void CHNLIB_Debug(const char format[], const char filename[], int line, const char funcname[], ...)
\r
45 char s[CHNLIB_MAX_STRING_LENGTH];
\r
48 fprintf(stdout, "CHNLIB:Debug:%s@%s:%d:", funcname, filename, line);
\r
50 va_start(varg, funcname);
\r
51 vsnprintf(s, sizeof(s), format, varg);
\r
55 fputs("\n", stdout);
\r
62 void CHNLIB_Debug_PrintStructureData(void *structure, uint level)
\r
64 //ライブラリ定義の構造体の中身を表示する。
\r
65 //structureがUIPArrayを指していた場合、その中身も表示する。表示する階層はlevelで制限できる。
\r
67 //-level >= 1:level階層まで
\r
69 CHNLIB_Debug_PrintStructureData_RecursiveCounter = level - 1;
\r
71 CHNLIB_Debug_Internal_PrintStructureDataSub(structure, 0);
\r
76 void CHNLIB_ReportError(const char format[], const char filename[], int line, const char funcname[], ...)
\r
78 //stderrにprintfの書式に従って出力する。
\r
79 char s[CHNLIB_MAX_STRING_LENGTH];
\r
82 fprintf(stderr, "CHNLIB:Error:%s@%s:%d:", funcname, filename, line);
\r
84 va_start(varg, funcname);
\r
85 vsnprintf(s, sizeof(s), format, varg);
\r
89 fputs("\n", stderr);
\r
94 void CHNLIB_StructureHeader_Initialize(CHNLIB_StructureHeader *header, uint typeid)
\r
96 //ライブラリ共通構造体ヘッダの初期化を行う。
\r
97 //各構造体のInitializeで呼ばれることを想定している。
\r
98 //referenceCountは1で初期化される(初期化を行った関数が所有すると考える)
\r
100 CHNLIB_ReportError("Null structure.", CHNLIB_DEBUG_ARGUMENTS);
\r
104 header->signature = CHNLIB_STRUCTURE_SIGNATURE;
\r
105 header->typeid = typeid;
\r
106 #ifdef DEBUG_MEMORY_REFERENCE_COUNT
\r
107 CHNLIB_Debug("Init with referenceCount = 1 [%p].", CHNLIB_DEBUG_ARGUMENTS, header);
\r
109 header->referenceCount = 1;
\r
110 header->destructor = NULL;
\r
114 uint CHNLIB_StructureHeader_GetTypeID(const void *structure)
\r
116 //structureが指す構造体のヘッダを確認して、その構造体のtypeidを返す。
\r
117 //ポインタの正当性の実証に利用するとよい。
\r
118 CHNLIB_StructureHeader *strhead;
\r
120 if(structure == NULL){
\r
121 return CHNLIB_STRUCT_ID_Null;
\r
124 strhead = (CHNLIB_StructureHeader *)structure;
\r
125 if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){
\r
126 return strhead->typeid;
\r
128 return CHNLIB_STRUCT_ID_Null;
\r
131 void *CHNLIB_System_AllocateMemory_Strict(int size, const char filename[], int line, const char funcname[])
\r
133 //mallocを行い、確保が失敗した場合にメッセージを出力してプログラムを終了する。
\r
134 //また、この関数で取得されたメモリはゼロクリアされていることが保証される。
\r
139 CHNLIB_ReportError("An attempt to allocate memory %d bytes in %s@%s:%d: is failed. Abort.", CHNLIB_DEBUG_ARGUMENTS, size, filename, line, funcname);
\r
140 exit(EXIT_FAILURE);
\r
143 #ifdef DEBUG_MEMORY_ALLOCATION
\r
144 CHNLIB_Debug("Request allocation %d bytes ->[%p].", CHNLIB_DEBUG_ARGUMENTS, size, p);
\r
147 memset(p, 0, size);
\r
152 void CHNLIB_System_FreeMemory(void *p, const char filename[], int line, const char funcname[])
\r
154 //ポインタがNullでないことを確認して、Freeする。
\r
156 CHNLIB_ReportError("An attempt to free NULL memory in %s@%s:%d:. Ignore.", CHNLIB_DEBUG_ARGUMENTS, filename, line, funcname);
\r
160 #ifdef DEBUG_MEMORY_ALLOCATION
\r
161 CHNLIB_Debug("Request ƒree memory [%p].", CHNLIB_DEBUG_ARGUMENTS, p);
\r
169 void CHNLIB_Retain(void **structure)
\r
171 //structureのreferenceCountをインクリメントする。
\r
172 //referenceCountの初期値は1
\r
174 CHNLIB_StructureHeader *strhead;
\r
176 if(structure == NULL || *structure == NULL){
\r
180 strhead = (CHNLIB_StructureHeader *)*structure;
\r
181 if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){
\r
182 #ifdef DEBUG_MEMORY_REFERENCE_COUNT
\r
183 CHNLIB_Debug("Retain [%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);
\r
185 strhead->referenceCount++;
\r
191 void CHNLIB_Release(void **structure)
\r
193 //structureのreferenceCountをデクリメントする。
\r
194 //デクリメントした結果referenceCount==0となった時、そのstructureを解放する。
\r
195 //structureが内包しているオブジェクトについては、releaseを行う。
\r
197 CHNLIB_StructureHeader *strhead;
\r
199 if(structure == NULL || *structure == NULL){
\r
203 strhead = (CHNLIB_StructureHeader *)*structure;
\r
204 if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){
\r
205 if(strhead->referenceCount <= 1){
\r
206 if(strhead->destructor == NULL){
\r
207 #ifdef DEBUG_MEMORY_REFERENCE_COUNT
\r
208 CHNLIB_Debug("Release(with free)[%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);
\r
212 strhead->destructor(structure);
\r
215 #ifdef DEBUG_MEMORY_REFERENCE_COUNT
\r
216 CHNLIB_Debug("Release[%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);
\r
218 strhead->referenceCount--;
\r
226 void *CHNLIB_AutoRelease(void *structure)
\r
228 //structureのreferenceCountを、destructせずに0にする。
\r
229 //オブジェクト確保後に自分の所有権を放棄して他の関数へ渡すときに利用する。
\r
231 CHNLIB_StructureHeader *strhead;
\r
233 if(structure != NULL){
\r
234 strhead = (CHNLIB_StructureHeader *)structure;
\r
235 if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){
\r
236 #ifdef DEBUG_MEMORY_REFERENCE_COUNT
\r
237 CHNLIB_Debug("Set AutoRelease [%p].", CHNLIB_DEBUG_ARGUMENTS, structure);
\r
239 strhead->referenceCount = 0;
\r
247 //Internal functions
\r
250 const char *CHNLIB_Debug_Internal_GetStructTypeNameByID(uint typeid)
\r
252 //デバッグ出力で利用するための構造体名を取得する。
\r
253 //このソース以外から呼び出してはならない。
\r
255 case CHNLIB_STRUCT_ID_Null:
\r
257 case CHNLIB_STRUCT_ID_UIPArray:
\r
259 case CHNLIB_STRUCT_ID_String:
\r
265 void CHNLIB_Debug_Internal_PrintStructureDataSub(void *structure, uint level)
\r
268 //このソース以外から呼び出してはならない。
\r
272 typeid = CHNLIB_StructureHeader_GetTypeID(structure);
\r
275 case CHNLIB_STRUCT_ID_UIPArray:
\r
276 i = CHNLIB_UIPArray_GetNumberOfDatas(structure);
\r
277 CHNLIB_Debug_Internal_PrintIndent(level);
\r
278 CHNLIB_Debug("%s[%p]:Number of datas=%d", "", 0, "", CHNLIB_Debug_Internal_GetStructTypeNameByID(typeid), structure, i);
\r
279 for(j = 0; j < i; j++){
\r
280 p = CHNLIB_UIPArray_GetPointerByIndex(structure, j);
\r
281 CHNLIB_Debug_Internal_PrintIndent(level);
\r
282 CHNLIB_Debug("%s[%p]:[%d]=(%u,[%p])", "", 0, "", CHNLIB_Debug_Internal_GetStructTypeNameByID(typeid), structure, j, CHNLIB_UIPArray_GetData32ByIndex(structure, j), p);
\r
283 if(CHNLIB_Debug_PrintStructureData_RecursiveCounter != 0){
\r
284 CHNLIB_Debug_Internal_PrintStructureDataSub(p, level + 1);
\r
288 case CHNLIB_STRUCT_ID_String:
\r
289 CHNLIB_Debug_Internal_PrintIndent(level);
\r
290 CHNLIB_Debug("%s[%p]:[%s]", "", 0, "", CHNLIB_Debug_Internal_GetStructTypeNameByID(typeid), structure, CHNLIB_String_GetReferencePointerOfCString(structure));
\r
293 CHNLIB_Debug_Internal_PrintIndent(level);
\r
294 CHNLIB_Debug("%s[%p]:NULL structure or not implemented.", "", 0, "", CHNLIB_Debug_Internal_GetStructTypeNameByID(typeid), structure);
\r
300 void CHNLIB_Debug_Internal_PrintIndent(int level)
\r
303 //このソース以外から呼び出してはならない。
\r
306 for(i = 0; i < level; i++){
\r
307 fputs(" ", stdout);
\r