diff --git a/src/parser.c b/src/parser.c index 01b01f2..b838c24 100644 --- a/src/parser.c +++ b/src/parser.c @@ -9,7 +9,7 @@ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * @@ -30,17 +30,17 @@ #include "parser.h" +#include "tools/DynamicArray/dynamic_array.h" #include "khash.h" /* hashing */ KHASH_MAP_INIT_STR(__STR__TABLE__, uint32_t) -struct +struct _SP_PARSER_STRUT { - SCItem *items; - uint32_t item_len; - uint32_t index; + GArray items; + uint32_t items_len; khash_t(__STR__TABLE__) *strtable; }; @@ -52,9 +52,14 @@ _SP_PARSER_ITEM void *data; uint32_t name_len; uint32_t type_len; + uint16_t size; uint8_t allocated; uint8_t type; - uint16_t size; +}; + +enum +{ + SC_PARSER_FORMAT_BUFF_FILL_SIZE = 4, }; @@ -159,56 +164,45 @@ __FILE_GET_NEW_LINE(FILE *fr, char *buff, unsigned int bufflength) } } -static const char *const -__SC_GET_FORMAT_FROM_TYPE(const enum SCType t) +static int +__SC_GET_FORMAT_FROM_TYPE_FILL(const enum SCType t, char fill_buff[SC_PARSER_FORMAT_BUFF_FILL_SIZE]) { + + int i = 0; + + fill_buff[i++] = '%'; switch(t) { - case SCTypeNoType: - return NULL; - case SCTypeBOOL: - return "%s"; - case SCTypeCHAR: - return "%c"; - case SCTypeUCHAR: - return "%d"; - case SCTypeSHORT: - return "%d"; - case SCTypeUSHORT: - return "%d"; - case SCTypeINT: - return "%d"; - case SCTypeUINT: - return "%u"; - case SCTypeFLOAT: - return "%f"; - case SCTypeDOUBLE: - return "%lf"; - case SCTypeLONG: - return "%ld"; - case SCTypeULONG: - return "%lu"; - case SCTypeSTRING: - return "%s"; + case SCTypeNoType: return EXIT_FAILURE; + case SCTypeBOOL: fill_buff[i++] = 's'; break; + case SCTypeCHAR: fill_buff[i++] = 'c'; break; + case SCTypeUCHAR: fill_buff[i++] = 'd'; break; + case SCTypeSHORT: fill_buff[i++] = 'd'; break; + case SCTypeUSHORT: fill_buff[i++] = 'd'; break; + case SCTypeINT: fill_buff[i++] = 'd'; break; + case SCTypeUINT: fill_buff[i++] = 'u'; break; + case SCTypeFLOAT: fill_buff[i++] = 'f'; break; + case SCTypeDOUBLE: fill_buff[i++] = 'l'; + fill_buff[i++] = 'f'; break; + case SCTypeLONG: fill_buff[i++] = 'l'; + fill_buff[i++] = 'd'; break; + case SCTypeULONG: fill_buff[i++] = 'l'; + fill_buff[i++] = 'u'; break; + case SCTypeSTRING: fill_buff[i++] = 's'; break; } - return NULL; + return EXIT_SUCCESS; } - -static const char *const -__SC_GET_FORMAT_FROM_SIZE(const size_t size) +static int +__SC_GET_FORMAT_FROM_SIZE_FILL(const size_t size, char fill_buff[SC_PARSER_FORMAT_BUFF_FILL_SIZE]) { switch(size) { - case sizeof(int8_t): - return "%c"; - case sizeof(int16_t): - return "%d"; - case sizeof(int32_t): - return "%f"; - case sizeof(int64_t): - return "%ld"; - } - return "%c"; + default: + case sizeof(uint8_t): return __SC_GET_FORMAT_FROM_TYPE_FILL(SCTypeCHAR, fill_buff); + case sizeof(uint16_t): return __SC_GET_FORMAT_FROM_TYPE_FILL(SCTypeINT, fill_buff); + case sizeof(uint32_t): return __SC_GET_FORMAT_FROM_TYPE_FILL(SCTypeFLOAT, fill_buff); + case sizeof(uint64_t): return __SC_GET_FORMAT_FROM_TYPE_FILL(SCTypeLONG, fill_buff); + } } static const unsigned int @@ -216,34 +210,56 @@ __SC_GET_SIZE_FROM_TYPE(const enum SCType t) { switch(t) { - case SCTypeNoType: - return 0; - case SCTypeBOOL: - return sizeof(uint8_t); - case SCTypeCHAR: - return sizeof(int8_t); - case SCTypeUCHAR: - return sizeof(uint8_t); - case SCTypeSHORT: - return sizeof(int16_t); - case SCTypeUSHORT: - return sizeof(uint16_t); - case SCTypeINT: - return sizeof(int32_t); - case SCTypeUINT: - return sizeof(uint32_t); - case SCTypeFLOAT: - return sizeof(float); - case SCTypeDOUBLE: - return sizeof(double); - case SCTypeLONG: - return sizeof(int64_t); - case SCTypeULONG: - return sizeof(uint64_t); - case SCTypeSTRING: - return 0; - } - return 0; + default: return 0; + case SCTypeSTRING: return 0; + case SCTypeNoType: return 0; + case SCTypeBOOL: return sizeof(uint8_t); + case SCTypeCHAR: return sizeof(int8_t); + case SCTypeUCHAR: return sizeof(uint8_t); + case SCTypeSHORT: return sizeof(int16_t); + case SCTypeUSHORT: return sizeof(uint16_t); + case SCTypeINT: return sizeof(int32_t); + case SCTypeUINT: return sizeof(uint32_t); + case SCTypeFLOAT: return sizeof(float); + case SCTypeDOUBLE: return sizeof(double); + case SCTypeLONG: return sizeof(int64_t); + case SCTypeULONG: return sizeof(uint64_t); + } +} + +static uint32_t +__SC__PARSER__SEARCH__INDEX__( + SCParser *parser, + const char *const NAME, + unsigned int *_NOT_FOUND + ) +{ + uint32_t ret = 0; + if(!parser || !NAME) + { + *_NOT_FOUND = 1; + return 0; + } + khint_t k = kh_get(__STR__TABLE__, parser->strtable, NAME); + khint_t end = kh_end(parser->strtable); + if(k != end) + { return kh_val(parser->strtable, k); + } + else + { + const uint32_t LAST = GArrayEnd(&parser->items); + uint32_t i; + SCItem *item; + for(i = 0; i < LAST; ++i) + { + item = GArrayAt(&parser->items, i); + if(item && !strcmp(item->name, NAME)) + { return i; + } + } + } + *_NOT_FOUND = 1; + return ret; } SCItem * @@ -252,19 +268,18 @@ SCParserSearch( const char *const NAME ) { + void *ret = NULL; if(!parser || !NAME) - { return NULL; + { return ret; } khint_t k = kh_get(__STR__TABLE__, parser->strtable, NAME); khint_t end = kh_end(parser->strtable); if(k != end) { uint32_t index = kh_val(parser->strtable, k); - if(parser->index > index && index >= 0) - { return parser->items + index; - } + ret = GArrayAt(&parser->items, index); } - return NULL; + return ret; } SCItem * @@ -276,12 +291,13 @@ SCParserSearchSlow( if(!parser || !NAME) { return NULL; } + const uint32_t LAST = GArrayEnd(&parser->items); uint32_t i; SCItem *item; - for(i = 0; i < parser->index; ++i) + for(i = 0; i < LAST; ++i) { - item = parser->items + i; - if(!strcmp(item->name, NAME)) + item = GArrayAt(&parser->items, i); + if(item && !strcmp(item->name, NAME)) { return item; } } @@ -304,11 +320,11 @@ SCParserLoad( const char *const TRUE_STRING = "true"; const char *const FALSE_STRING = "false"; - const char *const format = __SC_GET_FORMAT_FROM_TYPE(_optional_type); const int SSCANF_CHECKSUM = 1; const int DATA_SIZE = 32; uint8_t check; uint8_t data[DATA_SIZE]; + char format[SC_PARSER_FORMAT_BUFF_FILL_SIZE]; char *str; /* clear memory */ @@ -324,7 +340,8 @@ SCParserLoad( if(_optional_type == SCTypeBOOL) { goto BOOLTYPE; } - if(!format) + check = __SC_GET_FORMAT_FROM_TYPE_FILL(_optional_type, format); + if(check == EXIT_FAILURE) { goto NOTYPE; } goto SINGLETYPE; @@ -362,7 +379,13 @@ SCParserLoad( } return FAILURE; NOTYPE: - check = sscanf(item->typename, __SC_GET_FORMAT_FROM_SIZE(item->size), data); + check = __SC_GET_FORMAT_FROM_SIZE_FILL(item->size, (char *)format); + if(check == EXIT_SUCCESS) + { check = sscanf(item->typename, format, data); + } + else + { check = !SSCANF_CHECKSUM; + } if(check == SSCANF_CHECKSUM) { memcpy(_return, data, bytescopy); @@ -383,10 +406,11 @@ SCParserWriteVarData( if(!fw || !data) { return EXIT_FAILURE; } - const char *const format = __SC_GET_FORMAT_FROM_TYPE(type); + char format[SC_PARSER_FORMAT_BUFF_FILL_SIZE]; if(type) { + __SC_GET_FORMAT_FROM_TYPE_FILL(type, format); switch(type) { case SCTypeBOOL: @@ -431,19 +455,20 @@ SCParserWriteVarData( } else { + __SC_GET_FORMAT_FROM_SIZE_FILL(size, format); switch(size) { case sizeof(int8_t): - fprintf(fw, __SC_GET_FORMAT_FROM_SIZE(size), *(char *)data); + fprintf(fw, format, *(char *)data); break; case sizeof(int16_t): - fprintf(fw, __SC_GET_FORMAT_FROM_SIZE(size), *(int16_t *)data); + fprintf(fw, format, *(int16_t *)data); break; case sizeof(int32_t): - fprintf(fw, __SC_GET_FORMAT_FROM_SIZE(size), *(float *)data); + fprintf(fw, format, *(float *)data); break; case sizeof(int64_t): - fprintf(fw, __SC_GET_FORMAT_FROM_SIZE(size), *(int64_t *)data); + fprintf(fw, format, *(int64_t *)data); break; } } @@ -487,13 +512,16 @@ SCParserWrite( { return FAILURE; } + const uint32_t END = GArrayEnd(&parser->items); SCItem *item; uint32_t i; - for(i = 0; i < parser->index; ++i) + for(i = 0; i < END; ++i) { - item = parser->items + i; - SCParserWriteVar(fw, item); + item = GArrayAt(&parser->items, i); + if(item) + { SCParserWriteVar(fw, item); + } } fclose(fw); return SUCCESS; @@ -507,22 +535,23 @@ SCParserCreate( SCParser *p = malloc(sizeof(SCParser)); if(p) { + int status; p->strtable = kh_init(__STR__TABLE__); + p->items_len = 0; if(!p->strtable) { free(p); return NULL; } - p->items = malloc(BASE_VAR_COUNT * sizeof(SCItem)); - if(!p->items) + status = GArrayCreateFilled(&p->items, sizeof(SCItem), BASE_VAR_COUNT); + if(status == EXIT_FAILURE) { kh_destroy(__STR__TABLE__, p->strtable); + GArrayWipe(&p->items); free(p); return NULL; } - p->item_len = BASE_VAR_COUNT; - p->index = 0; } return p; } @@ -532,11 +561,15 @@ SCParserDestroy( SCParser *parser ) { + if(!parser) + { return; + } + const uint32_t END = GArrayEnd(&parser->items); uint32_t i; SCItem *item; - for(i = 0; i < parser->index; ++i) + for(i = 0; i < END; ++i) { - item = parser->items + i; + item = GArrayAt(&parser->items, i); if(item->allocated) { free(item->name); } @@ -546,10 +579,59 @@ SCParserDestroy( free(item->data); } kh_destroy(__STR__TABLE__, parser->strtable); - free(parser->items); + GArrayWipe(&parser->items); free(parser); } +SCItem * +SCParserReadLine( + SCParser *parser, + char *buff, + uint32_t buff_length, + char **data_fill + ) +{ + uint32_t namelen; + uint8_t namestatus; + uint32_t typenamelen; + __REMOVE__EXTRAS__STRING(buff, buff_length - 1, &buff_length); + namestatus = __SC__PARSER__NAME(buff, &namelen); + if(namestatus != EXIT_SUCCESS) + { return NULL; + } + + const char saved_char = buff[namelen]; + + buff[namelen] = '\0'; + + SCItem *item; + /* search for item. */ + item = SCParserSearch(parser, buff); + if(!item) + { item = SCParserSearchSlow(parser, buff); + } + buff[namelen] = saved_char; + + if(item && data_fill) + { + namestatus = __SC__PARSER__NAME(buff + namelen + 1, &typenamelen); + if(namestatus == EXIT_SUCCESS) + { + char *data = malloc(typenamelen + 1); + if(data) + { + /* copy buff to data */ + memcpy(data, buff + namelen + 1, typenamelen); + /* set string null byte */ + data[typenamelen] = '\0'; + /* fill data_fill with data pointer */ + memcpy(data_fill, &data, sizeof(void *)); + } + } + } + return item; +} + int SCParserReadFile( SCParser *parser, @@ -573,12 +655,9 @@ SCParserReadFile( const int BUFF_LIMIT = 1024; int running = 1; char buff[BUFF_LIMIT]; - char *name = NULL; char *typename = NULL; - int namestatus = 0; uint32_t bufflenreal = 0; - uint32_t namelen = 0; uint32_t typenamelen = 0; SCItem *item; /* Make sure null byte is set */ @@ -587,37 +666,17 @@ SCParserReadFile( { switch(__FILE_GET_NEW_LINE(fr, buff, BUFF_LIMIT - 1)) { + case ParseOverflow: case ParseSuccess: break; case ParseEOF: running = 0; /* FALLTHROUGH */ - case ParseOverflow: case ParseError: default: continue; } - __REMOVE__EXTRAS__STRING(buff, BUFF_LIMIT - 1, &bufflenreal); - namestatus = __SC__PARSER__NAME(buff, &namelen); - if(namestatus != EXIT_SUCCESS) - { continue; - } - namestatus = __SC__PARSER__NAME(buff + namelen + 1, &typenamelen); - if(namestatus != EXIT_SUCCESS) - { continue; - } - typename = malloc(typenamelen + 1); - if(!typename) - { continue; - } - memcpy(typename, buff + namelen + 1, typenamelen); - typename[typenamelen] = '\0'; - /* assuming its '=' */ - buff[namelen] = '\0'; - item = SCParserSearch(parser, buff); - if(!item) - { item = SCParserSearchSlow(parser, name); - } + item = SCParserReadLine(parser, buff, BUFF_LIMIT, &typename); if(item) { if(item->typename) @@ -629,6 +688,8 @@ SCParserReadFile( else { free(typename); } + + typename = NULL; memset(buff, 0, bufflenreal); } @@ -648,45 +709,33 @@ SCParserNewVar( { const int FAILURE = 1; const int SUCCESS = 0; + char format[SC_PARSER_FORMAT_BUFF_FILL_SIZE]; + int format_status = EXIT_FAILURE; + if(!parser || !VAR_NAME) { return FAILURE; } - if(!size && !__SC_GET_FORMAT_FROM_TYPE(_optional_type)) + format_status = __SC_GET_FORMAT_FROM_TYPE_FILL(_optional_type, format); + if(!size && format_status == EXIT_FAILURE) { return FAILURE; } - /* increase array size if too small */ - if(parser->index >= parser->item_len) - { - const float INCREASE_FACTOR = 1.5f; - const uint32_t newlen = parser->item_len * INCREASE_FACTOR; - void *rec = realloc(parser->items, (newlen) * sizeof(SCItem)); - if(rec) - { - parser->items = rec; - parser->item_len = newlen; - } - else - { return FAILURE; - } - } - - SCItem *item = parser->items + parser->index; + SCItem item; if(_optional_type == SCTypeSTRING) { - item->size = sizeof(char *); - item->type = SCTypeSTRING; + item.size = sizeof(char *); + item.type = SCTypeSTRING; } - else if(__SC_GET_FORMAT_FROM_TYPE(_optional_type)) + else if(format_status == EXIT_SUCCESS) { - item->size = __SC_GET_SIZE_FROM_TYPE(_optional_type); - item->type = _optional_type; + item.size = __SC_GET_SIZE_FROM_TYPE(_optional_type); + item.type = _optional_type; } else if(size) { - item->size = size; - item->type = SCTypeNoType; + item.size = size; + item.type = SCTypeNoType; } else { return FAILURE; @@ -694,26 +743,42 @@ SCParserNewVar( if(READONLY_SECTION) { - item->name = (char *)VAR_NAME; - item->allocated = 0; + item.name = (char *)VAR_NAME; + item.allocated = 0; } else { - item->name = malloc(VAR_NAME_FULL_LENGTH * sizeof(char)); - item->allocated = 1; - if(!item->name) + item.name = malloc(VAR_NAME_FULL_LENGTH * sizeof(char)); + item.allocated = 1; + if(!item.name) { return FAILURE; } - memcpy(item->name, VAR_NAME, VAR_NAME_FULL_LENGTH); + memcpy(item.name, VAR_NAME, VAR_NAME_FULL_LENGTH); + } + item.name_len = VAR_NAME_FULL_LENGTH; + item.data = malloc(item.size); + item.typename = NULL; + item.type_len = 0; + + int status; + if(GArrayEnd(&parser->items) <= parser->items_len) + { status = GArrayPushBack(&parser->items, &item); + } + else + { status = GArrayReplace(&parser->items, &item, parser->items_len); + } + if(status == EXIT_FAILURE) + { + free(item.data); + if(item.allocated) + { free(item.name); + } + return EXIT_FAILURE; } - item->name_len = VAR_NAME_FULL_LENGTH; - item->data = malloc(item->size); - item->typename = NULL; - item->type_len = 0; /* add to table */ int err = 3; - khint_t k = kh_put(__STR__TABLE__, parser->strtable, item->name, &err); + khint_t k = kh_put(__STR__TABLE__, parser->strtable, item.name, &err); enum { __KHASH_BAD_OPERATION = -1, @@ -736,11 +801,11 @@ SCParserNewVar( default: /* bounds check */ if(kh_end(parser->strtable) > k) - { kh_value(parser->strtable, k) = parser->index; + { kh_value(parser->strtable, k) = parser->items_len; } break; } - ++parser->index; + ++parser->items_len; return SUCCESS; } @@ -750,19 +815,22 @@ SCParserDelVar( const char *const VAR_NAME ) { - SCItem *item = SCParserSearch(parser, VAR_NAME); - if(!item) - { item = SCParserSearchSlow(parser, VAR_NAME); - } - if(item) + unsigned int NOT_FOUND = 0; + uint32_t index = __SC__PARSER__SEARCH__INDEX__(parser, VAR_NAME, &NOT_FOUND); + if(!NOT_FOUND) { - if(item->allocated) - { free(item->name); + SCItem *item = GArrayAt(&parser->items, index); + if(item) + { + if(item->allocated) + { free(item->name); + } + free(item->typename); + --parser->items_len; + return GArrayDelete(&parser->items, index); } - free(item->typename); - memset(item, 0, sizeof(SCItem)); } - return !item; + return EXIT_FAILURE; } int diff --git a/tools/DynamicArray/LICENSE b/tools/DynamicArray/LICENSE new file mode 100644 index 0000000..7815992 --- /dev/null +++ b/tools/DynamicArray/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Joseph + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tools/DynamicArray/README.md b/tools/DynamicArray/README.md new file mode 100644 index 0000000..11824a9 --- /dev/null +++ b/tools/DynamicArray/README.md @@ -0,0 +1,101 @@ +# GArray + +A small (300 lines) dynamic array. + +## Example +```C + +#include +#include + +#include "dynamic_array.h" + + +int +main(void) +{ + uint32_t item_size = sizeof(int); + uint32_t initial_size = 10; + uint32_t i; + + GArray *array = GArrayCreate(item_size, initial_size); + if (array == NULL) + { return EXIT_FAILURE; + } + + /* make all data 0's to show it works */ + for(i = GArrayStart(array); i < GArrayEnd(array); ++i) + { GArrayReplace(array, NULL, i); + } + + int value = 42; + if (GArrayPushBack(array, &value) != EXIT_SUCCESS) + { + GArrayWipe(array); + free(array); + return EXIT_FAILURE; + } + + + int *p = (int *)GArrayAt(array, 0); + + if (p) + { printf("Previous Value at index 0: %d\n", *p); + } + else + { + GArrayWipe(array); + free(array); + return EXIT_FAILURE; + } + + int new_value = 99; + if (GArrayReplace(array, &new_value, 0) != EXIT_SUCCESS) + { + GArrayWipe(array); + free(array); + return EXIT_FAILURE; + } + + p = (int *)GArrayAt(array, 0); + if (p) + { printf("New value at index 0: %d\n", *p); + } + else + { + GArrayWipe(array); + free(array); + return EXIT_FAILURE; + } + + int insert_value = 55; + if (GArrayInsert(array, &insert_value, 1) != EXIT_SUCCESS) + { + GArrayWipe(array); + free(array); + return EXIT_FAILURE; + } + + printf("Value at index %d: %d\n", 1, *(int *)GArrayAt(array, 1)); + printf("Deleting Index %d\n", 1); + + if (GArrayDelete(array, 1) != EXIT_SUCCESS) + { + GArrayWipe(array); + free(array); + return EXIT_FAILURE; + } + + for (i = GArrayStart(array); i < GArrayEnd(array); ++i) + { + p = (int *)GArrayAt(array, i); + if (p) + { printf("Value at index %d: %d\n", i, *p); + } + } + + GArrayWipe(array); + free(array); + return EXIT_SUCCESS; +} + diff --git a/tools/DynamicArray/array.h b/tools/DynamicArray/array.h new file mode 100644 index 0000000..824cf1f --- /dev/null +++ b/tools/DynamicArray/array.h @@ -0,0 +1,12 @@ +#ifndef __F____ARRAY__H__ +#define __F____ARRAY__H__ + + +#include "dynamic_array.h" +#include "array8.h" +#include "array16.h" +#include "array32.h" +#include "array64.h" +#include "array_p.h" + +#endif diff --git a/tools/DynamicArray/array16.c b/tools/DynamicArray/array16.c new file mode 100644 index 0000000..5502382 --- /dev/null +++ b/tools/DynamicArray/array16.c @@ -0,0 +1,301 @@ +#include +#include +#include + +#include "array16.h" +#include "dynamic_array.h" + +GArray * +GArrayCreate16( + uint32_t base_allocate + ) +{ + GArray *ret = malloc(sizeof(GArray)); + + if(ret) + { + uint8_t status = GArrayCreateFilled16(ret, base_allocate); + if(status == EXIT_FAILURE) + { + GArrayWipe16(ret); + free(ret); + ret = NULL; + } + } + return ret; +} + +int +GArrayCreateFilled16( + GArray *array_return, + uint32_t base_allocate + ) +{ + if(!array_return) + { return EXIT_FAILURE; + } + array_return->data = NULL; + array_return->data_len = 0; + array_return->data_len_real = 0; + GArrayResize16(array_return, base_allocate); + return EXIT_SUCCESS; +} + +void +GArrayWipe16( + GArray *array + ) +{ + if(!array) + { return; + } + free(array->data); +} + +int +GArrayResize16( + GArray *array, + uint32_t item_len + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data_len == item_len) + { return EXIT_SUCCESS; + } + + const uint32_t item_size = sizeof(uint16_t); + const float MIN_GROWTH = 1.25f; + + if(item_len == 0) + { + free(array->data); + array->data = NULL; + } + else if(!array->data) + { + uint64_t size = item_len * MIN_GROWTH; + array->data = malloc(item_size * size); + if(!array->data) + { return EXIT_FAILURE; + } + array->data_len_real = size; + } + else + { + const uint8_t toosmall = array->data_len_real < item_len; + uint64_t size; + if(toosmall) + { size = item_len + (item_len / (array->data_len_real + !array->data_len_real)); + } + else + { size = array->data_len_real - (array->data_len_real - item_len); + } + + void *rec = realloc(array->data, item_size * size); + if(!rec ) + { return EXIT_FAILURE; + } + array->data = rec; + } + + array->data_len = item_len; + + return EXIT_SUCCESS; +} +int +GArrayPushBack16( + GArray *array, + void *item_cpy + ) +{ + if(!array || !item_cpy) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint16_t); + + uint8_t status = GArrayResize16(array, array->data_len + 1); + if(status == EXIT_SUCCESS) + { + uint8_t *data = array->data; + uint8_t *dest = data + (array->data_len - 1) * item_size; + uint8_t *src = item_cpy; + uint32_t size = item_size; + + memmove(dest, src, size); + } + return status; +} + +int +GArrayPopBack16( + GArray *array + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data) + { + /* make sure no underflow */ + if(array->data_len) + { GArrayResize16(array, array->data_len - 1); + } + } + return EXIT_SUCCESS; +} + +int +GArrayReplace16( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index > array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint16_t); + uint8_t *data = array->data; + uint8_t *dest = data + index * item_size; + uint8_t *src = item_cpy; + + if(item_cpy) + { memmove(dest, src, item_size); + } + else + { memset(dest, 0, item_size); + } + return EXIT_SUCCESS; +} + +int +GArrayInsert16( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + uint8_t status = GArrayResize16(array, array->data_len + 1); + + if(status == EXIT_SUCCESS) + { + const uint32_t item_size = sizeof(uint16_t); + + uint8_t *data = array->data; + uint8_t *dest = data + (index + 1) * item_size; + uint8_t *src = data + index * item_size; + + uint32_t move_size = (array->data_len - index - 1) * item_size; + + memmove(dest, src, move_size); + if(item_cpy) + { memmove(src, item_cpy, item_size); + } + else + { memset(src, 0, item_size); + } + } + + return status; +} + +int +GArrayDelete16( + GArray *array, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint16_t); + const uint32_t BYTES_MOVE = (array->data_len - index - 1) * item_size; + + uint8_t *data = array->data; + uint8_t *src = data + (item_size * (index + 1)); + uint8_t *dest = data + (item_size * index); + + /* Check if last so no invalid memove */ + if(index < array->data_len - 1) + { memmove(dest, src, BYTES_MOVE); + } + + GArrayResize(array, array->data_len - 1); + return EXIT_SUCCESS; +} + + +void * +GArrayAt16( + GArray *array, + uint32_t index + ) +{ + if(array->data_len < index) + { return NULL; + } + const uint32_t item_size = sizeof(uint16_t); + return (uint8_t *)array->data + (index * item_size); +} + +int +GArrayAtSafe16( + GArray *array, + uint32_t index, + void *fill_return + ) +{ + const uint32_t item_size = sizeof(uint16_t); + + void *data = GArrayAt16(array, index); + int ret = EXIT_FAILURE; + if(fill_return) + { + if(data) + { + memmove(fill_return, data, item_size); + ret = EXIT_SUCCESS; + } + } + return ret; +} + + +uint32_t +GArrayEnd16( + GArray *array + ) +{ + if(array) + { return array->data_len; + } + return 0; +} + +uint32_t +GArrayStart16( + GArray *array + ) +{ return (const unsigned int) 0; +} + diff --git a/tools/DynamicArray/array16.h b/tools/DynamicArray/array16.h new file mode 100644 index 0000000..26c7fe7 --- /dev/null +++ b/tools/DynamicArray/array16.h @@ -0,0 +1,82 @@ +#ifndef __ARRAY__16__H__ +#define __ARRAY__16__H__ + + +#include "dynamic_array.h" + +typedef struct __GArray__ Garray16; + + +GArray * +GArrayCreate16( + uint32_t base_allocate + ); + +int +GArrayCreateFilled16( + GArray *array_return, + uint32_t base_allocate + ); + +void +GArrayWipe16( + GArray *array + ); + +int +GArrayResize16( + GArray *array, + uint32_t item_len + ); + +int +GArrayPopBack16( + GArray *array + ); + +int +GArrayReplace16( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayInsert16( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayDelete16( + GArray *array, + uint32_t index + ); + + +void * +GArrayAt16( + GArray *array, + uint32_t index + ); + +int +GArrayAtSafe16( + GArray *array, + uint32_t index, + void *fill_return + ); + +uint32_t +GArrayEnd16( + GArray *array + ); + +uint32_t +GArrayStart16( + GArray *array + ); + + +#endif diff --git a/tools/DynamicArray/array32.c b/tools/DynamicArray/array32.c new file mode 100644 index 0000000..fde46fd --- /dev/null +++ b/tools/DynamicArray/array32.c @@ -0,0 +1,301 @@ +#include +#include +#include + +#include "array32.h" +#include "dynamic_array.h" + +GArray * +GArrayCreate32( + uint32_t base_allocate + ) +{ + GArray *ret = malloc(sizeof(GArray)); + + if(ret) + { + uint8_t status = GArrayCreateFilled32(ret, base_allocate); + if(status == EXIT_FAILURE) + { + GArrayWipe32(ret); + free(ret); + ret = NULL; + } + } + return ret; +} + +int +GArrayCreateFilled32( + GArray *array_return, + uint32_t base_allocate + ) +{ + if(!array_return) + { return EXIT_FAILURE; + } + array_return->data = NULL; + array_return->data_len = 0; + array_return->data_len_real = 0; + GArrayResize32(array_return, base_allocate); + return EXIT_SUCCESS; +} + +void +GArrayWipe32( + GArray *array + ) +{ + if(!array) + { return; + } + free(array->data); +} + +int +GArrayResize32( + GArray *array, + uint32_t item_len + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data_len == item_len) + { return EXIT_SUCCESS; + } + + const uint32_t item_size = sizeof(uint32_t); + const float MIN_GROWTH = 1.25f; + + if(item_len == 0) + { + free(array->data); + array->data = NULL; + } + else if(!array->data) + { + uint64_t size = item_len * MIN_GROWTH; + array->data = malloc(item_size * size); + if(!array->data) + { return EXIT_FAILURE; + } + array->data_len_real = size; + } + else + { + const uint8_t toosmall = array->data_len_real < item_len; + uint64_t size; + if(toosmall) + { size = item_len + (item_len / (array->data_len_real + !array->data_len_real)); + } + else + { size = array->data_len_real - (array->data_len_real - item_len); + } + + void *rec = realloc(array->data, item_size * size); + if(!rec ) + { return EXIT_FAILURE; + } + array->data = rec; + } + + array->data_len = item_len; + + return EXIT_SUCCESS; +} +int +GArrayPushBack32( + GArray *array, + void *item_cpy + ) +{ + if(!array || !item_cpy) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint32_t); + + uint8_t status = GArrayResize32(array, array->data_len + 1); + if(status == EXIT_SUCCESS) + { + uint8_t *data = array->data; + uint8_t *dest = data + (array->data_len - 1) * item_size; + uint8_t *src = item_cpy; + uint32_t size = item_size; + + memmove(dest, src, size); + } + return status; +} + +int +GArrayPopBack32( + GArray *array + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data) + { + /* make sure no underflow */ + if(array->data_len) + { GArrayResize32(array, array->data_len - 1); + } + } + return EXIT_SUCCESS; +} + +int +GArrayReplace32( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index > array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint32_t); + uint8_t *data = array->data; + uint8_t *dest = data + index * item_size; + uint8_t *src = item_cpy; + + if(item_cpy) + { memmove(dest, src, item_size); + } + else + { memset(dest, 0, item_size); + } + return EXIT_SUCCESS; +} + +int +GArrayInsert32( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + uint8_t status = GArrayResize32(array, array->data_len + 1); + + if(status == EXIT_SUCCESS) + { + const uint32_t item_size = sizeof(uint32_t); + + uint8_t *data = array->data; + uint8_t *dest = data + (index + 1) * item_size; + uint8_t *src = data + index * item_size; + + uint32_t move_size = (array->data_len - index - 1) * item_size; + + memmove(dest, src, move_size); + if(item_cpy) + { memmove(src, item_cpy, item_size); + } + else + { memset(src, 0, item_size); + } + } + + return status; +} + +int +GArrayDelete32( + GArray *array, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint32_t); + const uint32_t BYTES_MOVE = (array->data_len - index - 1) * item_size; + + uint8_t *data = array->data; + uint8_t *src = data + (item_size * (index + 1)); + uint8_t *dest = data + (item_size * index); + + /* Check if last so no invalid memove */ + if(index < array->data_len - 1) + { memmove(dest, src, BYTES_MOVE); + } + + GArrayResize32(array, array->data_len - 1); + return EXIT_SUCCESS; +} + + +void * +GArrayAt32( + GArray *array, + uint32_t index + ) +{ + if(array->data_len < index) + { return NULL; + } + const uint32_t item_size = sizeof(uint32_t); + return (uint8_t *)array->data + (index * item_size); +} + +int +GArrayAtSafe32( + GArray *array, + uint32_t index, + void *fill_return + ) +{ + const uint32_t item_size = sizeof(uint32_t); + + void *data = GArrayAt32(array, index); + int ret = EXIT_FAILURE; + if(fill_return) + { + if(data) + { + memmove(fill_return, data, item_size); + ret = EXIT_SUCCESS; + } + } + return ret; +} + + +uint32_t +GArrayEnd32( + GArray *array + ) +{ + if(array) + { return array->data_len; + } + return 0; +} + +uint32_t +GArrayStart32( + GArray *array + ) +{ return (const unsigned int) 0; +} + diff --git a/tools/DynamicArray/array32.h b/tools/DynamicArray/array32.h new file mode 100644 index 0000000..9fc66da --- /dev/null +++ b/tools/DynamicArray/array32.h @@ -0,0 +1,81 @@ +#ifndef __ARRAY__32__H__ +#define __ARRAY__32__H__ + +#include "dynamic_array.h" + +typedef struct __GArray__ GArrray32; + + +GArray * +GArrayCreate32( + uint32_t base_allocate + ); + +int +GArrayCreateFilled32( + GArray *array_return, + uint32_t base_allocate + ); + +void +GArrayWipe32( + GArray *array + ); + +int +GArrayResize32( + GArray *array, + uint32_t item_len + ); + +int +GArrayPopBack32( + GArray *array + ); + +int +GArrayReplace32( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayInsert32( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayDelete32( + GArray *array, + uint32_t index + ); + + +void * +GArrayAt32( + GArray *array, + uint32_t index + ); + +int +GArrayAtSafe32( + GArray *array, + uint32_t index, + void *fill_return + ); + +uint32_t +GArrayEnd32( + GArray *array + ); + +uint32_t +GArrayStart32( + GArray *array + ); + + +#endif diff --git a/tools/DynamicArray/array64.c b/tools/DynamicArray/array64.c new file mode 100644 index 0000000..11c28da --- /dev/null +++ b/tools/DynamicArray/array64.c @@ -0,0 +1,301 @@ +#include +#include +#include + +#include "array64.h" +#include "dynamic_array.h" + +GArray * +GArrayCreate64( + uint32_t base_allocate + ) +{ + GArray *ret = malloc(sizeof(GArray)); + + if(ret) + { + uint8_t status = GArrayCreateFilled64(ret, base_allocate); + if(status == EXIT_FAILURE) + { + GArrayWipe64(ret); + free(ret); + ret = NULL; + } + } + return ret; +} + +int +GArrayCreateFilled64( + GArray *array_return, + uint32_t base_allocate + ) +{ + if(!array_return) + { return EXIT_FAILURE; + } + array_return->data = NULL; + array_return->data_len = 0; + array_return->data_len_real = 0; + GArrayResize64(array_return, base_allocate); + return EXIT_SUCCESS; +} + +void +GArrayWipe64( + GArray *array + ) +{ + if(!array) + { return; + } + free(array->data); +} + +int +GArrayResize64( + GArray *array, + uint32_t item_len + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data_len == item_len) + { return EXIT_SUCCESS; + } + + const uint32_t item_size = sizeof(uint64_t); + const float MIN_GROWTH = 1.25f; + + if(item_len == 0) + { + free(array->data); + array->data = NULL; + } + else if(!array->data) + { + uint64_t size = item_len * MIN_GROWTH; + array->data = malloc(item_size * size); + if(!array->data) + { return EXIT_FAILURE; + } + array->data_len_real = size; + } + else + { + const uint8_t toosmall = array->data_len_real < item_len; + uint64_t size; + if(toosmall) + { size = item_len + (item_len / (array->data_len_real + !array->data_len_real)); + } + else + { size = array->data_len_real - (array->data_len_real - item_len); + } + + void *rec = realloc(array->data, item_size * size); + if(!rec ) + { return EXIT_FAILURE; + } + array->data = rec; + } + + array->data_len = item_len; + + return EXIT_SUCCESS; +} +int +GArrayPushBack64( + GArray *array, + void *item_cpy + ) +{ + if(!array || !item_cpy) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint64_t); + + uint8_t status = GArrayResize64(array, array->data_len + 1); + if(status == EXIT_SUCCESS) + { + uint8_t *data = array->data; + uint8_t *dest = data + (array->data_len - 1) * item_size; + uint8_t *src = item_cpy; + uint32_t size = item_size; + + memmove(dest, src, size); + } + return status; +} + +int +GArrayPopBack64( + GArray *array + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data) + { + /* make sure no underflow */ + if(array->data_len) + { GArrayResize64(array, array->data_len - 1); + } + } + return EXIT_SUCCESS; +} + +int +GArrayReplace64( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index > array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint64_t); + uint8_t *data = array->data; + uint8_t *dest = data + index * item_size; + uint8_t *src = item_cpy; + + if(item_cpy) + { memmove(dest, src, item_size); + } + else + { memset(dest, 0, item_size); + } + return EXIT_SUCCESS; +} + +int +GArrayInsert64( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + uint8_t status = GArrayResize64(array, array->data_len + 1); + + if(status == EXIT_SUCCESS) + { + const uint32_t item_size = sizeof(uint64_t); + + uint8_t *data = array->data; + uint8_t *dest = data + (index + 1) * item_size; + uint8_t *src = data + index * item_size; + + uint32_t move_size = (array->data_len - index - 1) * item_size; + + memmove(dest, src, move_size); + if(item_cpy) + { memmove(src, item_cpy, item_size); + } + else + { memset(src, 0, item_size); + } + } + + return status; +} + +int +GArrayDelete64( + GArray *array, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(uint64_t); + const uint32_t BYTES_MOVE = (array->data_len - index - 1) * item_size; + + uint8_t *data = array->data; + uint8_t *src = data + (item_size * (index + 1)); + uint8_t *dest = data + (item_size * index); + + /* Check if last so no invalid memove */ + if(index < array->data_len - 1) + { memmove(dest, src, BYTES_MOVE); + } + + GArrayResize64(array, array->data_len - 1); + return EXIT_SUCCESS; +} + + +void * +GArrayAt64( + GArray *array, + uint32_t index + ) +{ + if(array->data_len < index) + { return NULL; + } + const uint32_t item_size = sizeof(uint64_t); + return (uint8_t *)array->data + (index * item_size); +} + +int +GArrayAtSafe64( + GArray *array, + uint32_t index, + void *fill_return + ) +{ + const uint32_t item_size = sizeof(uint64_t); + + void *data = GArrayAt64(array, index); + int ret = EXIT_FAILURE; + if(fill_return) + { + if(data) + { + memmove(fill_return, data, item_size); + ret = EXIT_SUCCESS; + } + } + return ret; +} + + +uint32_t +GArrayEnd64( + GArray *array + ) +{ + if(array) + { return array->data_len; + } + return 0; +} + +uint32_t +GArrayStart64( + GArray *array + ) +{ return (const unsigned int) 0; +} + diff --git a/tools/DynamicArray/array64.h b/tools/DynamicArray/array64.h new file mode 100644 index 0000000..ecc531d --- /dev/null +++ b/tools/DynamicArray/array64.h @@ -0,0 +1,81 @@ +#ifndef __ARRAY__64__H__ +#define __ARRAY__64__H__ + +#include "dynamic_array.h" + +typedef struct __GArray__ Garray64; + + +GArray * +GArrayCreate64( + uint32_t base_allocate + ); + +int +GArrayCreateFilled64( + GArray *array_return, + uint32_t base_allocate + ); + +void +GArrayWipe64( + GArray *array + ); + +int +GArrayResize64( + GArray *array, + uint32_t item_len + ); + +int +GArrayPopBack64( + GArray *array + ); + +int +GArrayReplace64( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayInsert64( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayDelete64( + GArray *array, + uint32_t index + ); + + +void * +GArrayAt64( + GArray *array, + uint32_t index + ); + +int +GArrayAtSafe64( + GArray *array, + uint32_t index, + void *fill_return + ); + +uint32_t +GArrayEnd64( + GArray *array + ); + +uint32_t +GArrayStart64( + GArray *array + ); + + +#endif diff --git a/tools/DynamicArray/array8.c b/tools/DynamicArray/array8.c new file mode 100644 index 0000000..4f3f828 --- /dev/null +++ b/tools/DynamicArray/array8.c @@ -0,0 +1,301 @@ +#include +#include +#include + +#include "array8.h" +#include "dynamic_array.h" + +GArray * +GArrayCreate8( + uint32_t base_allocate + ) +{ + GArray *ret = malloc(sizeof(GArray)); + + if(ret) + { + uint8_t status = GArrayCreateFilled8(ret, base_allocate); + if(status == EXIT_FAILURE) + { + GArrayWipe8(ret); + free(ret); + ret = NULL; + } + } + return ret; +} + +int +GArrayCreateFilled8( + GArray *array_return, + uint32_t base_allocate + ) +{ + if(!array_return) + { return EXIT_FAILURE; + } + array_return->data = NULL; + array_return->data_len = 0; + array_return->data_len_real = 0; + GArrayResize8(array_return, base_allocate); + return EXIT_SUCCESS; +} + +void +GArrayWipe8( + GArray *array + ) +{ + if(!array) + { return; + } + free(array->data); +} + +int +GArrayResize8( + GArray *array, + uint32_t item_len + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data_len == item_len) + { return EXIT_SUCCESS; + } + + const uint32_t item_size = sizeof(char); + const float MIN_GROWTH = 1.25f; + + if(item_len == 0) + { + free(array->data); + array->data = NULL; + } + else if(!array->data) + { + uint64_t size = item_len * MIN_GROWTH; + array->data = malloc(item_size * size); + if(!array->data) + { return EXIT_FAILURE; + } + array->data_len_real = size; + } + else + { + const uint8_t toosmall = array->data_len_real < item_len; + uint64_t size; + if(toosmall) + { size = item_len + (item_len / (array->data_len_real + !array->data_len_real)); + } + else + { size = array->data_len_real - (array->data_len_real - item_len); + } + + void *rec = realloc(array->data, item_size * size); + if(!rec ) + { return EXIT_FAILURE; + } + array->data = rec; + } + + array->data_len = item_len; + + return EXIT_SUCCESS; +} +int +GArrayPushBack8( + GArray *array, + void *item_cpy + ) +{ + if(!array || !item_cpy) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(char); + + uint8_t status = GArrayResize8(array, array->data_len + 1); + if(status == EXIT_SUCCESS) + { + uint8_t *data = array->data; + uint8_t *dest = data + (array->data_len - 1) * item_size; + uint8_t *src = item_cpy; + uint32_t size = item_size; + + memmove(dest, src, size); + } + return status; +} + +int +GArrayPopBack8( + GArray *array + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data) + { + /* make sure no underflow */ + if(array->data_len) + { GArrayResize8(array, array->data_len - 1); + } + } + return EXIT_SUCCESS; +} + +int +GArrayReplace8( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index > array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(char); + uint8_t *data = array->data; + uint8_t *dest = data + index * item_size; + uint8_t *src = item_cpy; + + if(item_cpy) + { memmove(dest, src, item_size); + } + else + { memset(dest, 0, item_size); + } + return EXIT_SUCCESS; +} + +int +GArrayInsert8( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + uint8_t status = GArrayResize8(array, array->data_len + 1); + + if(status == EXIT_SUCCESS) + { + const uint32_t item_size = sizeof(char); + + uint8_t *data = array->data; + uint8_t *dest = data + (index + 1) * item_size; + uint8_t *src = data + index * item_size; + + uint32_t move_size = (array->data_len - index - 1) * item_size; + + memmove(dest, src, move_size); + if(item_cpy) + { memmove(src, item_cpy, item_size); + } + else + { memset(src, 0, item_size); + } + } + + return status; +} + +int +GArrayDelete8( + GArray *array, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(char); + const uint32_t BYTES_MOVE = (array->data_len - index - 1) * item_size; + + uint8_t *data = array->data; + uint8_t *src = data + (item_size * (index + 1)); + uint8_t *dest = data + (item_size * index); + + /* Check if last so no invalid memove */ + if(index < array->data_len - 1) + { memmove(dest, src, BYTES_MOVE); + } + + GArrayResize8(array, array->data_len - 1); + return EXIT_SUCCESS; +} + + +void * +GArrayAt8( + GArray *array, + uint32_t index + ) +{ + if(array->data_len < index) + { return NULL; + } + const uint32_t item_size = sizeof(char); + return (uint8_t *)array->data + (index * item_size); +} + +int +GArrayAtSafe8( + GArray *array, + uint32_t index, + void *fill_return + ) +{ + const uint32_t item_size = sizeof(char); + + void *data = GArrayAt8(array, index); + int ret = EXIT_FAILURE; + if(fill_return) + { + if(data) + { + memmove(fill_return, data, item_size); + ret = EXIT_SUCCESS; + } + } + return ret; +} + + +uint32_t +GArrayEnd8( + GArray *array + ) +{ + if(array) + { return array->data_len; + } + return 0; +} + +uint32_t +GArrayStart8( + GArray *array + ) +{ return (const unsigned int) 0; +} + diff --git a/tools/DynamicArray/array8.h b/tools/DynamicArray/array8.h new file mode 100644 index 0000000..599b28b --- /dev/null +++ b/tools/DynamicArray/array8.h @@ -0,0 +1,81 @@ +#ifndef __ARRAY__8__H__ +#define __ARRAY__8__H__ + + + +#include "dynamic_array.h" + +typedef struct __GArray__ GArray8; + +GArray * +GArrayCreate8( + uint32_t base_allocate + ); + +int +GArrayCreateFilled8( + GArray *array_return, + uint32_t base_allocate + ); + +void +GArrayWipe8( + GArray *array + ); + +int +GArrayResize8( + GArray *array, + uint32_t item_len + ); + +int +GArrayPopBack8( + GArray *array + ); + +int +GArrayReplace8( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayInsert8( + GArray *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayDelete8( + GArray *array, + uint32_t index + ); + + +void * +GArrayAt8( + GArray *array, + uint32_t index + ); + +int +GArrayAtSafe8( + GArray *array, + uint32_t index, + void *fill_return + ); + +uint32_t +GArrayEnd8( + GArray *array + ); + +uint32_t +GArrayStart8( + GArray *array + ); + +#endif diff --git a/tools/DynamicArray/array_p.c b/tools/DynamicArray/array_p.c new file mode 100644 index 0000000..7792981 --- /dev/null +++ b/tools/DynamicArray/array_p.c @@ -0,0 +1,301 @@ +#include +#include +#include + +#include "array_p.h" + + +GArrayP * +GArrayCreateP( + uint32_t base_allocate + ) +{ + GArrayP *ret = malloc(sizeof(GArrayP)); + + if(ret) + { + uint8_t status = GArrayCreateFilledP(ret, base_allocate); + if(status == EXIT_FAILURE) + { + GArrayWipeP(ret); + free(ret); + ret = NULL; + } + } + return ret; +} + +int +GArrayCreateFilledP( + GArrayP *array_return, + uint32_t base_allocate + ) +{ + if(!array_return) + { return EXIT_FAILURE; + } + array_return->data = NULL; + array_return->data_len = 0; + array_return->data_len_real = 0; + GArrayResizeP(array_return, base_allocate); + return EXIT_SUCCESS; +} + +void +GArrayWipeP( + GArrayP *array + ) +{ + if(!array) + { return; + } + free(array->data); +} + +int +GArrayResizeP( + GArrayP *array, + uint32_t item_len + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data_len == item_len) + { return EXIT_SUCCESS; + } + + const uint32_t item_size = sizeof(char *); + const float MIN_GROWTH = 1.25f; + + if(item_len == 0) + { + free(array->data); + array->data = NULL; + } + else if(!array->data) + { + uint64_t size = item_len * MIN_GROWTH; + array->data = malloc(item_size * size); + if(!array->data) + { return EXIT_FAILURE; + } + array->data_len_real = size; + } + else + { + const uint8_t toosmall = array->data_len_real < item_len; + uint64_t size; + if(toosmall) + { size = item_len + (item_len / (array->data_len_real + !array->data_len_real)); + } + else + { size = array->data_len_real - (array->data_len_real - item_len); + } + + void *rec = realloc(array->data, item_size * size); + if(!rec ) + { return EXIT_FAILURE; + } + array->data = rec; + } + + array->data_len = item_len; + + return EXIT_SUCCESS; +} +int +GArrayPushBackP( + GArrayP *array, + void *item_cpy + ) +{ + if(!array || !item_cpy) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(char *); + + uint8_t status = GArrayResizeP(array, array->data_len + 1); + if(status == EXIT_SUCCESS) + { + uint8_t *data = array->data; + uint8_t *dest = data + (array->data_len - 1) * item_size; + uint8_t *src = item_cpy; + uint32_t size = item_size; + + memmove(dest, src, size); + } + return status; +} + +int +GArrayPopBackP( + GArrayP *array + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data) + { + /* make sure no underflow */ + if(array->data_len) + { GArrayResizeP(array, array->data_len - 1); + } + } + return EXIT_SUCCESS; +} + +int +GArrayReplaceP( + GArrayP *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index > array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(char *); + uint8_t *data = array->data; + uint8_t *dest = data + index * item_size; + uint8_t *src = item_cpy; + + if(item_cpy) + { memmove(dest, src, item_size); + } + else + { memset(dest, 0, item_size); + } + return EXIT_SUCCESS; +} + +int +GArrayInsertP( + GArrayP *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + uint8_t status = GArrayResizeP(array, array->data_len + 1); + + if(status == EXIT_SUCCESS) + { + const uint32_t item_size = sizeof(char *); + + uint8_t *data = array->data; + uint8_t *dest = data + (index + 1) * item_size; + uint8_t *src = data + index * item_size; + + uint32_t move_size = (array->data_len - index - 1) * item_size; + + memmove(dest, src, move_size); + if(item_cpy) + { memmove(src, item_cpy, item_size); + } + else + { memset(src, 0, item_size); + } + } + + return status; +} + +int +GArrayDeleteP( + GArrayP *array, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t item_size = sizeof(char *); + const uint32_t BYTES_MOVE = (array->data_len - index - 1) * item_size; + + uint8_t *data = array->data; + uint8_t *src = data + (item_size * (index + 1)); + uint8_t *dest = data + (item_size * index); + + /* Check if last so no invalid memove */ + if(index < array->data_len - 1) + { memmove(dest, src, BYTES_MOVE); + } + + GArrayResizeP(array, array->data_len - 1); + return EXIT_SUCCESS; +} + + +void * +GArrayAtP( + GArrayP *array, + uint32_t index + ) +{ + if(array->data_len < index) + { return NULL; + } + const uint32_t item_size = sizeof(char *); + return (uint8_t *)array->data + (index * item_size); +} + +int +GArrayAtSafeP( + GArrayP *array, + uint32_t index, + void *fill_return + ) +{ + const uint32_t item_size = sizeof(char *); + + void *data = GArrayAtP(array, index); + int ret = EXIT_FAILURE; + if(fill_return) + { + if(data) + { + memmove(fill_return, data, item_size); + ret = EXIT_SUCCESS; + } + } + return ret; +} + + +uint32_t +GArrayEndP( + GArrayP *array + ) +{ + if(array) + { return array->data_len; + } + return 0; +} + +uint32_t +GArrayStartP( + GArrayP *array + ) +{ return (const unsigned int) 0; +} + diff --git a/tools/DynamicArray/array_p.h b/tools/DynamicArray/array_p.h new file mode 100644 index 0000000..729ca71 --- /dev/null +++ b/tools/DynamicArray/array_p.h @@ -0,0 +1,82 @@ +#ifndef __ARRAY__P__H__ +#define __ARRAY__P__H__ + + +#include "dynamic_array.h" + +typedef struct __GArray__ GArrayP; + + +GArrayP * +GArrayCreateP( + uint32_t base_allocate + ); + +int +GArrayCreateFilledP( + GArrayP *array_return, + uint32_t base_allocate + ); + +void +GArrayWipeP( + GArrayP *array + ); + +int +GArrayResizeP( + GArrayP *array, + uint32_t item_len + ); + +int +GArrayPopBackP( + GArrayP *array + ); + +int +GArrayReplaceP( + GArrayP *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayInsertP( + GArrayP *array, + void *item_cpy, + uint32_t index + ); + +int +GArrayDeleteP( + GArrayP *array, + uint32_t index + ); + + +void * +GArrayAtP( + GArrayP *array, + uint32_t index + ); + +int +GArrayAtSafeP( + GArrayP *array, + uint32_t index, + void *fill_return + ); + +uint32_t +GArrayEndP( + GArrayP *array + ); + +uint32_t +GArrayStartP( + GArrayP *array + ); + + +#endif diff --git a/tools/DynamicArray/dynamic_array.c b/tools/DynamicArray/dynamic_array.c new file mode 100644 index 0000000..a5165dd --- /dev/null +++ b/tools/DynamicArray/dynamic_array.c @@ -0,0 +1,319 @@ +/* MIT License + * + * Copyright (c) 2024 Joseph + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include "dynamic_array.h" + +GArray * +GArrayCreate( + uint32_t item_size, + uint32_t base_allocate + ) +{ + GArray *ret = malloc(sizeof(GArray)); + + if(ret) + { + uint8_t status = GArrayCreateFilled(ret, item_size, base_allocate); + if(status == EXIT_FAILURE) + { + GArrayWipe(ret); + free(ret); + ret = NULL; + } + } + return ret; +} + +int +GArrayCreateFilled( + GArray *array_return, + uint32_t item_size, + uint32_t base_allocate + ) +{ + if(!array_return || !item_size) + { return EXIT_FAILURE; + } + array_return->item_size = item_size; + array_return->data = NULL; + array_return->data_len = 0; + array_return->data_len_real = 0; + GArrayResize(array_return, base_allocate); + return EXIT_SUCCESS; +} + +void +GArrayWipe( + GArray *array + ) +{ + if(!array) + { return; + } + free(array->data); +} + +int +GArrayResize( + GArray *array, + uint32_t item_len + ) +{ + if(!array) + { return EXIT_FAILURE; + } + + if(array->data_len == item_len) + { return EXIT_SUCCESS; + } + + const float MIN_GROWTH = 1.25f; + + if(item_len == 0) + { + free(array->data); + array->data = NULL; + } + else if(!array->data) + { + uint64_t size = item_len * MIN_GROWTH; + array->data = malloc(array->item_size * size); + if(!array->data) + { return EXIT_FAILURE; + } + array->data_len_real = size; + } + else + { + const uint8_t toosmall = array->data_len_real < item_len; + uint64_t size; + if(toosmall) + { size = item_len + (item_len / (array->data_len_real + !array->data_len_real)); + } + else + { size = array->data_len_real - (array->data_len_real - item_len); + } + + void *rec = realloc(array->data, array->item_size * size); + if(!rec ) + { return EXIT_FAILURE; + } + array->data = rec; + } + + array->data_len = item_len; + + return EXIT_SUCCESS; +} +int +GArrayPushBack( + GArray *array, + void *item_cpy + ) +{ + if(!array || !item_cpy) + { return EXIT_FAILURE; + } + uint8_t status = GArrayResize(array, array->data_len + 1); + if(status == EXIT_SUCCESS) + { + uint8_t *data = array->data; + uint8_t *dest = data + (array->data_len - 1) * array->item_size; + uint8_t *src = item_cpy; + uint32_t size = array->item_size; + + memmove(dest, src, size); + } + return status; +} + +int +GArrayPopBack( + GArray *array + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(array->data) + { + /* make sure no underflow */ + if(array->item_size) + { GArrayResize(array, array->item_size - 1); + } + } + return EXIT_SUCCESS; +} + +int +GArrayReplace( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index > array->data_len) + { return EXIT_FAILURE; + } + + uint32_t size = array->item_size;; + uint8_t *data = array->data; + uint8_t *dest = data + index * size; + uint8_t *src = item_cpy; + + if(item_cpy) + { memmove(dest, src, size); + } + else + { memset(dest, 0, size); + } + return EXIT_SUCCESS; +} + +int +GArrayInsert( + GArray *array, + void *item_cpy, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + uint8_t status = GArrayResize(array, array->data_len + 1); + + if(status == EXIT_SUCCESS) + { + uint32_t size = array->item_size; + + uint8_t *data = array->data; + uint8_t *dest = data + (index + 1) * size; + uint8_t *src = data + index * size; + + uint32_t move_size = (array->data_len - index - 1) * size; + + memmove(dest, src, move_size); + if(item_cpy) + { memmove(src, item_cpy, size); + } + else + { memset(src, 0, size); + } + } + + return status; +} + +int +GArrayDelete( + GArray *array, + uint32_t index + ) +{ + if(!array) + { return EXIT_FAILURE; + } + if(index >= array->data_len) + { return EXIT_FAILURE; + } + + const uint32_t size = array->item_size; + const uint32_t BYTES_MOVE = (array->data_len - index - 1) * size; + + uint8_t *data = array->data; + uint8_t *src = data + (size * (index + 1)); + uint8_t *dest = data + (size * index); + + /* Check if last so no invalid memove */ + if(index < array->data_len - 1) + { memmove(dest, src, BYTES_MOVE); + } + + GArrayResize(array, array->data_len - 1); + return EXIT_SUCCESS; +} + + +void * +GArrayAt( + GArray *array, + uint32_t index + ) +{ + if(array->data_len < index) + { return NULL; + } + return (uint8_t *)array->data + (index * array->item_size); +} + +int +GArrayAtSafe( + GArray *array, + uint32_t index, + void *fill_return + ) +{ + void *data = GArrayAt(array, index); + int ret = EXIT_FAILURE; + if(fill_return) + { + if(data) + { + memmove(fill_return, data, array->item_size); + ret = EXIT_SUCCESS; + } + } + return ret; +} + + +uint32_t +GArrayEnd( + GArray *array + ) +{ + if(array) + { return array->data_len; + } + return 0; +} + +uint32_t +GArrayStart( + GArray *array + ) +{ return (const unsigned int) 0; +} + diff --git a/tools/DynamicArray/dynamic_array.h b/tools/DynamicArray/dynamic_array.h new file mode 100644 index 0000000..00350c6 --- /dev/null +++ b/tools/DynamicArray/dynamic_array.h @@ -0,0 +1,178 @@ +/* MIT License + * + * Copyright (c) 2024 Joseph + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __DY__NAMIC__ARRAY__H__ +#define __DY__NAMIC__ARRAY__H__ + +#include + +#ifdef __G_ARRAY_H__ +#error "Using Glib for dynamic array, delete this line to acknowledge this" +#else +#define __G_ARRAY_H__ +#endif + +/* G stands for generic by the way. + */ +typedef struct GArray GArray; +typedef struct __GArray__ __GArray__; +/* UNUSED cause why would you use this? + * Encapsulation is useless at this low level. + * Even had said that I still use encapsulation, and half the time I only do it for sustainability of the project. + * Otherwise why would I? + */ +typedef uint32_t garray_i; + +struct +GArray +{ + void *data; + uint32_t item_size; + uint32_t data_len; + uint32_t data_len_real; + uint8_t pad0[4]; +}; + +struct +__GArray__ +{ + void *data; + uint32_t data_len; + uint32_t data_len_real; +}; + +/* + * RETURN: GArray * on Success + * RETURN: NULL on Failure. + */ +GArray * +GArrayCreate( + uint32_t item_size, + uint32_t base_allocate + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayCreateFilled( + GArray *array_return, + uint32_t item_size, + uint32_t base_allocate + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +void +GArrayWipe( + GArray *array + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayResize( + GArray *array, + uint32_t item_len + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayPushBack( + GArray *array, + void *item_cpy + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayPopBack( + GArray *array + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayReplace( + GArray *array, + void *item_cpy, + uint32_t index + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayInsert( + GArray *array, + void *item_cpy, + uint32_t index + ); + +/* + * RETURN: EXIT_SUCCESS on Sucesss. + * RETURN: EXIT_FAILURE on Failure. + */ +int +GArrayDelete( + GArray *array, + uint32_t index + ); + +void * +GArrayAt( + GArray *array, + uint32_t index + ); +int +GArrayAtSafe( + GArray *array, + uint32_t index, + void *fill_return + ); + +uint32_t +GArrayEnd( + GArray *array + ); + +uint32_t +GArrayStart( + GArray *array + ); + +#endif