OSDN Git Service

referenceCountを導入。今のところ正常に動作している。メモリリークについても一部改善。69.67KB(1852/2023)>36.59KB(588/2163)
[chnosproject/CHNOSProject.git] / CHNOSProject / chn / chnlib04.c
1 //\r
2 //  chnlib04.c\r
3 //  AI003\r
4 //\r
5 //  Created by 西田 耀 on 13/02/10.\r
6 //  Copyright (c) 2013年 Hikaru Nishida. All rights reserved.\r
7 //\r
8 \r
9 //UTF-8関連のうち、このソースファイルで完結する関数群\r
10 \r
11 //\r
12 //Include headers\r
13 //\r
14 \r
15 #include <stdio.h>\r
16 #include "chnlib.h"\r
17 \r
18 //\r
19 //Functions(UTF-8)\r
20 //\r
21 \r
22 int CHNLIB_UTF8_GetCharacterType(char c)\r
23 {\r
24     //[UTF-8]\r
25     //UTF-8文字列中の1バイトcが、UTF-8文字列中でどのような役割を持つのかを返す。\r
26     //0:マルチバイト文字の後続バイト\r
27     //1:1バイト文字\r
28     //2以上の数値n:nバイト文字の最初のバイト。後続のn個のマルチバイト後続バイトと組み合わせて一つの文字を示す。\r
29     //判断不能な場合は-1を返す。\r
30     if(((c >> 6) & 3) == 2){\r
31         //マルチバイト後続バイト\r
32         //10xxxxxx\r
33         return 0;\r
34     } else if(((c >> 7) & 1) == 0){\r
35         //1Byte\r
36         //7bit\r
37         //0xxxxxxx\r
38         return 1;\r
39     } else if(((c >> 5) & 7) == 6){\r
40         //2Byte\r
41         //11bit\r
42         //110xxxxx\r
43         return 2;\r
44     } else if(((c >> 4) & 15) == 14){\r
45         //3Byte\r
46         //16bit\r
47         //1110xxxx\r
48         return 3;\r
49     } else if(((c >> 3) & 31) == 30){\r
50         //4Byte\r
51         //21bit\r
52         //11110xxx\r
53         return 4;\r
54     }\r
55     \r
56     return -1;\r
57 }\r
58 \r
59 int CHNLIB_UTF8_GetStringLengthByCharacter(const char s[])\r
60 {\r
61     //[UTF-8]\r
62     //sをUTF-8文字列として解釈し、文字としては何文字で構成された文字列かを返す。\r
63     //無効な(マルチバイトの一部が欠けているような)文字はカウントしない。\r
64     int i, mbsize, n;\r
65     int count;\r
66     \r
67     if(s == NULL){\r
68         return 0;\r
69     }\r
70     \r
71     count = 0;\r
72     mbsize = 0;\r
73     for(i = 0; s[i] != '\0'; i++){\r
74         n = CHNLIB_UTF8_GetCharacterType(s[i]);\r
75         switch(n){\r
76             case -1:\r
77                 //無効なバイト\r
78                 mbsize = 0;\r
79                 break;\r
80             case 0:\r
81                 //マルチバイト後続バイト\r
82                 if(mbsize > 0){\r
83                     mbsize--;\r
84                     if(mbsize == 0){\r
85                         count++;\r
86                     }\r
87                 }\r
88                 break;\r
89             case 1:\r
90                 //1バイト文字\r
91                 count++;\r
92                 if(mbsize > 0){\r
93                     mbsize = 0;\r
94                 }\r
95                 break;\r
96             default:\r
97                 //nバイト文字の最初のバイト\r
98                 mbsize = n - 1;\r
99                 break;\r
100         }\r
101     }\r
102     return count;\r
103 }\r
104 \r
105 uint CHNLIB_UTF8_GetNextUnicodeOfCharacter(const char s[], const char **next)\r
106 {\r
107     //[UTF-8]\r
108     //sをUTF-8文字列として解釈し、その文字列の最初の文字のUnicodeを返す。\r
109     //また、nextがNULLでないとき、*nextに、この文字列中で次の文字にあたる部分へのポインタを格納する。\r
110     //s==NULLの時、*nextの値は変更されない。\r
111     //次の文字が存在しない場合は、*nextはs中の終端文字へのポインタとなる。また、戻り値は0となる。\r
112     //無効な(マルチバイトの一部が欠けているような)文字は無視する。\r
113     int i, n, mbsize;\r
114     uint unicode;\r
115     \r
116     if(s == NULL){\r
117         return 0;\r
118     }\r
119     \r
120     unicode = 0;\r
121     mbsize = 0;\r
122     for(i = 0; s[i] != '\0'; i++){\r
123         n = CHNLIB_UTF8_GetCharacterType(s[i]);\r
124         switch(n){\r
125             case -1:\r
126                 //無効なバイト\r
127                 mbsize = 0;\r
128                 break;\r
129             case 0:\r
130                 //マルチバイト後続バイト\r
131                 if(mbsize > 0){\r
132                     mbsize--;\r
133                     unicode <<= 6;\r
134                     unicode |= (0x3f & s[i]);\r
135                     if(mbsize == 0){\r
136                         return unicode;\r
137                     }\r
138                 }\r
139                 break;\r
140             case 1:\r
141                 //1バイト文字\r
142                 if(next != NULL){\r
143                     *next = (char *)(s + 1);\r
144                 }\r
145                 return s[i];\r
146             default:\r
147                 //nバイト文字の最初のバイト\r
148                 unicode = (((s[i]) << (n + 1)) >> n + 1);\r
149                 mbsize = n - 1;\r
150                 if(next != NULL){\r
151                     *next = (char *)(s + n);\r
152                 }\r
153                 break;\r
154         }\r
155     }\r
156     if(next != NULL){\r
157         *next = &s[i];\r
158     }\r
159     return 0;\r
160 }\r
161 \r
162 int CHNLIB_UTF8_CompareString(const char s[], const char search[])\r
163 {\r
164     //[UTF-8]\r
165     //s,searchをUTF-8文字列として解釈し、s[]の先頭からsearch[]と比較し、searchの終端まで一致したらTrue, 一致しなかったらFalseを返す。\r
166     //終端文字は比較せず、search[]に含まれる文字(終端文字除く)がすべて入っていれば一致とみなす。\r
167     //ただし、searchの先頭文字が終端文字、つまり空文字列だった場合は、常にFalseを返す。\r
168     int i, i_max;\r
169     \r
170     if(s == NULL || search == NULL){\r
171         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
172         return False;\r
173     }\r
174     if(search[0] == '\0'){\r
175         //空文字はいかなる文字列とも一致しない。\r
176         return False;\r
177     }\r
178     \r
179     i_max = CHNLIB_UTF8_GetStringLengthByCharacter(search);\r
180     for(i = 0; i < i_max; i++){\r
181         if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) != CHNLIB_UTF8_GetNextUnicodeOfCharacter(search, &search)){\r
182             return False;\r
183         }\r
184     }\r
185     return True;\r
186 }\r
187 \r
188 int CHNLIB_UTF8_CompareString_LeftHand(const char s[], const char search[])\r
189 {\r
190     //[UTF-8]\r
191     //s,searchをUTF-8文字列として解釈し、二つの文字列がどの程度一致するか調べる。前方一致。\r
192     //戻り値は、終端文字を除く、同一だった文字数。\r
193     int i, i_max;\r
194     \r
195     if(s == NULL || search == NULL){\r
196         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
197         return 0;\r
198     }\r
199     \r
200     i_max = CHNLIB_UTF8_GetStringLengthByCharacter(search);\r
201     for(i = 0; i < i_max; i++){\r
202         if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) != CHNLIB_UTF8_GetNextUnicodeOfCharacter(search, &search)){\r
203             break;\r
204         }\r
205     }\r
206     return i;\r
207 }\r
208 \r
209 int CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(const char s[], int start, int end)\r
210 {\r
211     //[UTF-8]\r
212     //sをUTF-8文字列として解釈し、start番目の文字からend番目の文字までの占めるバイト数を返す。\r
213     //start番目の文字が終端文字以降の文字を指している場合は0を返す。\r
214     //end番目の文字が終端文字以降の文字を指していても、endが文字列終端を指している場合と同値になる。\r
215     int i;\r
216     const char *p;\r
217     \r
218     if(s == NULL){\r
219         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
220         return 0;\r
221     }\r
222     if(end < start){\r
223         CHNLIB_ReportError("Invalid index.\n", CHNLIB_DEBUG_ARGUMENTS);\r
224         return 0;\r
225     }\r
226     \r
227     for(i = 0; i < start; i++){\r
228         if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) == 0){\r
229             return 0;\r
230         }\r
231     }\r
232     p = s;\r
233     for(; i <= end; i++){\r
234         CHNLIB_UTF8_GetNextUnicodeOfCharacter(p, &p);\r
235     }\r
236     \r
237     return (int)(p - s);\r
238 }\r
239 \r
240 uint CHNLIB_UTF8_GetCountOfContain(const char s[], const char search[])\r
241 {\r
242     //[UTF-8]\r
243     //文字列s中に、文字列searchがいくつ含まれているかを返す。\r
244     uint count;\r
245     \r
246     if(s == NULL || search == NULL){\r
247         CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
248         return 0;\r
249     }\r
250     \r
251     count = 0;\r
252     for(;;){\r
253         if(CHNLIB_UTF8_CompareString(s, search)){\r
254             count++;\r
255         }\r
256         if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) == 0){\r
257             break;\r
258         }\r
259     }\r
260     return count;\r
261 }\r