source: libcf/trunk/src/cf_list.c@ 117

Last change on this file since 117 was 117, checked in by cheese, 11 years ago

#1 more fix and arrange doxygen comments

File size: 6.8 KB
Line 
1/**
2 * @file cf_list.c
3 * @author myusgun <myusgun@gmail.com>
4 *
5 * @brief 연결 리스트 구현
6 */
7#include "cf_list.h"
8#include "cf_local.h"
9#include "cf_error.h"
10
11#include <stdlib.h>
12
13#define ASSERT_CTX(__ctx) \
14 if (__ctx == NULL) \
15 return CF_ERROR_DS_INVALID_CTX
16
17#define ASSERT_TRAVERSER(__trav) \
18 if (__trav == NULL) \
19 return CF_ERROR_DS_INVALID_TRAVERSER
20
21#define ASSERT_ARGS(x) \
22 if ((x)) \
23 return CF_ERROR_DS_INVALID_ARGS
24
25/** 리스트 노드 (CF_Traverser의 구현) */
26typedef struct __cf_node__
27{
28 void * element;
29 struct __cf_node__ * prev;
30 struct __cf_node__ * next;
31} CF_NODE;
32
33/** 리스트 컨텍스트 (CF_List_Ctx의 구현) */
34typedef struct __cf_list__
35{
36 int size;
37 CF_NODE * front;
38 CF_NODE * rear;
39} CF_LIST_CTX;
40
41/**
42 * 리스트 컨텍스트 생성
43 *
44 * @return 성공 시, CF_OK; 실패 시, 오류 코드
45 *
46 * @param ctx 리스트 컨텍스트 포인터
47 */
48int
49CF_List_CreateCtx (CF_List_Ctx * ctx)
50{
51 CF_LIST_CTX * context = NULL;
52
53 ASSERT_ARGS (ctx == NULL);
54
55 context = (CF_LIST_CTX *) calloc (sizeof (CF_LIST_CTX), 1);
56 if (context == NULL)
57 return CF_ERROR_DS_CREATE_CTX;
58
59 *ctx = (CF_List_Ctx) context;
60
61 return CF_OK;
62}
63
64/**
65 * 리스트 컨텍스트 해제
66 *
67 * @return 성공 시, CF_OK; 실패 시, 오류 코드
68 *
69 * @param ctx 리스트 컨텍스트
70 */
71int
72CF_List_DestroyCtx (CF_List_Ctx ctx)
73{
74 CF_LIST_CTX * context = (CF_LIST_CTX *) ctx;
75
76 ASSERT_CTX (ctx);
77
78 CF_List_RemoveAll (ctx);
79
80 free (context);
81
82 return CF_OK;
83}
84
85/**
86 * 리스트 탐색자(Traverser)를 Front 위치로 설정
87 *
88 * @return 성공 시, CF_OK; 실패 시, 오류 코드
89 *
90 * @param ctx 리스트 컨텍스트
91 * @param traverser 리스트 탐색자 주소
92 */
93int
94CF_List_Front (CF_List_Ctx ctx,
95 CF_Traverser * traverser)
96{
97 CF_LIST_CTX * context = (CF_LIST_CTX *) ctx;
98
99 ASSERT_CTX (ctx);
100 ASSERT_TRAVERSER (traverser);
101
102 *traverser = (CF_Traverser *) context->front;
103
104 return CF_OK;
105}
106
107/**
108 * 리스트 탐색자(Traverser)를 Rear 위치로 설정
109 *
110 * @return 성공 시, CF_OK; 실패 시, 오류 코드
111 *
112 * @param ctx 리스트 컨텍스트
113 * @param traverser 리스트 탐색자 주소
114 */
115int
116CF_List_Rear (CF_List_Ctx ctx,
117 CF_Traverser * traverser)
118{
119 CF_LIST_CTX * context = (CF_LIST_CTX *) ctx;
120
121 ASSERT_CTX (ctx);
122 ASSERT_TRAVERSER (traverser);
123
124 *traverser = (CF_Traverser *) context->rear;
125
126 return CF_OK;
127}
128
129/**
130 * 리스트에 새 데이터 삽입
131 *
132 * @return 성공 시, CF_OK; 실패 시, 오류 코드
133 *
134 * @param ctx 리스트 컨텍스트
135 * @param traverser 리스트 탐색자
136 * @param direction 탐색자의 전/후를 지정
137 * @param element 삽입할 데이터 주소
138 *
139 * @remarks
140 * traverser가 NULL일 때,
141 * direction이 CF_DIRECTION_BEFORE라면 Front 위치이고
142 * direction이 CF_DIRECTION_AFTER라면 Rear 위치에 삽입
143 */
144int
145CF_List_Insert (CF_List_Ctx ctx,
146 const CF_Traverser traverser,
147 const CF_DIRECTION direction,
148 const void * element)
149{
150 CF_LIST_CTX * context = (CF_LIST_CTX *) ctx;
151 CF_NODE * node = NULL;
152 CF_NODE * newnode = NULL;
153
154 ASSERT_CTX (ctx);
155
156 newnode = (CF_NODE *) calloc (sizeof (CF_NODE), 1);
157 if (newnode == NULL)
158 return CF_ERROR_DS_CREATE_NODE;
159
160 newnode->element = (void *) element;
161
162 TRY
163 {
164 if (CF_List_GetSize (ctx) == 0)
165 {
166 context->front = context->rear = newnode;
167 TRY_BREAK;
168 }
169
170 if (direction == CF_DIRECTION_BEFORE)
171 {
172 node = traverser ? (CF_NODE *) traverser : context->front;
173
174 newnode->next = node;
175 if (node)
176 {
177 newnode->prev = node->prev;
178 node->prev = newnode;
179 if (newnode->prev)
180 newnode->prev->next = newnode;
181 }
182
183 if (node == context->front)
184 context->front = newnode;
185 }
186 else /* if (direction == CF_DIRECTION_AFTER) */
187 {
188 node = traverser ? (CF_NODE *) traverser : context->rear;
189
190 newnode->prev = node;
191 if (node)
192 {
193 newnode->next = node->next;
194 node->next = newnode;
195 if (newnode->next)
196 newnode->next->prev = newnode;
197 }
198
199 if (node == context->rear)
200 context->rear = newnode;
201 }
202 } NO_CATCH;
203
204 context->size++;
205
206 return CF_OK;
207}
208
209/**
210 * 리스트에서 탐색자 위치의 항목을 삭제
211 *
212 * @return 성공 시, CF_OK; 실패 시, 오류 코드
213 *
214 * @param ctx 리스트 컨텍스트
215 * @param traverser 리스트 탐색자 주소
216 */
217int
218CF_List_Remove (CF_List_Ctx ctx,
219 CF_Traverser * traverser)
220{
221 CF_LIST_CTX * context = (CF_LIST_CTX *) ctx;
222 CF_NODE * node = NULL;
223
224 ASSERT_CTX (ctx);
225 ASSERT_TRAVERSER (traverser);
226 ASSERT_ARGS (*traverser == NULL);
227
228 node = (CF_NODE *) *traverser;
229
230 if (node->prev)
231 {
232 node->prev->next = node->next;
233 if (node == context->rear)
234 context->rear = node->prev;
235 }
236
237 if (node->next)
238 {
239 node->next->prev = node->prev;
240 if (node == context->front)
241 context->front = node->next;
242 }
243
244 free (node);
245
246 *traverser = NULL;
247
248 context->size--;
249
250 if (CF_List_GetSize (ctx) == 0)
251 context->front = context->rear = NULL;
252
253 return CF_OK;
254}
255
256/**
257 * 리스트에서 모든 항목을 삭제
258 *
259 * @return 성공 시, CF_OK; 실패 시, 오류 코드
260 *
261 * @param ctx 리스트 컨텍스트
262 */
263int
264CF_List_RemoveAll (CF_List_Ctx ctx)
265{
266 CF_Traverser traverser = NULL;
267
268 ASSERT_CTX (ctx);
269
270 while (CF_List_GetSize (ctx) > 0)
271 {
272 CF_List_Front (ctx, &traverser);
273 CF_List_Remove (ctx, &traverser);
274 }
275
276 return CF_OK;
277}
278
279/**
280 * 탐색자 위치의 데이터를 가져옴
281 *
282 * @return 성공 시, CF_OK; 실패 시, 오류 코드
283 *
284 * @param traverser 리스트 탐색자
285 * @param element 데이터 주소
286 */
287int
288CF_List_GetElement (const CF_Traverser traverser,
289 void ** element)
290{
291 CF_NODE * node = (CF_NODE *) traverser;
292
293 ASSERT_TRAVERSER (traverser);
294 ASSERT_ARGS (element == NULL);
295
296 *element = node->element;
297
298 return CF_OK;
299}
300
301/**
302 * 탐색자 위치를 이전으로 이동
303 *
304 * @return 성공 시, CF_OK; 실패 시, 오류 코드
305 *
306 * @param traverser 리스트 탐색자 주소
307 */
308int
309CF_List_Prev (CF_Traverser * traverser)
310{
311 CF_NODE * node = (CF_NODE *) *traverser;
312
313 ASSERT_TRAVERSER (traverser);
314 ASSERT_ARGS (*traverser == NULL);
315
316 node = node->prev;
317 *traverser = (CF_Traverser *) node;
318 if (node == NULL)
319 return CF_ERROR_DS_NO_MORE;
320
321 return CF_OK;
322}
323
324/**
325 * 탐색자 위치를 다음으로 이동
326 *
327 * @return 성공 시, CF_OK; 실패 시, 오류 코드
328 *
329 * @param traverser 리스트 탐색자 주소
330 */
331int
332CF_List_Next (CF_Traverser * traverser)
333{
334 CF_NODE * node = (CF_NODE *) *traverser;
335
336 ASSERT_TRAVERSER (traverser);
337 ASSERT_ARGS (*traverser == NULL);
338
339 node = node->next;
340 *traverser = (CF_Traverser *) node;
341 if (node == NULL)
342 return CF_ERROR_DS_NO_MORE;
343
344 return CF_OK;
345}
346
347/**
348 * 리스트에 등록된 항목의 수를 가져옴
349 *
350 * @return 성공 시, 항목 수; 실패 시, 오류 코드
351 *
352 * @param ctx 리스트 컨텍스트
353 */
354int
355CF_List_GetSize (CF_List_Ctx ctx)
356{
357 CF_LIST_CTX * context = (CF_LIST_CTX *) ctx;
358
359 ASSERT_CTX (ctx);
360
361 return context->size;
362}
Note: See TracBrowser for help on using the repository browser.