Algorithmique Numérique Distribuée Public GIT Repository
ca8f8907dec2a1564066b692a568d8507f59eda0
2 #include <vector.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
8 #ifdef _MSC_VER
9 #define inline _inline
10 #endif
12 static inline int
13 resize(vector_t vector)
14 {
15         return vector_reserve(vector, !(vector->capacity) ? 1 : (vector->size) << 1);
16 }
18 static inline int
19 move(vector_t vector, int dst,int src, int size)
20 {
21         return (NULL != memmove(vector->items + dst, vector->items + src,size * sizeof(void*)));
22 }
24 vector_t
25 vector_new(int capacity, fn_finalize_t fn_finalize)
26 {
27         vector_t vector;
29         if(capacity < 0)
30         {
31                 errno = EINVAL;
32                 return NULL;
33         }
35         if(!(vector = (vector_t)calloc(1,sizeof(s_vector_t))))
36                 return NULL;
38         if(capacity)
39         {
40                 if(!(vector->items = (void**)calloc(capacity,sizeof(void*))))
41                 {
42                         free(vector);
43                         return NULL;
44                 }
46                 vector->capacity = capacity;
47         }
49         vector->fn_finalize = fn_finalize;
50         vector->pos = -1;
51         return vector;
52 }
54 int
55 vector_clear(vector_t vector)
56 {
57         if(!vector)
58             return EINVAL;
60         if(!vector->size)
61                 return EAGAIN;
63         if(vector->fn_finalize)
64         {
65                 int size = vector->size;
66                 fn_finalize_t fn_finalize = vector->fn_finalize;
67                 void** items = vector->items;
68                 register int pos;
70                 for(pos = 0; pos < size; pos++)
71                 {
72                         if((errno = (*(fn_finalize))(&(items[pos]))))
73                                 return errno;
74                         else
75                                 vector->size--;
76                 }
77         }
78         else
79         {
80                 vector->size = 0;
81         }
83         vector->pos = -1;
85         return 0;
86 }
88 int
89 vector_free(vector_t* vector_ptr)
90 {
91     if(!(*vector_ptr))
92         return EINVAL;
94         if((errno = vector_clear(*vector_ptr)))
95                 return errno;
97         free(*vector_ptr);
98         *vector_ptr = NULL;
100         return 0;
101 }
103 int
104 vector_is_empty(vector_t vector)
105 {
106         if(!vector)
107         {
108             errno = EINVAL;
109             return 0;
110         }
112         return !vector->size;
113 }
115 int
116 vector_get_size(vector_t vector)
117 {
118     if(!vector)
119     {
120         errno = EINVAL;
121         return -1;
122     }
124         return vector->size;
125 }
127 void*
128 vector_get_front(vector_t vector)
129 {
130         if(!vector)
131     {
132         errno = EINVAL;
133         return NULL;
134     }
136     if(!vector->size)
137     {
138         errno = EAGAIN;
139         return NULL;
140     }
142         return vector->items[0];
143 }
145 void*
146 vector_get_back(vector_t vector)
147 {
148         if(!vector)
149     {
150         errno = EINVAL;
151         return NULL;
152     }
154     if(!vector->size)
155     {
156         errno = EAGAIN;
157         return NULL;
158     }
160         return vector->items[vector->size - 1];
161 }
163 int
164 vector_get_capacity_available(vector_t vector)
165 {
166     if(!vector)
167     {
168         errno = EINVAL;
169         return -1;
170     }
172         return (vector->capacity - vector->size);
173 }
175 int
176 vector_push_back(vector_t vector, void* item)
177 {
178         if(!vector || !item)
179         return EINVAL;
182         /* if all capacity is used, resize the vector */
183         if(vector->capacity <= vector->size)
184         {
185                 if(!resize(vector))
186                         return errno;
187         }
189         /* increment the item count and push the new item at the end of the vector */
190         vector->items[++(vector->size) - 1] = item;
192         vector->pos = -1;
194         return 0;
195 }
197 void*
198 vector_pop_back(vector_t vector)
199 {
200     if(!vector)
201     {
202         errno = EINVAL;
203         return NULL;
204     }
206     if(!vector->size)
207     {
208         errno = EAGAIN;
209         return NULL;
210     }
212         vector->pos = -1;
214         return vector->items[(vector->size)-- - 1];
215 }
217 int
218 vector_get_upper_bound(vector_t vector)
219 {
220         if(!vector)
221     {
222         errno = EINVAL;
223         return -1;
224     }
226     if(!vector->size)
227     {
228         errno = EAGAIN;
229         return -1;
230     }
232         return (vector->size - 1);
233 }
235 void*
236 vector_set_at(vector_t vector, int pos, void* item)
237 {
238         void* prev_item;
240         if(!vector)
241     {
242         errno = EINVAL;
243         return NULL;
244     }
246         if(!vector->size)
247         {
248                 errno = EAGAIN;
249                 return NULL;
250         }
252         if((pos < 0) || (pos >= vector->size))
253         {
254                 errno = ERANGE;
255                 return NULL;
256         }
258         prev_item = vector->items[pos];
259         vector->items[pos] = item;
260         return prev_item;
261 }
263 int
264 vector_insert(vector_t vector, int pos, void* item)
265 {
266         if(!vector)
267         return EINVAL;
269         if(!vector->size)
270         {
271                 errno = EAGAIN;
272                 return 0;
273         }
275         if((pos < 0) || (pos >= vector->size))
276         {
277                 errno = ERANGE;
278                 return 0;
279         }
281         if(vector->size >= vector->capacity)
282         {
283                 if(!resize(vector))
284                         return errno;
285         }
287         if(vector->size)
288         {
289                 if(!move(vector, pos + 1, pos, vector->size - pos))
290                     return errno;
291     }
293         vector->size++;
294         vector->items[pos] = item;
295         vector->pos = -1;
297         return 0;
298 }
300 int
301 vector_erase_at(vector_t vector, int pos)
302 {
303         if(!vector)
304         return EINVAL;
306     if(!vector->size)
307         {
308                 errno = EAGAIN;
309                 return 0;
310         }
312         if((pos < 0) || (pos >= vector->size))
313         {
314                 errno = ERANGE;
315                 return 0;
316         }
318         if(vector->fn_finalize)
319         {
320                 if((errno = (*(vector->fn_finalize))(&(vector->items[pos]))))
321                         return errno;
322         }
324         if(pos != (vector->size - 1))
325         {
326                 if(!move(vector, pos, pos + 1, (vector->size - (pos + 1))))
327                     return errno;
328         }
330         vector->size--;
331         vector->pos = -1;
333         return 0;
334 }
336 int
337 vector_erase(vector_t vector, void* item)
338 {
339         int pos;
341         if(!vector || !item)
342                 return EINVAL;
344         if(!vector->size)
345                 return EAGAIN;
347         if(-1 == (pos = vector_search(vector,item)))
348                 return errno;
350         if(vector->fn_finalize)
351         {
352                 if((errno = (*(vector->fn_finalize))(&item)))
353                         return errno;
354         }
356         if(pos != (vector->size - 1))
357                 if(!move(vector, pos, pos + 1, (vector->size - (pos + 1))))
358                         return errno;
360         vector->size--;
362         vector->pos = -1;
364         return 0;
365 }
367 int
368 vector_erase_range(vector_t vector, int first, int last)
369 {
370         register int width;
372         if(!vector || first >= last)
373                 return EINVAL;
375         if(vector->size < 2)
376                 return EAGAIN;
378         if((first < 0) || (last < 0) || (last >= vector->size))
379                 return ERANGE;
381         width = (last - first) + 1;
383         while(width--)
384         {
385                 if((errno = vector_erase_at(vector,first)))
386                         return errno;
387         }
389         return 0;
390 }
392 int
393 vector_search(vector_t vector, void* item)
394 {
395         register int pos;
396         void** items;
397         int size;
399         if(!vector || !item)
400         {
401                 errno = EINVAL;
402                 return -1;
403         }
405         if(!vector->size)
406         {
407                 errno = EAGAIN;
408                 return -1;
409         }
411         vector = (vector_t)vector;
413         items = vector->items;
414         size = vector->size;
416         for(pos = 0 ; pos < size; pos++)
417         {
418                 if(items[pos] == item)
419                         return pos;
420         }
422         errno = ESRCH;
423         return -1;
424 }
426 int
427 vector_remove(vector_t vector, void* item)
428 {
429         int pos;
431         if(!vector || !item)
432                 return EINVAL;
434         if(!vector->size)
435                 return EAGAIN;
437         if(-1 == (pos = vector_search(vector,item)))
438                 return errno;
440         if(pos != (vector->size - 1))
441                 if(!move(vector, pos, pos + 1, (vector->size - (pos + 1))))
442                         return errno;
444         vector->size--;
446         vector->pos = -1;
448         return 0;
449 }
451 int
452 vector_assign(vector_t dst,vector_t src)
453 {
454         register int pos;
455         int size;
456         void** items;
459         if(!dst || !src ||(dst == src))
460                 return EINVAL;
462         if(!src->size)
463                 return EAGAIN;
465         size = src->size;
467         /* if the destination vector has not enough capacity resize it */
468         if(size > dst->capacity)
469         {
470                 if((errno = vector_reserve(dst, size - dst->capacity)))
471                         return errno;
472         }
474         /* clear the destination vector */
475         if((errno = vector_clear(dst)))
476                 return errno;
478         dst->fn_finalize = NULL;
480         items = src->items;
482         /* file the destination vector */
483         for(pos = 0; pos < size; pos++)
484                  if((errno = vector_push_back(dst,items[pos])))
485                         return errno;
487         dst->pos = -1;
489         return 0;
490 }
492 int
493 vector_get_capacity(vector_t vector)
494 {
495         if(!vector)
496         {
497                 errno = EINVAL;
498                 return -1;
499         }
501         return vector->capacity;
502 }
504 int
505 vector_equals(vector_t first, vector_t second)
506 {
507         register int pos;
508         int size;
509         void** __first, ** __second;
512         if(!first || !second || (first == second))
513         {
514                 errno = EINVAL;
515                 return 0;
516         }
518         if(first->size != second->size)
519                 return 0;
521         size = first->size;
522         __first = first->items;
523         __second = second->items;
525         for(pos = 0; pos < size; pos++)
526         {
527                 if(__first[pos] != __second[pos])
528                         return 0;
529         }
531         return 1;
532 }
534 vector_t
535 vector_clone(vector_t vector)
536 {
537         int size;
538         register int pos;
539         void** dst,** src;
540         vector_t clone;
542         if(!vector)
543         {
544                 errno = EINVAL;
545                 return NULL;
546         }
548         clone = vector_new(vector->capacity,NULL);
550         if(!clone)
551             return NULL;
553         size = vector->size;
554         src = vector->items;
555         dst = clone->items;
557         for(pos = 0; pos < size; pos++)
558                 dst[pos] = src[pos];
560         clone->size = size;
562         return clone;
563 }
565 int
566 vector_contains(vector_t vector,void* item)
567 {
568         if(!vector || !item)
569         {
570                 errno = EINVAL;
571                 return 0;
572         }
574         return (-1 != vector_search(vector,item));
575 }
577 int
578 vector_swap(vector_t first,vector_t second)
579 {
580         s_vector_t tmp;
582         if(!first || !second)
583                 return EINVAL;
585         /* save the content or first */
586         tmp = *first;
588         /* copy second in first */
589         if(!memcpy(first, second, sizeof(s_vector_t)))
590             return 0;
592         /* copy tmp in first */
593         if(!memcpy(second, &tmp, sizeof(s_vector_t)))
594         {
595                 *first = tmp;
596             return 0;
597         }
599         return 1;
600 }
602 int
603 vector_reserve(vector_t vector, int size)
604 {
605         void** items;
607         if(!vector || (size < 0))
608                 return EINVAL;
610         if(vector->capacity >= size)
611                 return EAGAIN;
613         if(!(items = (void**)realloc(vector->items, size * sizeof(void*))))
614                 return errno;
616         vector->capacity = size;
617         vector->items = items;
619         return 0;
620 }
622 int
623 vector_is_autodelete(vector_t vector)
624 {
625         if(!vector)
626         {
627                 errno = EINVAL;
628                 return 0;
629         }
631         return NULL != vector->fn_finalize;
632 }
634 int
635 vector_has_capacity_available(vector_t vector)
636 {
637         if(!vector)
638         {
639                 errno = EINVAL;
640                 return 0;
641         }
643         return (vector->capacity > vector->size);
644 }
646 int
647 vector_is_full(vector_t vector)
648 {
649         if(!vector)
650     {
651         errno = EINVAL;
652         return 0;
653     }
656         return (vector->capacity == vector->size);
657 }
659 int
660 vector_get_max_index(vector_t vector)
661 {
663         if(!vector)
664         {
665                 errno = EINVAL;
666                 return -1;
667         }
670         return vector->size - 1;
671 }
673 void*
674 vector_get(vector_t vector)
675 {
676         if(!vector)
677         {
678                 errno = EINVAL;
679                 return NULL;
680         }
682         if(!vector->size || (-1 == vector->pos))
683         {
684                 errno = EAGAIN;
685                 return NULL;
686         }
687         return vector->items[vector->pos];
688 }
690 void*
691 vector_get_at(vector_t vector, int pos)
692 {
693         if(!vector)
694         {
695                 errno = EINVAL;
696                 return NULL;
697         }
699         if(pos < 0 || pos >= vector->size)
700         {
701                 errno = ERANGE;
702                 return NULL;
703         }
705         if(!vector->size)
706         {
707                 errno = EAGAIN;
708                 return NULL;
709         }
712         return vector->items[pos];
713 }
715 int
716 vector_getpos(vector_t vector, int* pos)
717 {
719         if(!vector || !pos)
720         {
721                 errno = EINVAL;
722                 return 0;
723         }
725         if(!vector->size || (-1 == vector->pos))
726         {
727                 errno = EAGAIN;
728                 return 0;
729         }
731         *pos = vector->pos;
732         return 1;
733 }
735 int
736 vector_move_next(vector_t vector)
737 {
738         if(!vector)
739         {
740                 errno = EINVAL;
741                 return 0;
742         }
744         if(!vector->size || (-1 == vector->pos))
745         {
746                 errno = EAGAIN;
747                 return 0;
748         }
750         if(vector->pos < (vector->size - 1))
751         {
752                 vector->pos++;
753                 return 1;
754         }
756         vector->pos = -1;
757         errno = ERANGE;
758         return 0;
759 }
761 int
762 vector_move_prev(vector_t vector)
763 {
764         if(!vector)
765         {
766                 errno = EINVAL;
767                 return 0;
768         }
770         if(!vector->size  || (-1 == vector->pos))
771         {
772                 errno = EAGAIN;
773                 return 0;
774         }
776         if(vector->pos > 0)
777         {
778                 vector->pos--;
779                 return 1;
780         }
782         vector->pos = -1;
783         errno = ERANGE;
784         return 0;
786 }
788 int
789 vector_rewind(vector_t vector)
790 {
791         if(!vector)
792         {
793                 errno = EINVAL;
794                 return 0;
795         }
797         if(!vector->size)
798         {
799                 errno = EAGAIN;
800                 return 0;
801         }
803         vector->pos = 0;
805         return 1;
806 }
808 static int
809 seek_set(vector_t vector, int offset)
810 {
811         if(offset > vector->size)
812                 return EINVAL;
814         vector_rewind(vector);
816         while(offset--)
817                 vector_move_next(vector);
819         return 0;
820 }
822 static int
823 seek_end(vector_t vector, int offset)
824 {
825         if(offset > vector->size)
826                 return EINVAL;
828         vector_unwind(vector);
830         while(offset--)
831                 vector_move_prev(vector);
833         return 0;
834 }
837 static int
838 seek_cur(vector_t vector, int offset)
839 {
840         if(vector->pos == 0)
841         {
842                 /* we are at the begin of the vector */
843                 seek_set(vector, offset);
844         }
845         else if(vector->pos == vector->size - 1)
846         {
847                 /* we are at the end of the vector */
848                 seek_end(vector, offset);
849         }
850         else
851         {
852                 if(offset > (vector->size - vector->pos + 1))
853                         return EINVAL;
855                 while(offset--)
856                         vector_move_next(vector);
858         }
860         return 0;
861 }
863 int
864 vector_seek(vector_t vector, int offset, int whence)
865 {
866         if(!vector)
867                 return EINVAL;
869         if(!vector->size)
870                 return EAGAIN;
872         switch(whence)
873         {
874                 case SEEK_SET :
875                 return seek_set(vector, offset);
877                 case SEEK_CUR :
878                 return seek_cur(vector, offset);
880                 case SEEK_END :
881                 return seek_end(vector, offset);
883         }
885         return EINVAL;
886 }
888 void*
889 vector_set(vector_t vector, void* item)
890 {
891         void* prev_item;
893         if(!vector || !item)
894         {
895                 errno = EINVAL;
896                 return NULL;
897         }
899         if(!vector->size  || (-1 == vector->pos))
900         {
901                 errno = EAGAIN;
902                 return NULL;
903         }
905         prev_item = vector->items[vector->pos];
906         vector->items[vector->pos] = item;
908         return prev_item;
909 }
911 int
912 vector_setpos(vector_t vector, int pos)
913 {
914         if(!vector)
915         {
916                 errno = EINVAL;
917                 return 0;
918         }
920         if(pos < 0 || pos >= vector->size)
921         {
922                 errno = ERANGE;
923                 return 0;
924         }
926         if(!vector->size)
927         {
928                 errno = EAGAIN;
929                 return 0;
930         }
932         vector->pos = pos;
933         return 1;
934 }
936 int
937 vector_tell(vector_t vector)
938 {
939         if(!vector)
940         {
941                 errno = EINVAL;
942                 return -1;
943         }
945         if(!vector->size || (-1 == vector->pos))
946         {
947                 errno = EAGAIN;
948                 return -1;
949         }
951         return vector->pos;
952 }
954 int
955 vector_unwind(vector_t vector)
956 {
957         if(!vector)
958         {
959                 errno = EINVAL;
960                 return 0;
961         }
963         if(!vector->size)
964         {
965                 errno = EAGAIN;
966                 return 0;
967         }
969         vector->pos = vector->size - 1;
970         return 1;
971 }