OSDN Git Service

d3d0fa61827d9d0fb3b22fe3bc4f6749dfc2b8c1
[chnosproject/CHNOSProject.git] / CHNOSProject / chn / chnlib00.c
1 //\r
2 //  chnlib00.c\r
3 //  AI003\r
4 //\r
5 //  Created by 西田 耀 on 13/01/28.\r
6 //  Copyright (c) 2013年 Hikaru Nishida. All rights reserved.\r
7 //\r
8 \r
9 //UIPArray関連のうち、このソースファイルで完結する関数群\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 #define CHNLIB_UIPArray_INTERNAL_PACKDATAS   7\r
24 \r
25 //\r
26 //Declare internal functions\r
27 //\r
28 CHNLIB_UIPArray *CHNLIB_UIPArray_Internal_Allocate(void);\r
29 \r
30 //\r
31 //Define types\r
32 //\r
33 typedef struct CHNLIB_UIPARRAY_INTERNAL_TAG CHNLIB_UIPArray_Internal_Tag;\r
34 struct CHNLIB_UIPARRAY_INTERNAL_TAG {\r
35     //UIPArrayの一つの添字に対応するデータを格納する構造体\r
36     uint data32;\r
37     void *pointer;\r
38 };\r
39 \r
40 struct CHNLIB_UIPARRAY {\r
41     //UnsignedIntとPointerを格納するArray構造体\r
42     CHNLIB_StructureHeader header;\r
43     \r
44     int using_tags;    //Number of using tags in this pack.\r
45     CHNLIB_UIPArray_Internal_Tag tag[CHNLIB_UIPArray_INTERNAL_PACKDATAS];\r
46     CHNLIB_UIPArray *next;\r
47 };\r
48 \r
49 //\r
50 //Functions\r
51 //\r
52 CHNLIB_UIPArray *CHNLIB_UIPArray_Initialize(void)\r
53 {\r
54     //ポインタを初期化する(NULLを返す)。\r
55     return NULL;\r
56 }\r
57 \r
58 int CHNLIB_UIPArray_AppendLast(CHNLIB_UIPArray **array, uint data32, void *pointer)\r
59 {\r
60     //Arrayの末尾にデータを追加する。\r
61     int index;\r
62     \r
63     index = 0;\r
64     for(; *array != NULL && (*array)->using_tags == CHNLIB_UIPArray_INTERNAL_PACKDATAS; array = &((*array)->next)){\r
65         index += CHNLIB_UIPArray_INTERNAL_PACKDATAS;\r
66     }\r
67     \r
68     if(*array == NULL){\r
69         *array = CHNLIB_UIPArray_Internal_Allocate();\r
70     }\r
71     (*array)->tag[(*array)->using_tags].data32 = data32;\r
72     (*array)->tag[(*array)->using_tags].pointer = pointer;\r
73     (*array)->using_tags++;\r
74     \r
75     return index + (*array)->using_tags - 1;\r
76 }\r
77 \r
78 int CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(CHNLIB_UIPArray **array, uint data32, void *pointer, int (*IsDuplicated)(const void *listtag, const void *newtag))\r
79 {\r
80     //戻り値:IsAdded(True/False)\r
81     //int (*IsDuplicated)(void *listtag, void *newtag)は、重複を確認する関数へのポインタ。\r
82     //listtagにarrayのすべてのpointerを与え、すべてがFalseだった場合追加してFalseを返す。\r
83     //Trueが返った時点で、追加をせずTrueを返す。\r
84     int i, i_max;\r
85     \r
86     i_max = CHNLIB_UIPArray_GetNumberOfDatas(*array);\r
87     for(i = 0; i < i_max; i++){\r
88         if(IsDuplicated(CHNLIB_UIPArray_GetPointerByIndex(*array, i), pointer)){\r
89             return False;\r
90         }\r
91     }\r
92     \r
93     CHNLIB_UIPArray_AppendLast(array, data32, pointer);\r
94     \r
95     return True;\r
96 }\r
97 \r
98 int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index)\r
99 {\r
100     //戻り値:削除が成功したか(0:成功,-1:指定された添字の要素は存在しない)\r
101     //indexが指し示す要素を削除し、後続の要素は前へつめる。\r
102     //削除された要素に格納されていたデータに関しては関知しない。\r
103     int i;\r
104     \r
105     for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
106         if(*array == NULL){\r
107             return -1;\r
108         }\r
109         array = &(*array)->next;\r
110     }\r
111     if(*array == NULL){\r
112         return -1;\r
113     }\r
114     if(index >= (*array)->using_tags){\r
115         return -1;\r
116     }\r
117     for(i = index; i < (*array)->using_tags - 1; i++){\r
118         (*array)->tag[i] = (*array)->tag[i + 1];\r
119     }\r
120     for(;;){\r
121         if((*array)->next != NULL){\r
122             if((*array)->using_tags != CHNLIB_UIPArray_INTERNAL_PACKDATAS || (*array)->next->using_tags == 0){\r
123                 //タグ数とリンクの関係があわない。以下の状態になっている。\r
124                 //次のパックがあるのに、間のパックが使い切られていない。\r
125                 //次のパックがあるのに、次のパックに一つもデータがない。\r
126                 CHNLIB_ReportError("Internal data error.", CHNLIB_DEBUG_ARGUMENTS);\r
127             }\r
128             (*array)->tag[CHNLIB_UIPArray_INTERNAL_PACKDATAS - 1] = (*array)->next->tag[0];\r
129             array = &(*array)->next;\r
130             for(i = 0; i < (*array)->using_tags - 1; i++){\r
131                 (*array)->tag[i] = (*array)->tag[i + 1];\r
132             }\r
133         } else{\r
134             (*array)->using_tags--;\r
135             if((*array)->using_tags == 0){\r
136                 //もうこのパックにはデータが存在しないので、パックを削除。\r
137                 CHNLIB_System_FreeMemory(*array, CHNLIB_DEBUG_ARGUMENTS);\r
138                 *array = NULL;\r
139             }\r
140             break;\r
141         }\r
142     }\r
143     return 0;\r
144 }\r
145 \r
146 void CHNLIB_UIPArray_FreeOnlyArray(CHNLIB_UIPArray **array)\r
147 {\r
148     //ArrayそのものをFreeする。\r
149     //Pointerの参照先については関知しない。\r
150     CHNLIB_UIPArray *now, *next;\r
151     \r
152     now = *array;\r
153     *array = NULL;\r
154     \r
155     for(; now != NULL; ){\r
156         next = now->next;\r
157         //free(now);\r
158         CHNLIB_System_FreeMemory(now, CHNLIB_DEBUG_ARGUMENTS);\r
159         now = next;\r
160     }\r
161     return;\r
162 }\r
163 \r
164 void CHNLIB_UIPArray_FreeOnlyAllPointer(CHNLIB_UIPArray *array)\r
165 {\r
166     //Pointerの参照先をすべてFree.\r
167     //Array自体はFreeしない。\r
168     int i;\r
169     \r
170     for(; array != NULL; array = array->next){\r
171         for(i = 0; i < array->using_tags; i++){\r
172             if(array->tag[i].pointer != NULL){\r
173                 //free(array->tag[i].pointer);\r
174                 CHNLIB_System_FreeMemory(array->tag[i].pointer, CHNLIB_DEBUG_ARGUMENTS);\r
175                 array->tag[i].pointer = NULL;\r
176             }\r
177         }\r
178     }\r
179     return;\r
180 }\r
181 \r
182 void CHNLIB_UIPArray_FreeOnlySelectedPointer(CHNLIB_UIPArray *array)\r
183 {\r
184     //Pointerの参照先で、data32==FalseのものをFree.\r
185     //Array自体はFreeしない。\r
186     int i;\r
187     \r
188     for(; array != NULL; array = array->next){\r
189         for(i = 0; i < array->using_tags; i++){\r
190             if(array->tag[i].pointer != NULL && !array->tag[i].data32){\r
191                 //free(array->tag[i].pointer);\r
192                 CHNLIB_System_FreeMemory(array->tag[i].pointer, CHNLIB_DEBUG_ARGUMENTS);\r
193                 array->tag[i].pointer = NULL;\r
194             }\r
195         }\r
196     }\r
197     return;\r
198 }\r
199 \r
200 void CHNLIB_UIPArray_FreeAll(CHNLIB_UIPArray **array)\r
201 {\r
202     //Array及びすべてのPointerをFree.\r
203     CHNLIB_UIPArray_FreeOnlyAllPointer(*array);\r
204     CHNLIB_UIPArray_FreeOnlyArray(array);\r
205     return;\r
206 }\r
207 \r
208 void CHNLIB_UIPArray_FreeSelectedAll(CHNLIB_UIPArray **array)\r
209 {\r
210     //Array及びdata32==TrueのPointerをFree.\r
211     CHNLIB_UIPArray_FreeOnlySelectedPointer(*array);\r
212     CHNLIB_UIPArray_FreeOnlyArray(array);\r
213     return;\r
214 }\r
215 \r
216 int CHNLIB_UIPArray_GetNumberOfDatas(const CHNLIB_UIPArray *array)\r
217 {\r
218     //Arrayで現在使用中のデータの個数を返す。\r
219     int tags;\r
220     \r
221     tags = 0;\r
222     \r
223     for(; array != NULL; array = array->next){\r
224         tags += array->using_tags;\r
225     }\r
226     return tags;\r
227 }\r
228 \r
229 uint CHNLIB_UIPArray_GetData32ByIndex(const CHNLIB_UIPArray *array, int index)\r
230 {\r
231     //retv:array[index]->data32\r
232     for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
233         if(array == NULL){\r
234             return 0;\r
235         }\r
236         array = array->next;\r
237     }\r
238     if(array == NULL){\r
239         return 0;\r
240     }\r
241     return array->tag[index].data32;\r
242 }\r
243 \r
244 uint CHNLIB_UIPArray_SetData32ByIndex(CHNLIB_UIPArray *array, int index, uint data32)\r
245 {\r
246     //retv = old data32\r
247     \r
248     uint olddata;\r
249     \r
250     for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
251         if(array == NULL){\r
252             return 0;\r
253         }\r
254         array = array->next;\r
255     }\r
256     if(array == NULL){\r
257         return 0;\r
258     }\r
259     olddata = array->tag[index].data32;\r
260     array->tag[index].data32 = data32;\r
261     return olddata;\r
262 }\r
263 \r
264 void *CHNLIB_UIPArray_GetPointerByIndex(const CHNLIB_UIPArray *array, int index)\r
265 {\r
266     //retv:array[index]->pointer\r
267     for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
268         if(array == NULL){\r
269             return NULL;\r
270         }\r
271         array = array->next;\r
272     }\r
273     if(array == NULL){\r
274         return NULL;\r
275     }\r
276     return array->tag[index].pointer;\r
277 }\r
278 \r
279 int CHNLIB_UIPArray_GetIndexByData32(const CHNLIB_UIPArray *array, uint data32)\r
280 {\r
281     //指定されたdata32を持つ最小のIndexを返す。\r
282     int i, i_max;\r
283     \r
284     i_max = CHNLIB_UIPArray_GetNumberOfDatas(array);\r
285     for(i = 0; i < i_max; i++){\r
286         if(CHNLIB_UIPArray_GetData32ByIndex(array, i) == data32){\r
287             return i;\r
288         }\r
289     }\r
290     return CHNLIB_UIPArray_INDEX_NOTFOUND;\r
291 }\r
292 \r
293 void *CHNLIB_UIPArray_GetPointerByData32(const CHNLIB_UIPArray *array, uint data32)\r
294 {\r
295     //指定されたdata32を持つindexのデータのPointerを返す。\r
296     return CHNLIB_UIPArray_GetPointerByIndex(array, CHNLIB_UIPArray_GetIndexByData32(array, data32));\r
297 }\r
298 \r
299 //\r
300 //Internal functions\r
301 //\r
302 CHNLIB_UIPArray *CHNLIB_UIPArray_Internal_Allocate(void)\r
303 {\r
304     //Arrayの実体を確保する。\r
305     //このソース以外から呼び出してはならない。\r
306     CHNLIB_UIPArray *tag;\r
307     \r
308     tag = (CHNLIB_UIPArray *)CHNLIB_System_AllocateMemory_Strict(sizeof(CHNLIB_UIPArray), CHNLIB_DEBUG_ARGUMENTS);\r
309     \r
310     CHNLIB_StructureHeader_Initialize(&tag->header, CHNLIB_STRUCT_ID_UIPArray);\r
311     \r
312     return tag;\r
313 \r
314 }\r
315 \r