Algorithmique Numérique Distribuée Public GIT Repository
2 #include <vector.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
8 #include <stdio.h>
10 #ifdef _MSC_VER
11 #define inline _inline
12 #endif
14 static inline int
15 resize(vector_t vector)
16 {
17         return vector_reserve(vector, !(vector->capacity) ? 1 : (vector->size) << 1);
18 }
20 static inline int
21 move(vector_t vector, int dst,int src, int size)
22 {
23         return (NULL != memmove(vector->items + dst, vector->items + src,size * sizeof(void*)));
24 }
26 vector_t
27 vector_new(int capacity, fn_finalize_t fn_finalize)
28 {
29         vector_t vector;
31         if(capacity < 0)
32         {
33                 errno = EINVAL;
34                 return NULL;
35         }
37         if(!(vector = (vector_t)calloc(1,sizeof(s_vector_t))))
38                 return NULL;
40         if(capacity)
41         {
42                 if(!(vector->items = (void**)calloc(capacity,sizeof(void*))))
43                 {
44                         free(vector);
45                         return NULL;
46                 }
48                 vector->capacity = capacity;
49         }
51         vector->fn_finalize = fn_finalize;
52         vector->pos = -1;
53         return vector;
54 }
56 int
57 vector_clear(vector_t vector)
58 {
59         int rv;
61         if(!vector)
62             return EINVAL;
64         if(!vector->size)
65                 return 0;
67         if(vector->fn_finalize)
68         {
69                 int size = vector->size;
70                 fn_finalize_t fn_finalize = vector->fn_finalize;
71                 void** items = vector->items;
72                 register int pos;
74                 for(pos = 0; pos < size; pos++)
75                 {
76                         if((rv = (*(fn_finalize))(&(items[pos]))))
77                                 return rv;
78                         else
79                                 vector->size--;
80                 }
81         }
82         else
83         {
84                 vector->size = 0;
85         }
87         vector->pos = -1;
89         return 0;
90 }
92 int
93 vector_free(vector_t* vector_ptr)
94 {
95         int rv;
97     if(!(*vector_ptr))
98         return EINVAL;
100         if((rv = vector_clear(*vector_ptr)))
101                 return rv;
103         free(*vector_ptr);
104         *vector_ptr = NULL;
106         return 0;
107 }
109 int
110 vector_is_empty(vector_t vector)
111 {
112         if(!vector)
113         {
114             errno = EINVAL;
115             return 0;
116         }
118         return !vector->size;
119 }
121 int
122 vector_get_size(vector_t vector)
123 {
124     if(!vector)
125     {
126         errno = EINVAL;
127         return -1;
128     }
130         return vector->size;
131 }
133 void*
134 vector_get_front(vector_t vector)
135 {
136         if(!vector)
137     {
138         errno = EINVAL;
139         return NULL;
140     }
142     if(!vector->size)
143     {
144         errno = EAGAIN;
145         return NULL;
146     }
148         return vector->items[0];
149 }
151 void*
152 vector_get_back(vector_t vector)
153 {
154         if(!vector)
155     {
156         errno = EINVAL;
157         return NULL;
158     }
160     if(!vector->size)
161     {
162         errno = EAGAIN;
163         return NULL;
164     }
166         return vector->items[vector->size - 1];
167 }
169 int
170 vector_get_capacity_available(vector_t vector)
171 {
172     if(!vector)
173     {
174         errno = EINVAL;
175         return -1;
176     }
178         return (vector->capacity - vector->size);
179 }
181 int
182 vector_push_back(vector_t vector, void* item)
183 {
184         int rv;
186         if(!vector || !item)
187         return EINVAL;
189         /* if all capacity is used, resize the vector */
190         if(vector->capacity <= vector->size)
191         {
192                 if((rv = resize(vector)))
193                         return rv;
194         }
196         /* increment the item count and push the new item at the end of the vector */
197         vector->items[++(vector->size) - 1] = item;
199         vector->pos = -1;
202         return 0;
203 }
205 void*
206 vector_pop_back(vector_t vector)
207 {
208     if(!vector)
209     {
210         errno = EINVAL;
211         return NULL;
212     }
214     if(!vector->size)
215     {
216         errno = EAGAIN;
217         return NULL;
218     }
220         vector->pos = -1;
222         return vector->items[(vector->size)-- - 1];
223 }
225 int
226 vector_get_upper_bound(vector_t vector)
227 {
228         if(!vector)
229     {
230         errno = EINVAL;
231         return -1;
232     }
234     if(!vector->size)
235     {
236         errno = EAGAIN;
237         return -1;
238     }
240         return (vector->size - 1);
241 }
243 void*
244 vector_set_at(vector_t vector, int pos, void* item)
245 {
246         void* prev_item;
248         if(!vector)
249     {
250         errno = EINVAL;
251         return NULL;
252     }
254         if(!vector->size)
255         {
256                 errno = EAGAIN;
257                 return NULL;
258         }
260         if((pos < 0) || (pos >= vector->size))
261         {
262                 errno = ERANGE;
263                 return NULL;
264         }
266         prev_item = vector->items[pos];
267         vector->items[pos] = item;
268         return prev_item;
269 }
271 int
272 vector_insert(vector_t vector, int pos, void* item)
273 {
274         int rv;
276         if(!vector)
277         return EINVAL;
279         if(!vector->size)
280         {
281                 errno = EAGAIN;
282                 return 0;
283         }
285         if((pos < 0) || (pos >= vector->size))
286         {
287                 errno = ERANGE;
288                 return 0;
289         }
291         if(vector->size >= vector->capacity)
292         {
293                 if((rv = resize(vector)))
294                         return rv;
295         }
297         if(vector->size)
298         {
299                 if(!move(vector, pos + 1, pos, vector->size - pos))
300                     return errno;
301     }
303         vector->size++;
304         vector->items[pos] = item;
305         vector->pos = -1;
307         return 0;
308 }
310 int
311 vector_erase_at(vector_t vector, int pos)
312 {
313         int rv;
315         if(!vector)
316         return EINVAL;
318     if(!vector->size)
319         {
320                 errno = EAGAIN;
321                 return 0;
322         }
324         if((pos < 0) || (pos >= vector->size))
325         {
326                 errno = ERANGE;
327                 return 0;
328         }
330         if(vector->fn_finalize)
331         {
332                 if((rv = (*(vector->fn_finalize))(&(vector->items[pos]))))
333                         return rv;
334         }
336         if(pos != (vector->size - 1))
337         {
338                 if(!move(vector, pos, pos + 1, (vector->size - (pos + 1))))
339                     return errno;
340         }
342         vector->size--;
343         vector->pos = -1;
345         return 0;
346 }
348 int
349 vector_erase(vector_t vector, void* item)
350 {
351         int pos, rv;
353         if(!vector || !item)
354                 return EINVAL;
356         if(!vector->size)
357                 return EAGAIN;
359         if(-1 == (pos = vector_search(vector,item)))
360                 return errno;
362         if(vector->fn_finalize)
363         {
364                 if((rv = (*(vector->fn_finalize))(&item)))
365                         return rv;
366         }
368         if(pos != (vector->size - 1))
369                 if(!move(vector, pos, pos + 1, (vector->size - (pos + 1))))
370                         return errno;
372         vector->size--;
374         vector->pos = -1;
376         return 0;
377 }
379 int
380 vector_erase_range(vector_t vector, int first, int last)
381 {
382         register int width;
383         int rv;
385         if(!vector || first >= last)
386                 return EINVAL;
388         if(vector->size < 2)
389                 return EAGAIN;
391         if((first < 0) || (last < 0) || (last >= vector->size))
392                 return ERANGE;
394         width = (last - first) + 1;
396         while(width--)
397         {
398                 if((rv = vector_erase_at(vector,first)))
399                         return rv;
400         }
402         return 0;
403 }
405 int
406 vector_search(vector_t vector, void* item)
407 {
408         register int pos;
409         void** items;
410         int size;
412         if(!vector || !item)
413         {
414                 errno = EINVAL;
415                 return -1;
416         }
418         if(!vector->size)
419         {
420                 errno = EAGAIN;
421                 return -1;
422         }
424         vector = (vector_t)vector;
426         items = vector->items;
427         size = vector->size;
429         for(pos = 0 ; pos < size; pos++)
430         {
431                 if(items[pos] == item)
432                         return pos;
433         }
435         errno = ESRCH;
436         return -1;
437 }
439 int
440 vector_remove(vector_t vector, void* item)
441 {
442         int pos;
444         if(!vector || !item)
445                 return EINVAL;
447         if(!vector->size)
448                 return EAGAIN;
450         if(-1 == (pos = vector_search(vector,item)))
451                 return errno;
453         if(pos != (vector->size - 1))
454                 if(!move(vector, pos, pos + 1, (vector->size - (pos + 1))))
455                         return errno;
457         vector->size--;
459         vector->pos = -1;
461         return 0;
462 }
464 int
465 vector_assign(vector_t dst,vector_t src)
466 {
467         register int pos;
468         int size;
469         void** items;
470         int rv;
473         if(!dst || !src ||(dst == src))
474                 return EINVAL;
476         if(!src->size)
477                 return EAGAIN;
479         size = src->size;
481         /* if the destination vector has not enough capacity resize it */
482         if(size > dst->capacity)
483         {
484                 if((rv = vector_reserve(dst, size - dst->capacity)))
485                         return rv;
486         }
488         /* clear the destination vector */
489         if((rv = vector_clear(dst)))
490                 return rv;
492         dst->fn_finalize = NULL;
494         items = src->items;
496         /* file the destination vector */
497         for(pos = 0; pos < size; pos++)
498                  if((rv = vector_push_back(dst,items[pos])))
499                         return rv;
501         dst->pos = -1;
503         return 0;
504 }
506 int
507 vector_get_capacity(vector_t vector)
508 {
509         if(!vector)
510         {
511                 errno = EINVAL;
512                 return -1;
513         }
515         return vector->capacity;
516 }
518 int
519 vector_equals(vector_t first, vector_t second)
520 {
521         register int pos;
522         int size;
523         void** __first, ** __second;
526         if(!first || !second || (first == second))
527         {
528                 errno = EINVAL;
529                 return 0;
530         }
532         if(first->size != second->size)
533                 return 0;
535         size = first->size;
536         __first = first->items;
537         __second = second->items;
539         for(pos = 0; pos < size; pos++)
540         {
541                 if(__first[pos] != __second[pos])
542                         return 0;
543         }
545         return 1;
546 }
548 vector_t
549 vector_clone(vector_t vector)
550 {
551         int size;
552         register int pos;
553         void** dst,** src;
554         vector_t clone;
556         if(!vector)
557         {
558                 errno = EINVAL;
559                 return NULL;
560         }
562         clone = vector_new(vector->capacity,NULL);
564         if(!clone)
565             return NULL;
567         size = vector->size;
568         src = vector->items;
569         dst = clone->items;
571         for(pos = 0; pos < size; pos++)
572                 dst[pos] = src[pos];
574         clone->size = size;
576         return clone;
577 }
579 int
580 vector_contains(vector_t vector,void* item)
581 {
582         if(!vector || !item)
583         {
584                 errno = EINVAL;
585                 return 0;
586         }
588         return (-1 != vector_search(vector,item));
589 }
591 int
592 vector_swap(vector_t first,vector_t second)
593 {
594         s_vector_t tmp;
596         if(!first || !second)
597                 return EINVAL;
599         /* save the content or first */
600         tmp = *first;
602         /* copy second in first */
603         if(!memcpy(first, second, sizeof(s_vector_t)))
604             return 0;
606         /* copy tmp in first */
607         if(!memcpy(second, &tmp, sizeof(s_vector_t)))
608         {
609                 *first = tmp;
610             return 0;
611         }
613         return 1;
614 }
616 int
617 vector_reserve(vector_t vector, int size)
618 {
619         void** items;
621         if(!vector || (size < 0))
622                 return EINVAL;
624         if(vector->capacity >= size)
625                 return EAGAIN;
627         if(!(items = (void**)realloc(vector->items, size * sizeof(void*))))
628                 return errno;
631         vector->capacity = size;
632         vector->items = items;
634         return 0;
635 }
637 int
638 vector_is_autodelete(vector_t vector)
639 {
640         if(!vector)
641         {
642                 errno = EINVAL;
643                 return 0;
644         }
646         return NULL != vector->fn_finalize;
647 }
649 int
650 vector_has_capacity_available(vector_t vector)
651 {
652         if(!vector)
653         {
654                 errno = EINVAL;
655                 return 0;
656         }
658         return (vector->capacity > vector->size);
659 }
661 int
662 vector_is_full(vector_t vector)
663 {
664         if(!vector)
665     {
666         errno = EINVAL;
667         return 0;
668     }
671         return (vector->capacity == vector->size);
672 }
674 int
675 vector_get_max_index(vector_t vector)
676 {
678         if(!vector)
679         {
680                 errno = EINVAL;
681                 return -1;
682         }
685         return vector->size - 1;
686 }
688 void*
689 vector_get(vector_t vector)
690 {
691         if(!vector)
692         {
693                 errno = EINVAL;
694                 return NULL;
695         }
697         if(!vector->size || (-1 == vector->pos))
698         {
699                 errno = EAGAIN;
700                 return NULL;
701         }
702         return vector->items[vector->pos];
703 }
705 void*
706 vector_get_at(vector_t vector, int pos)
707 {
708         if(!vector)
709         {
710                 errno = EINVAL;
711                 return NULL;
712         }
714         if(pos < 0 || pos >= vector->size)
715         {
716                 errno = ERANGE;
717                 return NULL;
718         }
720         if(!vector->size)
721         {
722                 errno = EAGAIN;
723                 return NULL;
724         }
727         return vector->items[pos];
728 }
730 int
731 vector_getpos(vector_t vector, int* pos)
732 {
734         if(!vector || !pos)
735         {
736                 errno = EINVAL;
737                 return 0;
738         }
740         if(!vector->size || (-1 == vector->pos))
741         {
742                 errno = EAGAIN;
743                 return 0;
744         }
746         *pos = vector->pos;
747         return 1;
748 }
750 int
751 vector_move_next(vector_t vector)
752 {
753         if(!vector)
754         {
755                 errno = EINVAL;
756                 return 0;
757         }
759         if(!vector->size || (-1 == vector->pos))
760         {
761                 errno = EAGAIN;
762                 return 0;
763         }
765         if(vector->pos < (vector->size - 1))
766         {
767                 vector->pos++;
768                 return 1;
769         }
771         vector->pos = -1;
772         errno = ERANGE;
773         return 0;
774 }
776 int
777 vector_move_prev(vector_t vector)
778 {
779         if(!vector)
780         {
781                 errno = EINVAL;
782                 return 0;
783         }
785         if(!vector->size  || (-1 == vector->pos))
786         {
787                 errno = EAGAIN;
788                 return 0;
789         }
791         if(vector->pos > 0)
792         {
793                 vector->pos--;
794                 return 1;
795         }
797         vector->pos = -1;
798         errno = ERANGE;
799         return 0;
801 }
803 int
804 vector_rewind(vector_t vector)
805 {
806         if(!vector)
807         {
808                 errno = EINVAL;
809                 return 0;
810         }
812         if(!vector->size)
813         {
814                 errno = EAGAIN;
815                 return 0;
816         }
818         vector->pos = 0;
820         return 1;
821 }
823 static int
824 seek_set(vector_t vector, int offset)
825 {
826         if(offset > vector->size)
827                 return EINVAL;
829         vector_rewind(vector);
831         while(offset--)
832                 vector_move_next(vector);
834         return 0;
835 }
837 static int
838 seek_end(vector_t vector, int offset)
839 {
840         if(offset > vector->size)
841                 return EINVAL;
843         vector_unwind(vector);
845         while(offset--)
846                 vector_move_prev(vector);
848         return 0;
849 }
852 static int
853 seek_cur(vector_t vector, int offset)
854 {
855         if(vector->pos == 0)
856         {
857                 /* we are at the begin of the vector */
858                 seek_set(vector, offset);
859         }
860         else if(vector->pos == vector->size - 1)
861         {
862                 /* we are at the end of the vector */
863                 seek_end(vector, offset);
864         }
865         else
866         {
867                 if(offset > (vector->size - vector->pos + 1))
868                         return EINVAL;
870                 while(offset--)
871                         vector_move_next(vector);
873         }
875         return 0;
876 }
878 int
879 vector_seek(vector_t vector, int offset, int whence)
880 {
881         if(!vector)
882                 return EINVAL;
884         if(!vector->size)
885                 return EAGAIN;
887         switch(whence)
888         {
889                 case SEEK_SET :
890                 return seek_set(vector, offset);
892                 case SEEK_CUR :
893                 return seek_cur(vector, offset);
895                 case SEEK_END :
896                 return seek_end(vector, offset);
898         }
900         return EINVAL;
901 }
903 void*
904 vector_set(vector_t vector, void* item)
905 {
906         void* prev_item;
908         if(!vector || !item)
909         {
910                 errno = EINVAL;
911                 return NULL;
912         }
914         if(!vector->size  || (-1 == vector->pos))
915         {
916                 errno = EAGAIN;
917                 return NULL;
918         }
920         prev_item = vector->items[vector->pos];
921         vector->items[vector->pos] = item;
923         return prev_item;
924 }
926 int
927 vector_setpos(vector_t vector, int pos)
928 {
929         if(!vector)
930         {
931                 errno = EINVAL;
932                 return 0;
933         }
935         if(pos < 0 || pos >= vector->size)
936         {
937                 errno = ERANGE;
938                 return 0;
939         }
941         if(!vector->size)
942         {
943                 errno = EAGAIN;
944                 return 0;
945         }
947         vector->pos = pos;
948         return 1;
949 }
951 int
952 vector_tell(vector_t vector)
953 {
954         if(!vector)
955         {
956                 errno = EINVAL;
957                 return -1;
958         }
960         if(!vector->size || (-1 == vector->pos))
961         {
962                 errno = EAGAIN;
963                 return -1;
964         }
966         return vector->pos;
967 }
969 int
970 vector_unwind(vector_t vector)
971 {
972         if(!vector)
973         {
974                 errno = EINVAL;
975                 return 0;
976         }
978         if(!vector->size)
979         {
980                 errno = EAGAIN;
981                 return 0;
982         }
984         vector->pos = vector->size - 1;
985         return 1;
986 }