OSDN Git Service

referenceCountを導入。今のところ正常に動作している。メモリリークについても一部改善。69.67KB(1852/2023)>36.59KB(588/2163)
[chnosproject/CHNOSProject.git] / CHNOSProject / chn / chnlib01.c
1 //\r
2 //  chnlib01.c\r
3 //  AI003\r
4 //\r
5 //  Created by 西田 耀 on 13/02/03.\r
6 //  Copyright (c) 2013年 Hikaru Nishida. All rights reserved.\r
7 //\r
8 \r
9 //String関連のうち、このソースファイルで完結する関数群\r
10 \r
11 //\r
12 //Include headers\r
13 //\r
14 \r
15 #include <stdio.h>\r
16 #include <stdlib.h>\r
17 #include <string.h>\r
18 #include "chnlib.h"\r
19 \r
20 //\r
21 //Define values\r
22 //\r
23 \r
24 //\r
25 //Define static values\r
26 //\r
27 char *CHNLIB_String_Intenal_NullCString = "";\r
28 \r
29 //\r
30 //Declare internal functions\r
31 //\r
32 \r
33 CHNLIB_String *CHNLIB_String_Internal_Allocate(void);\r
34 void CHNLIB_String_Internal_Destruct(void **structure);\r
35 \r
36 //\r
37 //Define types\r
38 //\r
39 \r
40 struct CHNLIB_STRING {\r
41     //文字列を保持する\r
42     CHNLIB_StructureHeader header;\r
43     char *str;\r
44 };\r
45 \r
46 //\r
47 //Functions(CHNLIB_String)\r
48 //\r
49 \r
50 CHNLIB_String *CHNLIB_String_Initialize(const char str[])\r
51 {\r
52     //指定された引数strと等価なStringを確保し返す。\r
53     //str==NULLの時は、NULLポインタへの参照を持つStringを返す。\r
54     CHNLIB_String *strtag;\r
55     \r
56     strtag = CHNLIB_String_Internal_Allocate();\r
57     strtag->header.destructor = &CHNLIB_String_Internal_Destruct;\r
58     \r
59     if(str != NULL){\r
60         CHNLIB_String_SetStringFromCString(strtag, str);\r
61     }\r
62     return strtag;\r
63 }\r
64 \r
65 void CHNLIB_String_Free(CHNLIB_String *strtag)\r
66 {\r
67     //strtagを解放する。\r
68     if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
69         return;\r
70     }\r
71     \r
72     if(strtag->str != NULL){\r
73         CHNLIB_System_FreeMemory(strtag->str, CHNLIB_DEBUG_ARGUMENTS);\r
74     }\r
75     strtag->header.typeid = CHNLIB_STRUCT_ID_Null;\r
76     strtag->header.signature = 0;\r
77     CHNLIB_System_FreeMemory(strtag, CHNLIB_DEBUG_ARGUMENTS);\r
78     \r
79     return;\r
80 }\r
81 \r
82 int CHNLIB_String_SetStringFromCString(CHNLIB_String *strtag, const char s[])\r
83 {\r
84     //strtagにsと等価な文字列を代入する。\r
85     //strtag==Invalid || s==NULLのときは何もしない。\r
86     int i, size;\r
87     \r
88     if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
89         return 0;\r
90     }\r
91     \r
92     if(s == NULL){\r
93         return 0;\r
94     }\r
95     \r
96     size = CHNLIB_CString_GetByteLength(s) + 1;\r
97     if(strtag->str != NULL){\r
98         CHNLIB_System_FreeMemory(strtag->str, CHNLIB_DEBUG_ARGUMENTS);\r
99     }\r
100     strtag->str = CHNLIB_System_AllocateMemory_Strict(size, CHNLIB_DEBUG_ARGUMENTS);\r
101     for(i = 0; i < size - 1; i++){\r
102         strtag->str[i] = s[i];\r
103     }\r
104     strtag->str[i] = '\0';\r
105     return size;\r
106 }\r
107 \r
108 int CHNLIB_String_Print(CHNLIB_String *strtag)\r
109 {\r
110     //strtagが格納している文字列を標準出力に出力する。\r
111     if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
112         return 0;\r
113     }\r
114     if(strtag->str == NULL){\r
115         return 0;\r
116     }\r
117     \r
118     return fputs(strtag->str, stdout);\r
119 }\r
120 \r
121 const char *CHNLIB_String_GetReferencePointerOfCString(const CHNLIB_String *strtag)\r
122 {\r
123     //strtagが格納している文字列へのポインタを返す。\r
124     //strtag->str==NULLの場合、constな空文字へのポインタを返す。\r
125     if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
126         return NULL;\r
127     }\r
128     \r
129     if(strtag->str == NULL){\r
130         return CHNLIB_String_Intenal_NullCString;\r
131     }\r
132     \r
133     return (const char *)strtag->str;\r
134 }\r
135 \r
136 CHNLIB_String *CHNLIB_String_ExtractByLength(const CHNLIB_String *strtag, int start, int len)\r
137 {\r
138     //strtagが格納している文字列sについて、\r
139     //s[start]からs[start + len - 1]の文字を含む文字列と等価なStringを確保し返す。\r
140     //lenに満たずにsが終端文字を迎えた場合は、sの終端文字直前までの文字列がコピーされる。\r
141     //(len < 0)のときは、NULLを返す。また、結果として(len < 0)となった時も同様にNULLを返す。\r
142     char *retstr;\r
143     CHNLIB_String *retstrtag;\r
144     \r
145     retstr = CHNLIB_CString_ExtractByLength(strtag->str, start, len);\r
146     \r
147     if(retstr == NULL){\r
148         return NULL;\r
149     }\r
150     \r
151     retstrtag = CHNLIB_String_Initialize(NULL);\r
152     retstrtag->str = retstr;\r
153     \r
154     return retstrtag;\r
155 }\r
156 \r
157 int CHNLIB_String_GetLength(const CHNLIB_String *strtag)\r
158 {\r
159     if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
160         return 0;\r
161     }\r
162     \r
163     return CHNLIB_CString_GetByteLength(strtag->str);\r
164 }\r
165 \r
166 void CHNLIB_String_DeleteLastCRLF(CHNLIB_String *strtag)\r
167 {\r
168     if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
169         return;\r
170     }\r
171     \r
172     CHNLIB_CString_DeleteLastCRLF(strtag->str);\r
173     \r
174     return;\r
175 }\r
176 \r
177 int CHNLIB_String_CompareStringWithCString(const CHNLIB_String *s, const char search[])\r
178 {\r
179     return CHNLIB_CString_CompareString(CHNLIB_String_GetReferencePointerOfCString(s), search);\r
180 }\r
181 \r
182 int CHNLIB_String_CompareString_Strict(const CHNLIB_String *s, const CHNLIB_String *search)\r
183 {\r
184     return CHNLIB_CString_CompareString_Strict(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(search));\r
185 }\r
186 \r
187 uint CHNLIB_String_GetCountOfContain(const CHNLIB_String *s, const CHNLIB_String *search)\r
188 {\r
189     return CHNLIB_UTF8_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(search));\r
190 }\r
191 \r
192 //\r
193 //Functions(CString(char[]))\r
194 //\r
195 \r
196 int CHNLIB_CString_GetByteLength(const char s[])\r
197 {\r
198     //[CString]\r
199     //終端文字を除いた、文字列本体のバイト数を返す。\r
200     int i;\r
201     \r
202     if(s == NULL){\r
203         return 0;\r
204     }\r
205     \r
206     for(i = 0; s[i] != 0x00; i++){\r
207         \r
208     }\r
209     \r
210     return i;\r
211 }\r
212 \r
213 void CHNLIB_CString_DeleteLastCRLF(char s[])\r
214 {\r
215     //末尾のLF, CR/LFを\0に置換する\r
216     int i, crlf;\r
217     \r
218     if(s == NULL){\r
219         return;\r
220     }\r
221     \r
222     crlf = -1;\r
223     for(i = 0; s[i] != '\0'; i++){\r
224         if(s[i] == '\n'){\r
225             if(crlf == -1 || crlf + 1 != i){\r
226                 crlf = i;\r
227             }\r
228         }\r
229         if(s[i] == '\r'){\r
230             if(crlf == -1 || crlf + 1 != i){\r
231                 crlf = i;\r
232             }\r
233         }\r
234     }\r
235     if(crlf != -1){\r
236         for(i = crlf; s[i] != '\0'; i++){\r
237             s[i] = '\0';\r
238         }\r
239     }\r
240     return;\r
241 }\r
242 \r
243 char *CHNLIB_CString_ExtractByLength(const char s[], int start, int len)\r
244 {\r
245     //s[start]からs[start + len - 1]の文字を含む文字列を、新たにメモリを確保して書き込み、その先頭アドレスを返す。\r
246     //lenに満たずにsが終端文字を迎えた場合は、sの終端文字直前までの文字列がコピーされる。\r
247     //(len < 0)のときは、NULLを返す。また、結果として(len < 0)となった時も同様にNULLを返す。\r
248     char *str;\r
249     int i;\r
250     int utf8type;\r
251     \r
252     if(s == NULL){\r
253         CHNLIB_ReportError("Null s[]\n", CHNLIB_DEBUG_ARGUMENTS);\r
254         return NULL;\r
255     }\r
256     \r
257     i = CHNLIB_CString_GetByteLength(s) + 1;\r
258     \r
259     if(i > (len + 1)){\r
260         i = len + 1;\r
261     }\r
262     \r
263     if(len == 0){\r
264         return NULL;\r
265     }\r
266     \r
267     str = CHNLIB_System_AllocateMemory_Strict(i, CHNLIB_DEBUG_ARGUMENTS);\r
268 \r
269     for(i = 0; s[i + start] != '\0'; i++){\r
270         if(len <= 0){\r
271             break;\r
272         }\r
273         //**UTF-8\r
274         utf8type = CHNLIB_UTF8_GetCharacterType(s[i + start]);\r
275         if(len < utf8type){\r
276             break;\r
277         }\r
278         //****\r
279         len--;\r
280         str[i] = s[i + start];\r
281     }\r
282     str[i] = '\0';\r
283     \r
284     return str;\r
285 }\r
286 \r
287 int CHNLIB_CString_CompareString(const char s[], const char search[])\r
288 {\r
289     //s[]の先頭からsearch[]と比較し、searchの終端まで一致したらTrue, 一致しなかったらFalseを返す。\r
290     //終端文字'\0'はカウントしない。\r
291     //search[]に含まれる文字(終端文字除く)がすべて入っていれば一致とみなす。\r
292     int i;\r
293     \r
294     if(s == NULL || search == NULL){\r
295         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
296         return False;\r
297     }\r
298     \r
299     for(i = 0; search[i] != '\0'; i++){\r
300         if(s[i] != search[i]){\r
301             return False;\r
302         }\r
303     }\r
304     return True;\r
305 }\r
306 \r
307 int CHNLIB_CString_CompareString_Strict(const char s[], const char search[])\r
308 {\r
309     //二つの文字列が終端文字までを含めて完全に一致するかどうか調べる。一致していればTrueを返す。\r
310     //StrictよりExactの方が適する?<関数名\r
311     int i;\r
312     \r
313     if(s == NULL || search == NULL){\r
314         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
315         return False;\r
316     }\r
317     \r
318     for(i = 0; search[i] != '\0'; i++){\r
319         if(s[i] != search[i]){\r
320             return False;\r
321         }\r
322     }\r
323     if(s[i] != '\0'){\r
324         return False;\r
325     }\r
326     return True;\r
327 }\r
328 \r
329 int CHNLIB_CString_CompareString_LeftHand(const char s[], const char search[])\r
330 {\r
331     //二つの文字列がどの程度一致するか調べる。前方一致。\r
332     //戻り値は、終端文字を除く、同一だったバイト数。\r
333     int i;\r
334     \r
335     if(s == NULL || search == NULL){\r
336         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
337         return 0;\r
338     }\r
339     \r
340     for(i = 0; search[i] != '\0'; i++){\r
341         if(s[i] != search[i]){\r
342             break;\r
343         }\r
344     }\r
345 \r
346     return i;\r
347 }\r
348     \r
349 //\r
350 //Internal functions\r
351 //\r
352 \r
353 CHNLIB_String *CHNLIB_String_Internal_Allocate(void)\r
354 {\r
355     CHNLIB_String *tag;\r
356     \r
357     tag = (CHNLIB_String *)CHNLIB_System_AllocateMemory_Strict(sizeof(CHNLIB_String), CHNLIB_DEBUG_ARGUMENTS);\r
358     \r
359     CHNLIB_StructureHeader_Initialize(&tag->header, CHNLIB_STRUCT_ID_String);\r
360     \r
361     return tag;\r
362 }\r
363 \r
364 void CHNLIB_String_Internal_Destruct(void **structure)\r
365 {\r
366     //デストラクタ(実際にRelease->freeされる時に呼ばれる)\r
367     if(structure == NULL){\r
368         return;\r
369     }\r
370     \r
371 #ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
372     CHNLIB_Debug("Release(with free)[%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);\r
373 #endif\r
374     \r
375     CHNLIB_String_Free(*structure);\r
376     \r
377     *structure = NULL;\r
378     \r
379     return;\r
380 }\r