graphics updates
[voxelands-alt.git] / src / lib / array.c
blob370d3933c61761b80c865d300d04f79d5d7dd070
1 /************************************************************************
2 * array.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "array.h"
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
27 /* initialises an array - useful for those created on the stack */
28 void array_init(array_t *a, uint32_t type)
30 a->type = type;
31 a->length = 0;
32 a->size = 0;
33 a->data = NULL;
36 /* create a new array of type */
37 array_t *array_create(uint32_t type)
39 array_t *a;
41 a = malloc(sizeof(array_t));
42 a->type = type;
43 a->length = 0;
44 a->size = 0;
45 a->data = NULL;
47 return a;
50 /* create a new array as a copy of a */
51 array_t *array_copy(array_t *a)
53 array_t *r = array_create(ARRAY_TYPE_STRING);
55 if (a) {
56 int i;
57 r->type = a->type;
58 switch (a->type) {
59 case ARRAY_TYPE_STRING:
60 for (i=0; i<a->length; i++) {
61 array_push_string(r,((char**)(a->data))[i]);
63 break;
64 case ARRAY_TYPE_FLOAT:
65 for (i=0; i<a->length; i++) {
66 array_push_float(r,((float*)(a->data))[i]);
68 break;
69 case ARRAY_TYPE_INT:
70 for (i=0; i<a->length; i++) {
71 array_push_int(r,((uint32_t*)(a->data))[i]);
73 break;
74 case ARRAY_TYPE_PTR:
75 for (i=0; i<a->length; i++) {
76 array_push_ptr(r,((unsigned char**)(a->data))[i]);
78 break;
79 default:;
83 return r;
86 /* compare two arrays */
87 int array_cmp(array_t *a1, array_t *a2)
89 int i;
90 char** c1;
91 char** c2;
92 int *i1;
93 int *i2;
94 float *f1;
95 float *f2;
96 if (!a1 || !a2)
97 return -1;
98 if (a1->length != a2->length)
99 return -1;
101 if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_STRING) {
102 c1 = a1->data;
103 c2 = a2->data;
104 for (i=0; i<a1->length; i++) {
105 if (!c1[i] || !c2[i] || strcmp(c1[i],c2[i]))
106 return 1;
108 }else if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_INT) {
109 c1 = a1->data;
110 i2 = a2->data;
111 for (i=0; i<a1->length; i++) {
112 if (!c1[i] || i2[i] != strtol(c1[i],NULL,10))
113 return 1;
115 }else if (a1->type == ARRAY_TYPE_STRING && a2->type == ARRAY_TYPE_FLOAT) {
116 c1 = a1->data;
117 f2 = a2->data;
118 for (i=0; i<a1->length; i++) {
119 if (!c1[i] || f2[i] != strtof(c1[i],NULL))
120 return 1;
122 }else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_STRING) {
123 i1 = a1->data;
124 c2 = a2->data;
125 for (i=0; i<a1->length; i++) {
126 if (!c2[i] || i1[i] != strtol(c2[i],NULL,10))
127 return 1;
129 }else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_STRING) {
130 f1 = a1->data;
131 c2 = a2->data;
132 for (i=0; i<a1->length; i++) {
133 if (!c2[i] || f1[i] != strtof(c2[i],NULL))
134 return 1;
136 }else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_INT) {
137 i1 = a1->data;
138 i2 = a2->data;
139 for (i=0; i<a1->length; i++) {
140 if (i1[i] != i2[i])
141 return 1;
143 }else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_FLOAT) {
144 f1 = a1->data;
145 f2 = a2->data;
146 for (i=0; i<a1->length; i++) {
147 if (f1[i] != f2[i])
148 return 1;
150 }else if (a1->type == ARRAY_TYPE_INT && a2->type == ARRAY_TYPE_FLOAT) {
151 i1 = a1->data;
152 f2 = a2->data;
153 for (i=0; i<a1->length; i++) {
154 if (i1[i] != (int)f2[i])
155 return 1;
157 }else if (a1->type == ARRAY_TYPE_FLOAT && a2->type == ARRAY_TYPE_INT) {
158 f1 = a1->data;
159 i2 = a2->data;
160 for (i=0; i<a1->length; i++) {
161 if ((int)f1[i] != i2[i])
162 return 1;
164 }else if (a1->type == ARRAY_TYPE_PTR && a2->type == ARRAY_TYPE_PTR) {
165 c1 = a1->data;
166 c2 = a2->data;
167 for (i=0; i<a1->length; i++) {
168 if (c1[i] != c2[i])
169 return 1;
173 return 0;
176 /* destroy an array */
177 void array_free(array_t *a, int freestruct)
179 int i;
180 if (!a)
181 return;
182 if (a->type == ARRAY_TYPE_STRING) {
183 char** p = a->data;
184 for (i=0; i<a->length; i++ ) {
185 if (p[i])
186 free(p[i]);
189 free(a->data);
190 if (freestruct)
191 free(a);
194 /* push an int onto an array */
195 int array_push_int(array_t *a, uint32_t v)
197 uint32_t *p;
198 if (a->type == ARRAY_TYPE_STRING) {
199 char sv[20];
200 sprintf(sv,"%u",v);
201 return array_push_string(a,sv);
202 }else if (a->type == ARRAY_TYPE_FLOAT) {
203 return array_push_float(a,(float)v);
204 }else if (a->type != ARRAY_TYPE_INT) {
205 return 1;
208 a->length++;
210 p = a->data;
212 if (a->size < a->length) {
213 p = realloc(a->data,sizeof(uint32_t)*a->length);
214 if (!p) {
215 a->length--;
216 return 1;
218 a->size = a->length;
221 p[a->length-1] = v;
222 a->data = p;
224 return 0;
227 /* push a float onto an array */
228 int array_push_float(array_t *a, float v)
230 float *p;
231 if (a->type == ARRAY_TYPE_STRING) {
232 char sv[20];
233 sprintf(sv,"%f",v);
234 return array_push_string(a,sv);
235 }else if (a->type == ARRAY_TYPE_INT) {
236 return array_push_int(a,(int)v);
237 }else if (a->type != ARRAY_TYPE_FLOAT) {
238 return 1;
241 a->length++;
243 p = a->data;
245 if (a->size < a->length) {
246 p = realloc(a->data,sizeof(float)*a->length);
247 if (!p) {
248 a->length--;
249 return 1;
251 a->size = a->length;
254 p[a->length-1] = v;
255 a->data = p;
257 return 0;
260 /* push a string onto an array */
261 int array_push_string(array_t *a, char* v)
263 char** p;
264 if (a->type != ARRAY_TYPE_STRING)
265 return 1;
267 a->length++;
269 p = a->data;
271 if (a->size < a->length) {
272 p = realloc(a->data,sizeof(char*)*a->length);
273 if (!p) {
274 a->length--;
275 return 1;
277 a->size = a->length;
280 if (v) {
281 p[a->length-1] = strdup(v);
282 }else{
283 p[a->length-1] = NULL;
285 a->data = p;
287 return 0;
290 /* push a pointer onto an array */
291 int array_push_ptr(array_t *a, void *v)
293 char** p;
294 if (a->type != ARRAY_TYPE_PTR)
295 return 1;
297 a->length++;
299 p = a->data;
301 if (a->size < a->length) {
302 p = realloc(a->data,sizeof(char*)*a->length);
303 if (!p)
304 return 1;
305 a->size = a->length;
308 p[a->length-1] = v;
310 a->data = p;
312 return 0;
315 /* push a colour onto an array */
316 int array_push_colour(array_t *a, colour_t *c)
318 int r = 0;
319 r += array_push_float(a,((float)c->r)/255.0);
320 r += array_push_float(a,((float)c->g)/255.0);
321 r += array_push_float(a,((float)c->b)/255.0);
322 r += array_push_float(a,((float)c->a)/255.0);
323 return r;
326 /* push a v3_t onto an array */
327 int array_push_v3t(array_t *a, v3_t *v)
329 int r = 0;
330 r += array_push_float(a,v->x);
331 r += array_push_float(a,v->y);
332 r += array_push_float(a,v->z);
333 return r;
336 /* push a v2_t onto an array */
337 int array_push_v2t(array_t *a, v2_t *v)
339 int r = 0;
340 r += array_push_float(a,v->x);
341 r += array_push_float(a,v->y);
342 return r;
345 /* set the value of array index i to an int value */
346 int array_set_int(array_t *a, uint32_t v, int i)
348 uint32_t *p = a->data;
349 if (a->type == ARRAY_TYPE_STRING) {
350 char sv[20];
351 sprintf(sv,"%u",v);
352 return array_set_string(a,sv,i);
353 }else if (a->type == ARRAY_TYPE_FLOAT) {
354 return array_set_float(a,(float)v,i);
355 }else if (a->type != ARRAY_TYPE_INT) {
356 return 1;
359 if (a->size <= i) {
360 int k;
361 int l = i+1;
363 p = realloc(a->data,sizeof(uint32_t)*l);
364 if (!p)
365 return 1;
366 for (k=a->length; k<l; k++) {
367 p[k] = 0;
369 a->data = p;
370 a->size = l;
373 if (a->length <= i)
374 a->length = i+1;
376 p[i] = v;
378 return 0;
381 /* set the value of array index i to a float value */
382 int array_set_float(array_t *a, float v, int i)
384 float *p = a->data;
385 if (a->type == ARRAY_TYPE_STRING) {
386 char sv[20];
387 sprintf(sv,"%f",v);
388 return array_set_string(a,sv,i);
389 }else if (a->type == ARRAY_TYPE_INT) {
390 return array_set_float(a,(uint32_t)v,i);
391 }else if (a->type != ARRAY_TYPE_FLOAT) {
392 return 1;
395 if (a->size <= i) {
396 int k;
397 int l = i+1;
399 p = realloc(a->data,sizeof(float)*l);
400 if (!p)
401 return 1;
402 for (k=a->length; k<l; k++) {
403 p[k] = 0.0;
405 a->data = p;
406 a->size = l;
408 if (a->length <= i)
409 a->length = i+1;
411 p[i] = v;
413 return 0;
416 /* set the value of array index i to a string value */
417 int array_set_string(array_t *a, char* v, int i)
419 char** p = a->data;
420 if (a->type != ARRAY_TYPE_STRING)
421 return 1;
423 if (a->size <= i) {
424 int k;
425 int l = i+1;
427 p = realloc(a->data,sizeof(char*)*l);
428 if (!p)
429 return 1;
430 for (k=a->length; k<l; k++) {
431 p[k] = NULL;
433 a->data = p;
434 a->size = l;
436 if (a->length <= i)
437 a->length = i+1;
439 if (v) {
440 p[i] = strdup(v);
441 }else{
442 p[i] = NULL;
445 return 0;
448 /* set the value of array index i to a ponter value */
449 int array_set_ptr(array_t *a, void* v, int i)
451 char** p = a->data;
452 if (a->type != ARRAY_TYPE_PTR)
453 return 1;
455 if (a->size <= i) {
456 int k;
457 int l = i+1;
459 p = realloc(a->data,sizeof(char*)*l);
460 if (!p)
461 return 1;
462 for (k=a->length; k<l; k++) {
463 p[k] = NULL;
465 a->data = p;
466 a->size = l;
468 if (a->length <= i)
469 a->length = i+1;
471 p[i] = v;
473 return 0;
476 /* pop an int off the top of an array */
477 uint32_t array_pop_int(array_t *a)
479 if (a->type == ARRAY_TYPE_INT) {
480 if (!a->length)
481 return 0;
482 a->length--;
483 return ((uint32_t*)(a->data))[a->length];
484 }else if (a->type == ARRAY_TYPE_FLOAT) {
485 float v = array_pop_float(a);
486 return (uint32_t)v;
487 }else if (a->type == ARRAY_TYPE_STRING) {
488 uint32_t v;
489 char* s = array_pop_string(a);
490 v = strtol(s,NULL,10);
491 free(s);
492 return v;
494 return 0;
497 /* pop a float off the top of an array */
498 float array_pop_float(array_t *a)
500 if (a->type == ARRAY_TYPE_FLOAT) {
501 if (!a->length)
502 return 0;
503 a->length--;
504 return ((float*)(a->data))[a->length];
505 }else if (a->type == ARRAY_TYPE_INT) {
506 uint32_t v = array_pop_int(a);
507 return (float)v;
508 }else if (a->type == ARRAY_TYPE_STRING) {
509 float v;
510 char* s = array_pop_string(a);
511 v = strtof(s,NULL);
512 free(s);
513 return v;
515 return 0.0;
518 /* pop a string off the top of an array */
519 char* array_pop_string(array_t *a)
521 if (a->type == ARRAY_TYPE_FLOAT) {
522 float v = array_pop_float(a);
523 char sv[20];
524 if (!a->length)
525 return NULL;
526 sprintf(sv,"%f",v);
527 return strdup(sv);
528 }else if (a->type == ARRAY_TYPE_INT) {
529 uint32_t v = array_pop_int(a);
530 char sv[20];
531 if (!a->length)
532 return NULL;
533 sprintf(sv,"%u",v);
534 return strdup(sv);
535 }else if (a->type == ARRAY_TYPE_STRING) {
536 if (!a->length)
537 return NULL;
538 a->length--;
539 return ((char**)(a->data))[a->length];
541 return NULL;
544 /* pop a pointer off the top of an array */
545 void *array_pop_ptr(array_t *a)
547 if (a->type == ARRAY_TYPE_PTR && a->length) {
548 a->length--;
549 return ((char**)(a->data))[a->length];
551 return NULL;
554 /* get an int value from an array */
555 uint32_t array_get_int(array_t *a, int i)
557 if (a->type == ARRAY_TYPE_INT) {
558 if (a->length <= i)
559 return 0;
560 return ((uint32_t*)(a->data))[i];
561 }else if (a->type == ARRAY_TYPE_FLOAT) {
562 float v = array_get_float(a,i);
563 return (uint32_t)v;
564 }else if (a->type == ARRAY_TYPE_STRING) {
565 uint32_t v;
566 char* s = array_get_string(a,i);
567 v = strtol(s,NULL,10);
568 free(s);
569 return v;
571 return 0;
574 /* get a float value from an array */
575 float array_get_float(array_t *a, int i)
577 if (a->type == ARRAY_TYPE_FLOAT) {
578 if (a->length <= i)
579 return 0.0;
580 return ((float*)(a->data))[i];
581 }else if (a->type == ARRAY_TYPE_INT) {
582 uint32_t v = array_get_int(a,i);
583 return (float)v;
584 }else if (a->type == ARRAY_TYPE_STRING) {
585 float v;
586 char* s = array_get_string(a,i);
587 v = strtof(s,NULL);
588 free(s);
589 return v;
591 return 0.0;
594 /* get a string value from an array */
595 char* array_get_string(array_t *a, int i)
597 if (a->type == ARRAY_TYPE_FLOAT) {
598 float v = array_get_float(a,i);
599 char sv[20];
600 sprintf(sv,"%f",v);
601 return strdup(sv);
602 }else if (a->type == ARRAY_TYPE_INT) {
603 uint32_t v = array_get_int(a,i);
604 char sv[20];
605 sprintf(sv,"%u",v);
606 return strdup(sv);
607 }else if (a->type == ARRAY_TYPE_STRING) {
608 if (a->length <= i)
609 return NULL;
610 return ((char**)(a->data))[i];
612 return NULL;
615 /* get a pointer from an array */
616 void *array_get_ptr(array_t *a, int i)
618 if (a->type == ARRAY_TYPE_PTR && a->length > i) {
619 return ((char**)(a->data))[i];
621 return NULL;
624 /* find the index of an int value in an array */
625 int array_find_int(array_t *a, uint32_t v)
627 if (a->type == ARRAY_TYPE_INT) {
628 int i;
629 uint32_t *p = a->data;
630 for (i=0; i<a->length; i++) {
631 if (p[i] == v)
632 return i;
635 return -1;
638 /* find the index of a float value in an array */
639 int array_find_float(array_t *a, float v)
641 if (a->type == ARRAY_TYPE_FLOAT) {
642 int i;
643 float *p = a->data;
644 for (i=0; i<a->length; i++) {
645 if (p[i] == v)
646 return i;
649 return -1;
652 /* find the index of a string value in an array */
653 int array_find_string(array_t *a, char* v)
655 if (a->type == ARRAY_TYPE_STRING) {
656 int i;
657 char** p = a->data;
658 for (i=0; i<a->length; i++) {
659 if (!strcmp(p[i],v))
660 return i;
663 return -1;
666 /* find the index of a pointer in an array */
667 int array_find_ptr(array_t *a, void *v)
669 if (a->type == ARRAY_TYPE_PTR) {
670 int i;
671 unsigned char* cv = v;
672 unsigned char** p = a->data;
673 for (i=0; i<a->length; i++) {
674 if (p[i] == cv)
675 return i;
678 return -1;
681 /* remove a string value from an array */
682 int array_remove_string(array_t *a, char* v)
684 if (a->type == ARRAY_TYPE_STRING) {
685 int i;
686 char** p = a->data;
687 for (i=0; i<a->length; i++) {
688 if (!strcmp(p[i],v)) {
689 free(p[i]);
690 break;
693 a->length--;
694 for (; i<a->length; i++) {
695 p[i] = p[i+1];
697 return 0;
699 return 1;
702 /* split a string into an array, at a separator character */
703 /* TODO: if strings is non-zero, then don't split within "" or '' */
704 /* TODO: utf8 support */
705 array_t *array_split(char* str, char* s, int strings)
707 char buff[1024];
708 int i;
709 int o = 0;
710 int l;
711 array_t *r;
713 if (!str)
714 return NULL;
716 r = array_create(ARRAY_TYPE_STRING);
718 l = strlen(s);
720 for (i=0; str[i]; i++) {
721 if (!strncmp(str+i,s,l)) {
722 buff[o] = 0;
723 array_push_string(r,buff);
724 o = 0;
725 i += l-1;
726 continue;
728 buff[o++] = str[i];
730 buff[o] = 0;
731 array_push_string(r,buff);
733 return r;
736 /* join an array into a string, using a glue character */
737 char* array_join(array_t *a, char* glue, int start)
739 char* str = NULL;
740 int l = 0;
741 if (!glue)
742 glue = " ";
743 if (a->type == ARRAY_TYPE_STRING) {
744 int i;
745 int gl = strlen(glue);
746 for (i=start; i<a->length; i++) {
747 l += strlen(((char**)(a->data))[i])+gl;
749 if (l) {
750 str = malloc(l+1);
751 str[0] = 0;
752 for (i=start; i<a->length; i++) {
753 if (i > start)
754 strcat(str,glue);
755 strcat(str,((char**)(a->data))[i]);
760 return str;