some meshgen and map rendering updates
[voxelands-alt.git] / src / lib / array.c
bloba13d08940be37ff9d5467c890b730707045438f3
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);
192 return;
195 a->data = NULL;
196 a->size = 0;
197 a->length = 0;
200 /* push an int onto an array */
201 int array_push_int(array_t *a, uint32_t v)
203 uint32_t *p;
204 if (a->type == ARRAY_TYPE_STRING) {
205 char sv[20];
206 sprintf(sv,"%u",v);
207 return array_push_string(a,sv);
208 }else if (a->type == ARRAY_TYPE_FLOAT) {
209 return array_push_float(a,(float)v);
210 }else if (a->type != ARRAY_TYPE_INT) {
211 return 1;
214 a->length++;
216 p = a->data;
218 if (a->size < a->length) {
219 p = realloc(a->data,sizeof(uint32_t)*a->length);
220 if (!p) {
221 a->length--;
222 return 1;
224 a->size = a->length;
227 p[a->length-1] = v;
228 a->data = p;
230 return 0;
233 /* push a float onto an array */
234 int array_push_float(array_t *a, float v)
236 float *p;
237 if (a->type == ARRAY_TYPE_STRING) {
238 char sv[20];
239 sprintf(sv,"%f",v);
240 return array_push_string(a,sv);
241 }else if (a->type == ARRAY_TYPE_INT) {
242 return array_push_int(a,(int)v);
243 }else if (a->type != ARRAY_TYPE_FLOAT) {
244 return 1;
247 a->length++;
249 p = a->data;
251 if (a->size < a->length) {
252 p = realloc(a->data,sizeof(float)*a->length);
253 if (!p) {
254 a->length--;
255 return 1;
257 a->size = a->length;
260 p[a->length-1] = v;
261 a->data = p;
263 return 0;
266 /* push a string onto an array */
267 int array_push_string(array_t *a, char* v)
269 char** p;
270 if (a->type != ARRAY_TYPE_STRING)
271 return 1;
273 a->length++;
275 p = a->data;
277 if (a->size < a->length) {
278 p = realloc(a->data,sizeof(char*)*a->length);
279 if (!p) {
280 a->length--;
281 return 1;
283 a->size = a->length;
286 if (v) {
287 p[a->length-1] = strdup(v);
288 }else{
289 p[a->length-1] = NULL;
291 a->data = p;
293 return 0;
296 /* push a pointer onto an array */
297 int array_push_ptr(array_t *a, void *v)
299 char** p;
300 if (a->type != ARRAY_TYPE_PTR)
301 return 1;
303 a->length++;
305 p = a->data;
307 if (a->size < a->length) {
308 p = realloc(a->data,sizeof(char*)*a->length);
309 if (!p) {
310 a->length--;
311 return 1;
313 a->size = a->length;
316 p[a->length-1] = v;
318 a->data = p;
320 return 0;
323 /* push a colour onto an array */
324 int array_push_colour(array_t *a, colour_t *c)
326 int r = 0;
327 r += array_push_float(a,((float)c->r)/255.0);
328 r += array_push_float(a,((float)c->g)/255.0);
329 r += array_push_float(a,((float)c->b)/255.0);
330 r += array_push_float(a,((float)c->a)/255.0);
331 return r;
334 /* push a v3_t onto an array */
335 int array_push_v3t(array_t *a, v3_t *v)
337 int r = 0;
338 r += array_push_float(a,v->x);
339 r += array_push_float(a,v->y);
340 r += array_push_float(a,v->z);
341 return r;
344 /* push a v2_t onto an array */
345 int array_push_v2t(array_t *a, v2_t *v)
347 int r = 0;
348 r += array_push_float(a,v->x);
349 r += array_push_float(a,v->y);
350 return r;
353 /* set the value of array index i to an int value */
354 int array_set_int(array_t *a, uint32_t v, int i)
356 uint32_t *p = a->data;
357 if (a->type == ARRAY_TYPE_STRING) {
358 char sv[20];
359 sprintf(sv,"%u",v);
360 return array_set_string(a,sv,i);
361 }else if (a->type == ARRAY_TYPE_FLOAT) {
362 return array_set_float(a,(float)v,i);
363 }else if (a->type != ARRAY_TYPE_INT) {
364 return 1;
367 if (a->size <= i) {
368 int k;
369 int l = i+1;
371 p = realloc(a->data,sizeof(uint32_t)*l);
372 if (!p)
373 return 1;
374 for (k=a->length; k<l; k++) {
375 p[k] = 0;
377 a->data = p;
378 a->size = l;
381 if (a->length <= i)
382 a->length = i+1;
384 p[i] = v;
386 return 0;
389 /* set the value of array index i to a float value */
390 int array_set_float(array_t *a, float v, int i)
392 float *p = a->data;
393 if (a->type == ARRAY_TYPE_STRING) {
394 char sv[20];
395 sprintf(sv,"%f",v);
396 return array_set_string(a,sv,i);
397 }else if (a->type == ARRAY_TYPE_INT) {
398 return array_set_float(a,(uint32_t)v,i);
399 }else if (a->type != ARRAY_TYPE_FLOAT) {
400 return 1;
403 if (a->size <= i) {
404 int k;
405 int l = i+1;
407 p = realloc(a->data,sizeof(float)*l);
408 if (!p)
409 return 1;
410 for (k=a->length; k<l; k++) {
411 p[k] = 0.0;
413 a->data = p;
414 a->size = l;
416 if (a->length <= i)
417 a->length = i+1;
419 p[i] = v;
421 return 0;
424 /* set the value of array index i to a string value */
425 int array_set_string(array_t *a, char* v, int i)
427 char** p = a->data;
428 if (a->type != ARRAY_TYPE_STRING)
429 return 1;
431 if (a->size <= i) {
432 int k;
433 int l = i+1;
435 p = realloc(a->data,sizeof(char*)*l);
436 if (!p)
437 return 1;
438 for (k=a->length; k<l; k++) {
439 p[k] = NULL;
441 a->data = p;
442 a->size = l;
444 if (a->length <= i)
445 a->length = i+1;
447 if (v) {
448 p[i] = strdup(v);
449 }else{
450 p[i] = NULL;
453 return 0;
456 /* set the value of array index i to a ponter value */
457 int array_set_ptr(array_t *a, void* v, int i)
459 char** p = a->data;
460 if (a->type != ARRAY_TYPE_PTR)
461 return 1;
463 if (a->size <= i) {
464 int k;
465 int l = i+1;
467 p = realloc(a->data,sizeof(char*)*l);
468 if (!p)
469 return 1;
470 for (k=a->length; k<l; k++) {
471 p[k] = NULL;
473 a->data = p;
474 a->size = l;
476 if (a->length <= i)
477 a->length = i+1;
479 p[i] = v;
481 return 0;
484 /* pop an int off the top of an array */
485 uint32_t array_pop_int(array_t *a)
487 if (a->type == ARRAY_TYPE_INT) {
488 if (!a->length)
489 return 0;
490 a->length--;
491 return ((uint32_t*)(a->data))[a->length];
492 }else if (a->type == ARRAY_TYPE_FLOAT) {
493 float v = array_pop_float(a);
494 return (uint32_t)v;
495 }else if (a->type == ARRAY_TYPE_STRING) {
496 uint32_t v;
497 char* s = array_pop_string(a);
498 v = strtol(s,NULL,10);
499 free(s);
500 return v;
502 return 0;
505 /* pop a float off the top of an array */
506 float array_pop_float(array_t *a)
508 if (a->type == ARRAY_TYPE_FLOAT) {
509 if (!a->length)
510 return 0;
511 a->length--;
512 return ((float*)(a->data))[a->length];
513 }else if (a->type == ARRAY_TYPE_INT) {
514 uint32_t v = array_pop_int(a);
515 return (float)v;
516 }else if (a->type == ARRAY_TYPE_STRING) {
517 float v;
518 char* s = array_pop_string(a);
519 v = strtof(s,NULL);
520 free(s);
521 return v;
523 return 0.0;
526 /* pop a string off the top of an array */
527 char* array_pop_string(array_t *a)
529 if (a->type == ARRAY_TYPE_FLOAT) {
530 float v = array_pop_float(a);
531 char sv[20];
532 if (!a->length)
533 return NULL;
534 sprintf(sv,"%f",v);
535 return strdup(sv);
536 }else if (a->type == ARRAY_TYPE_INT) {
537 uint32_t v = array_pop_int(a);
538 char sv[20];
539 if (!a->length)
540 return NULL;
541 sprintf(sv,"%u",v);
542 return strdup(sv);
543 }else if (a->type == ARRAY_TYPE_STRING) {
544 if (!a->length)
545 return NULL;
546 a->length--;
547 return ((char**)(a->data))[a->length];
549 return NULL;
552 /* pop a pointer off the top of an array */
553 void *array_pop_ptr(array_t *a)
555 if (a->type == ARRAY_TYPE_PTR && a->length) {
556 a->length--;
557 return ((char**)(a->data))[a->length];
559 return NULL;
562 /* get an int value from an array */
563 uint32_t array_get_int(array_t *a, int i)
565 if (a->type == ARRAY_TYPE_INT) {
566 if (a->length <= i)
567 return 0;
568 return ((uint32_t*)(a->data))[i];
569 }else if (a->type == ARRAY_TYPE_FLOAT) {
570 float v = array_get_float(a,i);
571 return (uint32_t)v;
572 }else if (a->type == ARRAY_TYPE_STRING) {
573 uint32_t v;
574 char* s = array_get_string(a,i);
575 v = strtol(s,NULL,10);
576 free(s);
577 return v;
579 return 0;
582 /* get a float value from an array */
583 float array_get_float(array_t *a, int i)
585 if (a->type == ARRAY_TYPE_FLOAT) {
586 if (a->length <= i)
587 return 0.0;
588 return ((float*)(a->data))[i];
589 }else if (a->type == ARRAY_TYPE_INT) {
590 uint32_t v = array_get_int(a,i);
591 return (float)v;
592 }else if (a->type == ARRAY_TYPE_STRING) {
593 float v;
594 char* s = array_get_string(a,i);
595 v = strtof(s,NULL);
596 free(s);
597 return v;
599 return 0.0;
602 /* get a string value from an array */
603 char* array_get_string(array_t *a, int i)
605 if (a->type == ARRAY_TYPE_FLOAT) {
606 float v = array_get_float(a,i);
607 char sv[20];
608 sprintf(sv,"%f",v);
609 return strdup(sv);
610 }else if (a->type == ARRAY_TYPE_INT) {
611 uint32_t v = array_get_int(a,i);
612 char sv[20];
613 sprintf(sv,"%u",v);
614 return strdup(sv);
615 }else if (a->type == ARRAY_TYPE_STRING) {
616 if (a->length <= i)
617 return NULL;
618 return ((char**)(a->data))[i];
620 return NULL;
623 /* get a pointer from an array */
624 void *array_get_ptr(array_t *a, int i)
626 if (a->type == ARRAY_TYPE_PTR && a->length > i) {
627 return ((char**)(a->data))[i];
629 return NULL;
632 /* find the index of an int value in an array */
633 int array_find_int(array_t *a, uint32_t v)
635 if (a->type == ARRAY_TYPE_INT) {
636 int i;
637 uint32_t *p = a->data;
638 for (i=0; i<a->length; i++) {
639 if (p[i] == v)
640 return i;
643 return -1;
646 /* find the index of a float value in an array */
647 int array_find_float(array_t *a, float v)
649 if (a->type == ARRAY_TYPE_FLOAT) {
650 int i;
651 float *p = a->data;
652 for (i=0; i<a->length; i++) {
653 if (p[i] == v)
654 return i;
657 return -1;
660 /* find the index of a string value in an array */
661 int array_find_string(array_t *a, char* v)
663 if (a->type == ARRAY_TYPE_STRING) {
664 int i;
665 char** p = a->data;
666 for (i=0; i<a->length; i++) {
667 if (!strcmp(p[i],v))
668 return i;
671 return -1;
674 /* find the index of a pointer in an array */
675 int array_find_ptr(array_t *a, void *v)
677 if (a->type == ARRAY_TYPE_PTR) {
678 int i;
679 unsigned char* cv = v;
680 unsigned char** p = a->data;
681 for (i=0; i<a->length; i++) {
682 if (p[i] == cv)
683 return i;
686 return -1;
689 /* remove a string value from an array */
690 int array_remove_string(array_t *a, char* v)
692 if (a->type == ARRAY_TYPE_STRING) {
693 int i;
694 char** p = a->data;
695 for (i=0; i<a->length; i++) {
696 if (!strcmp(p[i],v)) {
697 free(p[i]);
698 break;
701 a->length--;
702 for (; i<a->length; i++) {
703 p[i] = p[i+1];
705 return 0;
707 return 1;
710 /* split a string into an array, at a separator character */
711 /* TODO: if strings is non-zero, then don't split within "" or '' */
712 /* TODO: utf8 support */
713 array_t *array_split(char* str, char* s, int strings)
715 char buff[1024];
716 int i;
717 int o = 0;
718 int l;
719 array_t *r;
721 if (!str)
722 return NULL;
724 r = array_create(ARRAY_TYPE_STRING);
726 l = strlen(s);
728 for (i=0; str[i]; i++) {
729 if (!strncmp(str+i,s,l)) {
730 buff[o] = 0;
731 array_push_string(r,buff);
732 o = 0;
733 i += l-1;
734 continue;
736 buff[o++] = str[i];
738 buff[o] = 0;
739 array_push_string(r,buff);
741 return r;
744 /* join an array into a string, using a glue character */
745 char* array_join(array_t *a, char* glue, int start)
747 char* str = NULL;
748 int l = 0;
749 if (!glue)
750 glue = " ";
751 if (a->type == ARRAY_TYPE_STRING) {
752 int i;
753 int gl = strlen(glue);
754 for (i=start; i<a->length; i++) {
755 l += strlen(((char**)(a->data))[i])+gl;
757 if (l) {
758 str = malloc(l+1);
759 str[0] = 0;
760 for (i=start; i<a->length; i++) {
761 if (i > start)
762 strcat(str,glue);
763 strcat(str,((char**)(a->data))[i]);
768 return str;