1 /* Copyright 2013 Akira Ohta (akohta001@gmail.com)
2 This file is part of ntch.
4 The ntch is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 The ntch is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with ntch. If not, see <http://www.gnu.org/licenses/>.
22 #include "utils/nt_std_t.h"
23 #include "utils/text.h"
25 #define NT_ENUM_CHK_SUM (878428)
26 #define NT_MAP_CHK_SUM (878429)
27 #define NT_QUEUE_CHK_SUM (878430)
29 typedef struct tag_nt_enum_t *nt_enum_tp;
30 typedef struct tag_nt_enum_t {
31 nt_enum_handle_t handle;
35 nt_memfree_fn free_func;
38 typedef struct tag_nt_map_t *nt_map_tp;
39 typedef struct tag_nt_map_t {
40 nt_map_handle_t handle;
41 nt_link_tp key_value_list;
44 typedef struct tag_nt_queue_t *nt_queue_tp;
45 typedef struct tag_nt_queue_t{
46 nt_queue_handle_t handle;
51 nt_map_handle nt_map_alloc()
54 mapp = malloc(sizeof(nt_map_t));
58 mapp->handle.chk_sum = NT_MAP_CHK_SUM;
59 mapp->key_value_list = NULL;
63 void nt_map_free(nt_map_handle handle, nt_memfree_fn value_free_func)
66 nt_link_tp linkp, nextp;
67 nt_w_key_value_tp kvp;
69 assert(handle->chk_sum == NT_MAP_CHK_SUM);
70 mapp = (nt_map_tp)handle;
71 if(mapp->key_value_list){
72 linkp = mapp->key_value_list;
75 kvp = (nt_w_key_value_tp)linkp->data;
78 (value_free_func)(kvp->value);
84 }while(linkp != mapp->key_value_list);
89 BOOL nt_map_add_pair(nt_map_handle handle, const wchar_t *key, void *value)
93 nt_w_key_value_tp kvp;
95 assert(handle->chk_sum == NT_MAP_CHK_SUM);
96 mapp = (nt_map_tp)handle;
97 kvp = nt_map_find(handle, key);
99 kvp = nt_w_key_value_alloc(key, value);
102 linkp = nt_link_add_data(mapp->key_value_list, kvp);
108 if(!mapp->key_value_list)
109 mapp->key_value_list = linkp;
113 void* nt_map_find(nt_map_handle handle, const wchar_t *key)
117 nt_w_key_value_tp kvp;
119 assert(handle->chk_sum == NT_MAP_CHK_SUM);
120 mapp = (nt_map_tp)handle;
121 if(mapp->key_value_list){
122 linkp = mapp->key_value_list;
124 kvp = (nt_w_key_value_tp)linkp->data;
125 if(0 == wcscmp(key, kvp->key))
129 }while(linkp != mapp->key_value_list);
134 void* nt_map_remove(nt_map_handle handle, const wchar_t *key)
138 nt_w_key_value_tp kvp;
141 assert(handle->chk_sum == NT_MAP_CHK_SUM);
142 mapp = (nt_map_tp)handle;
143 if(mapp->key_value_list){
144 linkp = mapp->key_value_list;
146 kvp = (nt_w_key_value_tp)linkp->data;
147 if(0 == wcscmp(key, kvp->key)){
149 mapp->key_value_list = nt_link_remove2(
150 mapp->key_value_list, linkp);
157 }while(linkp != mapp->key_value_list);
162 int nt_map_get_count(nt_map_handle handle)
166 assert(handle->chk_sum == NT_MAP_CHK_SUM);
167 mapp = (nt_map_tp)handle;
168 if(!mapp->key_value_list)
170 return nt_link_num(mapp->key_value_list);
173 nt_link_tp nt_map_get_values(nt_map_handle handle)
177 assert(handle->chk_sum == NT_MAP_CHK_SUM);
178 mapp = (nt_map_tp)handle;
179 nt_link_tp linkp, wlinkp, rlinkp;
180 nt_w_key_value_tp kvp;
184 if(mapp->key_value_list){
185 linkp = mapp->key_value_list;
187 kvp = (nt_w_key_value_tp)linkp->data;
188 wlinkp = nt_link_add_data(rlinkp, kvp->value);
189 if(wlinkp && !rlinkp)
192 }while(linkp != mapp->key_value_list);
197 nt_enum_handle nt_enum_set(nt_link_tp linkp)
201 enump = malloc(sizeof(nt_enum_t));
204 enump->handle.chk_sum = NT_ENUM_CHK_SUM;
206 enump->source = linkp;
207 enump->current = NULL;
208 enump->free_func = NULL;
209 return (nt_enum_handle)enump;
212 void nt_enum_set_free_func(nt_enum_handle handle, nt_memfree_fn free_func)
215 enump = (nt_enum_tp)handle;
217 assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
218 enump->free_func = free_func;
222 void nt_enum_reset(nt_enum_handle handle)
225 enump = (nt_enum_tp)handle;
227 assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
228 enump->current = NULL;
231 void nt_enum_unset(nt_enum_handle handle)
234 enump = (nt_enum_tp)handle;
236 assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
237 if(enump->source && enump->free_func){
238 nt_all_link_free(enump->source, enump->free_func);
243 void* nt_enum_fetch(nt_enum_handle handle)
248 enump = (nt_enum_tp)handle;
250 assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
256 data = enump->source->data;
257 enump->current = enump->source->next;
261 if(enump->source == enump->current){
265 data = enump->current->data;
266 enump->current = enump->current->next;
270 int nt_enum_get_count(nt_enum_handle handle)
273 enump = (nt_enum_tp)handle;
275 assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
278 return nt_link_num(enump->source);
281 nt_link_tp nt_link_insert_before(nt_link_tp top_linkp,
282 nt_link_tp dest, nt_link_tp src)
284 if(top_linkp == dest){
285 src->next = top_linkp;
286 src->prev = top_linkp->prev;
287 src->prev->next = src;
288 src->next->prev = src;
293 src->prev = dest->prev;
294 src->prev->next = src;
295 src->next->prev = src;
300 nt_link_tp nt_link_add_last(nt_link_tp top_linkp, nt_link_tp src)
307 old_last = top_linkp->prev;
308 old_last->next = src;
309 top_linkp->prev = src->prev;
310 src->prev->next = top_linkp;
311 src->prev = old_last;
315 void nt_link_sort(nt_link_tp *top_linkp, nt_compare_fn comp_func)
317 nt_link_tp cur_linkp, next_linkp, work_linkp;
319 cur_linkp = *top_linkp;
321 next_linkp = cur_linkp->next;
322 work_linkp = *top_linkp;
324 while(work_linkp != cur_linkp){
325 if(0 < (comp_func)(cur_linkp->data, work_linkp->data)){
326 *top_linkp = nt_link_remove2(*top_linkp, cur_linkp);
327 *top_linkp = nt_link_insert_before(
328 *top_linkp, work_linkp, cur_linkp);
331 work_linkp = work_linkp->next;
333 cur_linkp = next_linkp;
334 }while(cur_linkp != *top_linkp);
338 void nt_link_n_sort(nt_link_tp *top_linkp, nt_compare_n_fn comp_func)
340 nt_link_tp cur_linkp, next_linkp, work_linkp;
342 cur_linkp = *top_linkp;
344 next_linkp = cur_linkp->next;
345 work_linkp = *top_linkp;
347 while(work_linkp != cur_linkp){
348 if(0 < (comp_func)(cur_linkp->n_data, work_linkp->n_data)){
349 *top_linkp = nt_link_remove2(*top_linkp, cur_linkp);
350 *top_linkp = nt_link_insert_before(
351 *top_linkp, work_linkp, cur_linkp);
354 work_linkp = work_linkp->next;
356 cur_linkp = next_linkp;
357 }while(cur_linkp != *top_linkp);
361 int nt_link_num(nt_link_tp linkp){
367 while(curp != linkp){
374 void* nt_link_get_by_index(nt_link_tp linkp, int index){
382 while(curp != linkp){
391 nt_link_tp nt_link_add_data(nt_link_tp link, void *data)
393 nt_link_tp ptr = malloc(sizeof(nt_link_t));
400 ptr->prev = link->prev;
401 ptr->prev->next = ptr;
411 nt_link_tp nt_link_add_n_data(nt_link_tp link, int n_data)
413 nt_link_tp ptr = calloc(1,sizeof(nt_link_t));
417 ptr->n_data = n_data;
420 ptr->prev = link->prev;
421 ptr->prev->next = ptr;
431 nt_link_tp nt_link_remove(nt_link_tp src, nt_link_tp target)
433 while(src != target){
434 if(src->next == target){
435 src->next = target->next;
436 target->next->prev = src;
444 nt_link_tp nt_link_remove2(nt_link_tp top_linkp, nt_link_tp target)
446 nt_link_tp new_top_linkp, prev, next;
448 if(top_linkp == target){
449 if(top_linkp == top_linkp->next)
451 new_top_linkp = top_linkp->next;
453 new_top_linkp = top_linkp;
460 return new_top_linkp;
463 nt_link_tp nt_link_remove_by_data(nt_link_tp link, void *data)
465 nt_link_tp ptr = link;
467 if(ptr->data == data){
468 ptr->prev->next = ptr->next;
469 ptr->next->prev = ptr->prev;
478 void* nt_link_get(nt_link_tp link)
483 nt_link_tp nt_link_find(nt_link_tp link, void *data,
484 nt_compare_fn comp_func)
486 nt_link_tp ptr = link;
488 if(0 == (comp_func)(ptr->data, data)){
498 nt_link_tp nt_link_next(nt_link_tp link)
503 nt_link_tp nt_link_copy(nt_link_tp src_linkp, nt_memcopy_fn copy_func)
505 nt_link_tp srcp, resultp, workp;
514 workp = nt_link_add_data(resultp, srcp->data);
516 ptr = (copy_func)(srcp->data);
518 workp = nt_link_add_data(resultp, ptr);
524 nt_all_link_free(resultp, NULL);
530 }while(srcp != src_linkp);
534 void* nt_link_strcpy_fnc(void *ptr)
546 void* nt_link_wcscpy_fnc(void *ptr)
550 cptr = (wchar_t*)ptr;
552 p = malloc((len+1)*sizeof(wchar_t));
559 int nt_link_wcscmp_fnc(void *lhs, void *rhs)
561 return wcscmp((const wchar_t *)lhs, (const wchar_t *)rhs);
565 void nt_all_link_free(nt_link_tp ptr, nt_memfree_fn free_func)
568 nt_link_tp tmp_linkp;
573 if(linkp->data && free_func)
574 (free_func)(linkp->data);
578 }while(ptr != linkp);
581 nt_key_value_tp nt_key_value_alloc(char *key, char *value)
583 nt_key_value_tp ptr = malloc(sizeof(nt_key_value_t));
591 nt_w_key_value_tp nt_w_key_value_alloc(const wchar_t *key, void *value)
593 nt_w_key_value_tp ptr = malloc(sizeof(nt_w_key_value_t));
596 ptr->key = nt_w_str_clone(key);
605 void* nt_stack_add_last(nt_stack_tp stackp, void* data)
614 linkp = stackp->linkp;
617 /* If there are data after the cursor,
620 if(cursor > stackp->cursor){
625 }while(linkp != stackp->linkp);
627 linkp = nt_link_add_data(stackp->linkp, data);
630 /* This special case we do not increment cursor */
631 /* stackp->cursor++;*/
635 void* nt_stack_push(nt_stack_tp stackp, void* data)
638 nt_link_tp saved_linkp, linkp;
642 linkp = nt_link_add_data(stackp->linkp, data);
645 stackp->linkp = linkp;
649 linkp = stackp->linkp;
652 /* Remove the links after the current corsor. */
653 if(cursor > stackp->cursor){
654 saved_linkp = stackp->linkp->prev;
655 stackp->linkp->prev = linkp->prev;
656 linkp->prev->next = stackp->linkp;
658 linkp->prev = saved_linkp;
659 saved_linkp->next = linkp;
661 /* Now the linkp is dangling */
662 if(!stackp->unlinkedp){
663 stackp->unlinkedp = linkp;
665 saved_linkp = stackp->unlinkedp->prev;
666 stackp->unlinkedp->prev = linkp->prev;
667 saved_linkp->next = linkp;
668 linkp->prev = saved_linkp;
674 }while(linkp != stackp->linkp);
676 linkp = nt_link_add_data(stackp->linkp, data);
683 void* nt_stack_pop(nt_stack_tp stackp)
690 linkp = stackp->linkp;
693 if(cursor == stackp->cursor){
695 if(stackp->cursor < 0){
702 }while(linkp != stackp->linkp);
706 void* nt_stack_peek(nt_stack_tp stackp)
713 linkp = stackp->linkp;
716 if(cursor == stackp->cursor){
721 }while(linkp != stackp->linkp);
724 int nt_stack_get_position(nt_stack_tp stackp)
726 return stackp->cursor;
729 BOOL nt_stack_is_empty(nt_stack_tp stackp)
731 return (!stackp->linkp);
734 void* nt_stack_cursor_next(nt_stack_tp stackp)
741 linkp = stackp->linkp;
744 if(cursor > (stackp->cursor+1)){
750 }while(linkp != stackp->linkp);
754 nt_stack_tp nt_stack_alloc()
756 nt_stack_tp stackp = malloc(sizeof(nt_stack_t));
761 stackp->linkp = NULL;
762 stackp->unlinkedp = NULL;
768 void nt_stack_free(nt_stack_tp ptr, nt_memfree_fn free_func)
777 nt_all_link_free(ptr->linkp, free_func);
780 nt_all_link_free(ptr->unlinkedp, free_func);
785 nt_queue_handle nt_queue_alloc()
788 ptr = malloc(sizeof(nt_queue_t));
792 ptr->handle.chk_sum = NT_QUEUE_CHK_SUM;
795 void nt_queue_free(nt_queue_handle handle, nt_memfree_fn free_func)
800 assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
801 queuep = (nt_queue_tp)handle;
803 nt_all_link_free(queuep->linkp, free_func);
808 BOOL nt_queue_push(nt_queue_handle handle, void* data)
814 assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
815 queuep = (nt_queue_tp)handle;
817 linkp = nt_link_add_data(queuep->linkp, data);
822 queuep->linkp = linkp;
825 void* nt_queue_shift(nt_queue_handle handle)
827 nt_link_tp linkp, prev, next;
832 assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
833 queuep = (nt_queue_tp)handle;
838 linkp = queuep->linkp;
839 if(linkp == linkp->next){
842 queuep->linkp = NULL;
851 queuep->linkp = next;
857 int nt_queue_get_count(nt_queue_handle handle)
862 assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
863 queuep = (nt_queue_tp)handle;
867 return nt_link_num(queuep->linkp);