OSDN Git Service

67927b4939a688347f085b6c382beb03e8bb3994
[ntch/develop.git] / src / utils / nt_std_t.c
1 /* Copyright 2013 Akira Ohta (akohta001@gmail.com)
2     This file is part of ntch.
3
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.
8
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.
13
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/>.
16     
17 */
18 #include <stdlib.h>
19 #include <wchar.h>
20 #include <memory.h>
21 #include <assert.h>
22 #include "utils/nt_std_t.h"
23 #include "utils/text.h"
24
25 #define NT_ENUM_CHK_SUM (878428)
26 #define NT_MAP_CHK_SUM (878429)
27 #define NT_QUEUE_CHK_SUM (878430)
28
29 typedef struct tag_nt_enum_t *nt_enum_tp;
30 typedef struct tag_nt_enum_t {
31         nt_enum_handle_t handle;
32         nt_link_tp source;
33         nt_link_tp current;
34         
35         nt_memfree_fn free_func;
36 }nt_enum_t;
37
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;
42 }nt_map_t;
43
44 typedef struct tag_nt_queue_t *nt_queue_tp;
45 typedef struct tag_nt_queue_t{
46         nt_queue_handle_t handle;
47         nt_link_tp linkp;
48 } nt_queue_t;
49
50
51 nt_map_handle nt_map_alloc()
52 {
53         nt_map_tp mapp;
54         mapp = malloc(sizeof(nt_map_t));
55         if(!mapp)
56                 return NULL;
57         
58         mapp->handle.chk_sum = NT_MAP_CHK_SUM;
59         mapp->key_value_list = NULL;
60         return &mapp->handle;
61 }
62
63 void nt_map_free(nt_map_handle handle, nt_memfree_fn value_free_func)
64 {
65         nt_map_tp mapp;
66         nt_link_tp linkp, nextp;
67         nt_w_key_value_tp kvp;
68         assert(handle);
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;
73                 do{
74                         nextp = linkp->next;
75                         kvp = (nt_w_key_value_tp)linkp->data;
76                         if(kvp->value)
77                                 if(value_free_func){
78                                         (value_free_func)(kvp->value);
79                         }
80                         free(kvp->key);
81                         free(kvp);
82                         free(linkp);
83                         linkp = nextp;
84                 }while(linkp != mapp->key_value_list);
85         }
86         free(mapp);
87 }
88
89 BOOL nt_map_add_pair(nt_map_handle handle, const wchar_t *key, void *value)
90 {
91         nt_map_tp mapp;
92         nt_link_tp linkp;
93         nt_w_key_value_tp kvp;
94         assert(handle);
95         assert(handle->chk_sum == NT_MAP_CHK_SUM);
96         mapp = (nt_map_tp)handle;
97         kvp = nt_map_find(handle, key);
98         assert(!kvp);
99         kvp = nt_w_key_value_alloc(key, value);
100         if(!kvp)
101                 return FALSE;
102         linkp = nt_link_add_data(mapp->key_value_list, kvp);
103         if(!linkp){
104                 free(kvp->key);
105                 free(kvp);
106                 return FALSE;
107         }
108         if(!mapp->key_value_list)
109                 mapp->key_value_list = linkp;
110         return TRUE;
111 }
112
113 void* nt_map_find(nt_map_handle handle, const wchar_t *key)
114 {
115         nt_map_tp mapp;
116         nt_link_tp linkp;
117         nt_w_key_value_tp kvp;
118         assert(handle);
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;
123                 do{
124                         kvp = (nt_w_key_value_tp)linkp->data;
125                         if(0 == wcscmp(key, kvp->key))
126                                 return kvp->value;
127                         
128                         linkp = linkp->next;
129                 }while(linkp != mapp->key_value_list);
130         }
131         return NULL;
132 }
133
134 void* nt_map_remove(nt_map_handle handle, const wchar_t *key)
135 {
136         nt_map_tp mapp;
137         nt_link_tp linkp;
138         nt_w_key_value_tp kvp;
139         void *data;
140         assert(handle);
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;
145                 do{
146                         kvp = (nt_w_key_value_tp)linkp->data;
147                         if(0 == wcscmp(key, kvp->key)){
148                                 data = kvp->value;
149                                 mapp->key_value_list = nt_link_remove2(
150                                                         mapp->key_value_list, linkp);
151                                 free(linkp);
152                                 free(kvp->key);
153                                 free(kvp);
154                                 return data;
155                         }
156                         linkp = linkp->next;
157                 }while(linkp != mapp->key_value_list);
158         }
159         return NULL;
160 }
161
162 int nt_map_get_count(nt_map_handle handle)
163 {
164         nt_map_tp mapp;
165         assert(handle);
166         assert(handle->chk_sum == NT_MAP_CHK_SUM);
167         mapp = (nt_map_tp)handle;
168         if(!mapp->key_value_list)
169                 return 0;
170         return nt_link_num(mapp->key_value_list);
171 }
172
173 nt_link_tp nt_map_get_values(nt_map_handle handle)
174 {
175         nt_map_tp mapp;
176         assert(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;
181         
182         rlinkp = NULL;
183         
184         if(mapp->key_value_list){
185                 linkp = mapp->key_value_list;
186                 do{
187                         kvp = (nt_w_key_value_tp)linkp->data;
188                         wlinkp = nt_link_add_data(rlinkp, kvp->value);
189                         if(wlinkp && !rlinkp)
190                                 rlinkp = wlinkp;
191                         linkp = linkp->next;
192                 }while(linkp != mapp->key_value_list);
193         }
194         return rlinkp;
195 }
196
197 nt_enum_handle nt_enum_set(nt_link_tp linkp)
198 {
199         nt_enum_tp enump;
200         
201         enump = malloc(sizeof(nt_enum_t));
202         if(!enump)
203                 return NULL;
204         enump->handle.chk_sum = NT_ENUM_CHK_SUM;
205         
206         enump->source = linkp;
207         enump->current = NULL;
208         enump->free_func = NULL;
209         return (nt_enum_handle)enump;
210 }
211
212 void nt_enum_set_free_func(nt_enum_handle handle, nt_memfree_fn free_func)
213 {
214         nt_enum_tp enump;
215         enump = (nt_enum_tp)handle;
216         assert(enump);
217         assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
218         enump->free_func =      free_func;
219 }
220
221
222 void nt_enum_reset(nt_enum_handle handle)
223 {
224         nt_enum_tp enump;
225         enump = (nt_enum_tp)handle;
226         assert(enump);
227         assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
228         enump->current = NULL;
229 }
230
231 void nt_enum_unset(nt_enum_handle handle)
232 {
233         nt_enum_tp enump;
234         enump = (nt_enum_tp)handle;
235         assert(enump);
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);
239         }
240         free(enump);
241 }
242
243 void* nt_enum_fetch(nt_enum_handle handle)
244 {
245         nt_enum_tp enump;
246         void *data;
247         
248         enump = (nt_enum_tp)handle;
249         assert(enump);
250         assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
251         
252         if(!enump->source)
253                 return NULL;
254         
255         if(!enump->current){
256                 data = enump->source->data;
257                 enump->current = enump->source->next;
258                 return data;
259         }
260         
261         if(enump->source == enump->current){
262                 return NULL;
263         }
264         
265         data = enump->current->data;
266         enump->current = enump->current->next;
267         return data;
268 }
269
270 int nt_enum_get_count(nt_enum_handle handle)
271 {
272         nt_enum_tp enump;
273         enump = (nt_enum_tp)handle;
274         assert(enump);
275         assert(enump->handle.chk_sum == NT_ENUM_CHK_SUM);
276         if(!enump->source)
277                 return 0;
278         return nt_link_num(enump->source);
279 }
280
281 nt_link_tp nt_link_insert_before(nt_link_tp top_linkp,
282                 nt_link_tp dest, nt_link_tp src)
283 {
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;
289                 return src;
290         }
291
292         src->next = dest;
293         src->prev = dest->prev;
294         src->prev->next = src;
295         src->next->prev = src;
296
297         return top_linkp;
298 }
299
300 nt_link_tp nt_link_add_last(nt_link_tp top_linkp, nt_link_tp src)
301 {
302         nt_link_tp old_last;
303         
304         if(!top_linkp)
305                 return src;
306         
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;
312         return top_linkp;
313 }
314
315 void nt_link_sort(nt_link_tp *top_linkp, nt_compare_fn comp_func)
316 {
317         nt_link_tp cur_linkp, next_linkp, work_linkp;
318
319         cur_linkp = *top_linkp;
320         do{
321                 next_linkp = cur_linkp->next;
322                 work_linkp = *top_linkp;
323
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);
329                                 break;
330                         }
331                         work_linkp = work_linkp->next;
332                 }
333                 cur_linkp = next_linkp;
334         }while(cur_linkp != *top_linkp);
335
336 }
337
338 void nt_link_n_sort(nt_link_tp *top_linkp, nt_compare_n_fn comp_func)
339 {
340         nt_link_tp cur_linkp, next_linkp, work_linkp;
341
342         cur_linkp = *top_linkp;
343         do{
344                 next_linkp = cur_linkp->next;
345                 work_linkp = *top_linkp;
346
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);
352                                 break;
353                         }
354                         work_linkp = work_linkp->next;
355                 }
356                 cur_linkp = next_linkp;
357         }while(cur_linkp != *top_linkp);
358
359 }
360
361 int nt_link_num(nt_link_tp linkp){
362         nt_link_tp curp;
363         int num = 1;
364         assert(linkp);
365         assert(linkp->next);
366         curp= linkp->next;
367         while(curp != linkp){
368                 num++;
369                 curp = curp->next;
370         }
371         return num;
372 }
373
374 void* nt_link_get_by_index(nt_link_tp linkp, int index){
375         nt_link_tp curp;
376         int i = 0;
377         assert(linkp);
378         assert(linkp->next);
379         if(index == 0)
380                 return linkp->data;
381         curp= linkp->next;
382         while(curp != linkp){
383                 i++;
384                 if(i == index)
385                         return curp->data;
386                 curp = curp->next;
387         }
388         return NULL;
389 }
390
391 nt_link_tp nt_link_add_data(nt_link_tp link, void *data)
392 {
393         nt_link_tp ptr = malloc(sizeof(nt_link_t));
394         if(ptr == NULL)
395                 return NULL;
396
397         ptr->data = data;
398         
399         if(link != NULL){
400                 ptr->prev = link->prev;
401                 ptr->prev->next = ptr;
402                 link->prev = ptr;
403                 ptr->next = link;
404         }else{
405                 ptr->prev = ptr;
406                 ptr->next = ptr;
407         }
408         return ptr;
409 }
410
411 nt_link_tp nt_link_add_n_data(nt_link_tp link, int n_data)
412 {
413         nt_link_tp ptr = calloc(1,sizeof(nt_link_t));
414         if(ptr == NULL)
415                 return NULL;
416
417         ptr->n_data = n_data;
418         
419         if(link != NULL){
420                 ptr->prev = link->prev;
421                 ptr->prev->next = ptr;
422                 link->prev = ptr;
423                 ptr->next = link;
424         }else{
425                 ptr->prev = ptr;
426                 ptr->next = ptr;
427         }
428         return ptr;
429 }
430
431 nt_link_tp nt_link_remove(nt_link_tp src, nt_link_tp target)
432 {
433         while(src != target){
434                 if(src->next == target){
435                         src->next = target->next;
436                         target->next->prev = src;
437                         return target;
438                 }
439                 src = src->next;
440         }
441         return target;
442 }
443
444 nt_link_tp nt_link_remove2(nt_link_tp top_linkp, nt_link_tp target)
445 {
446         nt_link_tp new_top_linkp, prev, next;
447
448         if(top_linkp == target){
449                 if(top_linkp == top_linkp->next)
450                         return NULL;
451                 new_top_linkp = top_linkp->next;
452         }else{
453                 new_top_linkp = top_linkp;
454         }
455         prev = target->prev;
456         next = target->next;
457         prev->next = next;
458         next->prev = prev;
459
460         return new_top_linkp;
461 }
462
463 nt_link_tp nt_link_remove_by_data(nt_link_tp link, void *data)
464 {
465         nt_link_tp ptr = link;
466         do{
467                 if(ptr->data  == data){
468                         ptr->prev->next = ptr->next;
469                         ptr->next->prev = ptr->prev;
470                         return ptr;
471                 }
472                 ptr++;
473         }while(ptr != link);
474
475         return NULL;
476 }
477
478 void* nt_link_get(nt_link_tp link)
479 {
480         return link->data;
481 }
482
483 nt_link_tp nt_link_find(nt_link_tp link, void *data, 
484                                         nt_compare_fn comp_func)
485 {
486         nt_link_tp ptr = link;
487         do{
488                 if(0 == (comp_func)(ptr->data, data)){
489                         return ptr;
490                 }
491                 ptr = ptr->next;
492         }while(ptr != link);
493
494         return NULL;
495
496 }
497
498 nt_link_tp nt_link_next(nt_link_tp link)
499 {
500         return link->next;
501 }
502
503 nt_link_tp nt_link_copy(nt_link_tp src_linkp, nt_memcopy_fn copy_func)
504 {
505         nt_link_tp srcp, resultp, workp;
506         void *ptr;
507         
508         assert(src_linkp);
509         
510         srcp = src_linkp;
511         resultp = NULL;
512         do{
513                 if(!copy_func){
514                         workp = nt_link_add_data(resultp, srcp->data);
515                 }else{
516                         ptr = (copy_func)(srcp->data);
517                         if(ptr)
518                                 workp = nt_link_add_data(resultp, ptr);
519                         else
520                                 workp = NULL;
521                 }
522                 if(!workp){
523                         if(resultp)
524                                 nt_all_link_free(resultp, NULL);
525                         return NULL;
526                 }
527                 if(!resultp)
528                         resultp = workp;
529                 srcp = srcp->next;
530         }while(srcp != src_linkp);
531         return resultp;
532 }
533
534 void* nt_link_strcpy_fnc(void *ptr)
535 {
536         char *cptr, *p;
537         int len;
538         cptr = (char*)ptr;
539         len = strlen(cptr);
540         p = malloc(len+1);
541         if(!p)
542                 return NULL;
543         strcpy(p, cptr);
544         return p;
545 }
546 void* nt_link_wcscpy_fnc(void *ptr)
547 {
548         wchar_t *cptr, *p;
549         int len;
550         cptr = (wchar_t*)ptr;
551         len = wcslen(cptr);
552         p = malloc((len+1)*sizeof(wchar_t));
553         if(!p)
554                 return NULL;
555         wcscpy(p, cptr);
556         return p;
557 }
558
559 int nt_link_wcscmp_fnc(void *lhs, void *rhs)
560 {
561         return wcscmp((const wchar_t *)lhs, (const wchar_t *)rhs);
562 }
563
564
565 void nt_all_link_free(nt_link_tp ptr, nt_memfree_fn free_func)
566 {
567         nt_link_tp linkp;
568         nt_link_tp tmp_linkp;
569         assert(ptr);
570
571         linkp = ptr;
572         do{
573                 if(linkp->data && free_func)
574                         (free_func)(linkp->data);
575                 tmp_linkp = linkp;      
576                 linkp = linkp->next;
577                 free(tmp_linkp);
578         }while(ptr != linkp);
579 }
580
581 nt_key_value_tp nt_key_value_alloc(char *key, char *value)
582 {
583         nt_key_value_tp ptr = malloc(sizeof(nt_key_value_t));
584         if(ptr == NULL)
585                 return NULL;
586         ptr->key = key;
587         ptr->value = value;
588         return ptr;
589 }
590
591 nt_w_key_value_tp nt_w_key_value_alloc(const wchar_t *key, void *value)
592 {
593         nt_w_key_value_tp ptr = malloc(sizeof(nt_w_key_value_t));
594         if(ptr == NULL)
595                 return NULL;
596         ptr->key = nt_w_str_clone(key);
597         if(!ptr->key){
598                 free(ptr);
599                 return NULL;
600         }
601         ptr->value = value;
602         return ptr;
603 }
604
605 void* nt_stack_add_last(nt_stack_tp stackp, void* data)
606 {
607         int cursor;
608         nt_link_tp linkp;
609
610         assert(stackp);
611         if(!stackp->linkp){
612                 return NULL;
613         }
614         linkp = stackp->linkp;
615         cursor = 0;
616         do{
617                 /* If there are data after the cursor, 
618                  * then do nothing. 
619                  */
620                 if(cursor > stackp->cursor){
621                         return NULL;
622                 }
623                 linkp = linkp->next;
624                 cursor++;
625         }while(linkp != stackp->linkp);
626
627         linkp = nt_link_add_data(stackp->linkp, data);
628         if(!linkp)
629                 return NULL;
630         /* This special case we do not increment cursor */
631         /* stackp->cursor++;*/
632         return data;
633 }
634
635 void* nt_stack_push(nt_stack_tp stackp, void* data)
636 {
637         int cursor;
638         nt_link_tp saved_linkp, linkp;
639
640         assert(stackp);
641         if(!stackp->linkp){
642                 linkp = nt_link_add_data(stackp->linkp, data);
643                 if(!linkp)
644                         return NULL;
645                 stackp->linkp = linkp;
646                 stackp->cursor = 0;
647                 return data;
648         }
649         linkp = stackp->linkp;
650         cursor = 0;
651         do{
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;
657
658                         linkp->prev = saved_linkp;
659                         saved_linkp->next = linkp;
660
661                         /* Now the linkp is dangling */
662                         if(!stackp->unlinkedp){
663                                 stackp->unlinkedp = linkp;
664                         }else{
665                                 saved_linkp = stackp->unlinkedp->prev;
666                                 stackp->unlinkedp->prev = linkp->prev;
667                                 saved_linkp->next = linkp;
668                                 linkp->prev = saved_linkp;
669                         }
670                         break;
671                 }
672                 linkp = linkp->next;
673                 cursor++;
674         }while(linkp != stackp->linkp);
675
676         linkp = nt_link_add_data(stackp->linkp, data);
677         if(!linkp)
678                 return NULL;
679         stackp->cursor++;
680         return data;
681 }
682
683 void* nt_stack_pop(nt_stack_tp stackp)
684 {
685         int cursor;
686         nt_link_tp linkp;
687         assert(stackp);
688         if(!stackp->linkp)
689                 return NULL;
690         linkp = stackp->linkp;
691         cursor = 0;
692         do{
693                 if(cursor == stackp->cursor){
694                         stackp->cursor--;
695                         if(stackp->cursor < 0){
696                                 stackp->cursor++;
697                         }
698                         return linkp->data;
699                 }
700                 linkp = linkp->next;
701                 cursor++;
702         }while(linkp != stackp->linkp);
703         return NULL;
704 }
705
706 void* nt_stack_peek(nt_stack_tp stackp)
707 {
708         int cursor;
709         nt_link_tp linkp;
710         assert(stackp);
711         if(!stackp->linkp)
712                 return NULL;
713         linkp = stackp->linkp;
714         cursor = 0;
715         do{
716                 if(cursor == stackp->cursor){
717                         return linkp->data;
718                 }
719                 linkp = linkp->next;
720                 cursor++;
721         }while(linkp != stackp->linkp);
722         return NULL;
723 }
724 int nt_stack_get_position(nt_stack_tp stackp)
725 {
726         return stackp->cursor;
727 }
728
729 BOOL nt_stack_is_empty(nt_stack_tp stackp)
730 {
731         return (!stackp->linkp);
732 }
733
734 void* nt_stack_cursor_next(nt_stack_tp stackp)
735 {
736         int cursor;
737         nt_link_tp linkp;
738         assert(stackp);
739         if(!stackp->linkp)
740                 return NULL;
741         linkp = stackp->linkp;
742         cursor = 0;
743         do{
744                 if(cursor > (stackp->cursor+1)){
745                         stackp->cursor++;
746                         return linkp->data;
747                 }
748                 linkp = linkp->next;
749                 cursor++;
750         }while(linkp != stackp->linkp);
751         return NULL;
752 }
753
754 nt_stack_tp nt_stack_alloc()
755 {
756         nt_stack_tp stackp = malloc(sizeof(nt_stack_t));
757         if(!stackp)
758                 return NULL;
759
760         stackp->cursor = -1;
761         stackp->linkp = NULL;
762         stackp->unlinkedp = NULL;
763         
764         return stackp;
765 }
766
767
768 void nt_stack_free(nt_stack_tp ptr, nt_memfree_fn free_func)
769 {
770         assert(ptr);
771
772         if(!free_func){
773                 free(ptr);
774                 return;
775         }
776         if(ptr->linkp){
777                 nt_all_link_free(ptr->linkp, free_func);
778         }
779         if(ptr->unlinkedp){
780                 nt_all_link_free(ptr->unlinkedp, free_func);
781         }
782         free(ptr);      
783 }
784
785 nt_queue_handle nt_queue_alloc()
786 {
787         nt_queue_tp ptr;
788         ptr = malloc(sizeof(nt_queue_t));
789         if(!ptr)
790                 return NULL;
791         ptr->linkp = NULL;
792         ptr->handle.chk_sum = NT_QUEUE_CHK_SUM;
793         return &ptr->handle;
794 }
795 void nt_queue_free(nt_queue_handle handle, nt_memfree_fn free_func)
796 {
797         nt_queue_tp queuep;
798         
799         assert(handle);
800         assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
801         queuep = (nt_queue_tp)handle;
802         if(queuep->linkp){
803                 nt_all_link_free(queuep->linkp, free_func);
804         }
805         free(queuep);
806 }
807
808 BOOL nt_queue_push(nt_queue_handle handle, void* data)
809 {
810         nt_link_tp linkp;
811         nt_queue_tp queuep;
812         
813         assert(handle);
814         assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
815         queuep = (nt_queue_tp)handle;
816         
817         linkp = nt_link_add_data(queuep->linkp, data);
818         if(!linkp)
819                 return FALSE;
820         
821         if(!queuep->linkp)
822                 queuep->linkp = linkp;
823         return TRUE;
824 }
825 void* nt_queue_shift(nt_queue_handle handle)
826 {
827         nt_link_tp linkp, prev, next;
828         nt_queue_tp queuep;
829         void *data;
830         
831         assert(handle);
832         assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
833         queuep = (nt_queue_tp)handle;
834         
835         if(!queuep->linkp)
836                 return NULL;
837         
838         linkp = queuep->linkp;
839         if(linkp == linkp->next){
840                 data = linkp->data;
841                 free(linkp);
842                 queuep->linkp = NULL;
843                 return data;
844         }
845         
846         prev = linkp->prev;
847         next = linkp->next;
848         
849         prev->next = next;
850         next->prev = prev;
851         queuep->linkp = next;
852         data = linkp->data;
853         free(linkp);
854         return data;
855 }
856
857 int nt_queue_get_count(nt_queue_handle handle)
858 {
859         nt_queue_tp queuep;
860         
861         assert(handle);
862         assert(handle->chk_sum == NT_QUEUE_CHK_SUM);
863         queuep = (nt_queue_tp)handle;
864         
865         if(!queuep->linkp)
866                 return 0;
867         return nt_link_num(queuep->linkp);
868 }
869
870