Start of the rewrite so da is safer

This commit is contained in:
Maciej Samborski 2024-11-24 20:53:05 +01:00
parent df957fa078
commit 5170ab1501
2 changed files with 258 additions and 226 deletions

335
da.h
View File

@ -5,6 +5,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h>
#define EHAN_IMPLEMENTATION #define EHAN_IMPLEMENTATION
#include "ehan.h" #include "ehan.h"
@ -15,14 +16,14 @@ enum daFields {
TYPE = 2, TYPE = 2,
DATA = 3, DATA = 3,
}; };
typedef void * dynarr; typedef void * dynarr;
GenericReturn _daCreate(size_t initCapacity, size_t type, size_t size); dynarr _daCreate(size_t initCapacity, size_t type, size_t size);
GenericReturn _daPushLit(dynarr * da, size_t item); GenericReturn _daPushLit(dynarr * da, size_t item);
GenericReturn _daPushFlt(dynarr * da, float item); GenericReturn _daPushFlt(dynarr * da, float item);
GenericReturn _daPushStr(dynarr * da, const char * str); GenericReturn _daPushStr(dynarr * da, const char * str);
GenericReturn daCopy(dynarr da); dynarr daCopy(dynarr da);
GenericReturn daResize(dynarr da); dynarr daResize(dynarr da);
void _daPop(dynarr da, void * element); void _daPop(dynarr da, void * element);
void daPopDiscard(dynarr da); void daPopDiscard(dynarr da);
void daFree(dynarr da); void daFree(dynarr da);
@ -52,23 +53,39 @@ void daBzero(dynarr da);
#define daPop(da, item) _daPop(da, &item) #define daPop(da, item) _daPop(da, &item)
#define daGet(da, index) (da[index]) #define daGet(da, index) (da[index])
#endif // DA_H_ #define daAppend(daImpl, value) ({ \
if (daImpl != NULL) \
{ \
if (daSize(daImpl) >= daCap(daImpl)) \
daImpl = daResize(daImpl); \
\
if (daImpl != NULL) { \
daImpl[daSize(daImpl)] = value; \
*(((size_t *) daImpl) - 3) += 1; \
errno = 0; \
} else { \
errno = 1; \
} \
} else { \
errno = 1; \
} \
})
#ifdef DA_IMPLEMENTATION #ifdef DA_IMPLEMENTATION
GenericReturn _daCreate(size_t cap, size_t type, size_t size) dynarr _daCreate(size_t cap, size_t type, size_t size)
{ {
if (cap == 0) cap = 1; size_t realCap = (((int)(cap / 8)) + 1 ) * 8;
size_t * da = (size_t *) malloc(type * cap + DATA * sizeof(size_t)); size_t * da = (size_t *) calloc(1, type * realCap + DATA * sizeof(size_t));
if (da == NULL) if (da == NULL)
return ehanError("Failed to allocate resources for a dynamic array!"); return NULL;
da[SIZE] = size; da[SIZE] = size;
da[CAPACITY] = cap; da[CAPACITY] = realCap;
da[TYPE] = type; da[TYPE] = type;
return ehanValue((dynarr) (da + DATA)); return (dynarr) (da + DATA);
} }
void daFree(dynarr da) void daFree(dynarr da)
@ -77,140 +94,128 @@ void daFree(dynarr da)
free((size_t *) da - DATA); free((size_t *) da - DATA);
} }
GenericReturn daCopy(dynarr da) dynarr daCopy(dynarr da)
{ {
if (da == NULL) if (da == NULL) return NULL;
return ehanError("Expected: 'dynarr' got 'NULL'");
GenericReturn temp = _daCreate(daCap(da), daType(da), daSize(da)); dynarr newArr = _daCreate(daCap(da), daType(da), daSize(da));
if (ehanCheck(temp)) if (newArr == NULL)
return ehanError(resultError(temp)); return NULL;
dynarr newArr = resultGeneric(dynarr, temp);
memcpy(newArr, da, daSize(da) * daType(da)); memcpy(newArr, da, daSize(da) * daType(da));
return ehanValue(newArr); return newArr;
} }
GenericReturn daResize(dynarr da) dynarr daResize(dynarr da)
{ {
if (da == NULL) if (da == NULL)
return ehanError("Expected: 'dynarr' got 'NULL'"); return NULL;
GenericReturn temp = _daCreate(daCap(da) * 2, daType(da), daSize(da)); dynarr newArr = _daCreate((size_t) daCap(da) * 1.5, daType(da), daSize(da));
if (ehanCheck(temp)) if (newArr == NULL)
return ehanError(resultError(temp)); return NULL;
dynarr newArr = resultGeneric(dynarr, temp);
memcpy(newArr, da, daSize(da) * daType(da)); memcpy(newArr, da, daSize(da) * daType(da));
daFree(da); daFree(da);
return ehanValue(newArr); return newArr;
} }
GenericReturn _daPushLit(dynarr * da, size_t item) //GenericReturn _daPushLit(dynarr * da, size_t item)
{ //{
if (daSize(*da) >= daCap(*da)) // if (daSize(*da) >= daCap(*da))
{ // {
GenericReturn temp = daResize(*da); // *da = daResize(*da);
//
if (ehanCheck(temp)) // if (da == NULL)
return ehanError(resultError(temp)); // return ehanError("Failed to reallocate new da!");
// }
*da = resultGeneric(dynarr, temp); //
} // printf("A %zu\n", daType(*da));
//
switch (daType(*da)) // switch (daType(*da))
{ // {
case 1: { // case 1: {
*((char *)*da + daType(*da) * daSize(*da)) = item; // *((char *)*da + daType(*da) * daSize(*da)) = item;
} break; // } break;
//
case 2: { // case 2: {
*(short *)((char *)*da + daType(*da) * daSize(*da)) = item; // *(short *)((char *)*da + daType(*da) * daSize(*da)) = item;
} break; // } break;
//
case 4: { // case 4: {
*(int *)((char *)*da + daType(*da) * daSize(*da)) = item; // *(int *)((char *)*da + daType(*da) * daSize(*da)) = item;
} break; // } break;
//
case 8: { // case 8: {
*(long long int *)((char *)*da + daType(*da) * daSize(*da)) = item; // *(long long int *)((char *)*da + daType(*da) * daSize(*da)) = item;
} break; // } break;
//
default: // default:
return ehanError("Wrong type size"); // return ehanError("Wrong type size");
} // }
*daField(*da, SIZE) += 1; // printf("B\n");
// *daField(*da, SIZE) += 1;
return ehanValue(0); //
} // return ehanValue(0);
//}
GenericReturn _daPushFlt(dynarr * da, float item) //
{ //GenericReturn _daPushFlt(dynarr * da, float item)
if (daSize(*da) >= daCap(*da)) //{
{ // if (daSize(*da) >= daCap(*da))
GenericReturn temp = daResize(*da); // {
// if (!daResize(*da))
if (ehanCheck(temp)) // return ehanError("Failed to reallocate new da!");
return ehanError(resultError(temp)); // }
//
*da = resultGeneric(dynarr, temp); // switch (daType(*da))
} // {
// case 4: {
switch (daType(*da)) // *(float *)((char *)*da + daType(*da) * daSize(*da)) = item;
{ // } break;
case 4: { //
*(float *)((char *)*da + daType(*da) * daSize(*da)) = item; // case 8: {
} break; // *(double *)((char *)*da + daType(*da) * daSize(*da)) = item;
// } break;
case 8: { //
*(double *)((char *)*da + daType(*da) * daSize(*da)) = item; // case 16: {
} break; // *(long double *)((char *)*da + daType(*da) * daSize(*da)) = item;
// } break;
case 16: { //
*(long double *)((char *)*da + daType(*da) * daSize(*da)) = item; // default:
} break; // return ehanError("Wrong type size");
// }
default: //
return ehanError("Wrong type size"); // *daField(*da, SIZE) += 1;
} //
// return ehanValue(0);
*daField(*da, SIZE) += 1; //}
//
return ehanValue(0); //GenericReturn _daPushStr(dynarr * da, const char * str)
} //{
// if (daSize(*da) >= daCap(*da))
GenericReturn _daPushStr(dynarr * da, const char * str) // {
{ // if (!daResize(*da))
if (daSize(*da) >= daCap(*da)) // return ehanError("Failed to reallocate new da!");
{ // }
GenericReturn temp = daResize(*da); //
// memcpy((char *)(*da) + daSize(*da) * daType(*da), &str, daType(*da));
if (ehanCheck(temp)) // *daField(*da, SIZE) += 1;
return ehanError(resultError(temp)); //
// return ehanValue(0);
*da = resultGeneric(dynarr, temp); //}
} //
//void _daPop(dynarr da, void * elem)
memcpy((char *)(*da) + daSize(*da) * daType(*da), &str, daType(*da)); //{
*daField(*da, SIZE) += 1; // *daField(da, SIZE) -= 1;
// memcpy(elem, (char *)da + daSize(da) * daType(da), daType(da));
return ehanValue(0); //}
} //
//void daPopDiscard(dynarr da)
void _daPop(dynarr da, void * elem) //{
{ // *daField(da, SIZE) -= 1;
*daField(da, SIZE) -= 1; //}
memcpy(elem, (char *)da + daSize(da) * daType(da), daType(da));
}
void daPopDiscard(dynarr da)
{
*daField(da, SIZE) -= 1;
}
size_t * daField(dynarr da, enum daFields field) size_t * daField(dynarr da, enum daFields field)
{ {
@ -242,38 +247,40 @@ size_t daType(dynarr da)
return ((size_t *) da - DATA)[TYPE]; return ((size_t *) da - DATA)[TYPE];
} }
void daForeach(dynarr da, func f) //void daForeach(dynarr da, func f)
{ //{
for (size_t i = 0; i < daSize(da); ++i) // for (size_t i = 0; i < daSize(da); ++i)
f((char *) da + i * daType(da)); // f((char *) da + i * daType(da));
} //}
//
heapstr daToCStr(dynarr da) //heapstr daToCStr(dynarr da)
{ //{
char * buffer = (char *) calloc(1, daSize(da) + 1); // char * buffer = (char *) calloc(1, daSize(da) + 1);
if (buffer == NULL) return NULL; // if (buffer == NULL) return NULL;
//
memcpy(buffer, da, daSize(da) * daType(da)); // memcpy(buffer, da, daSize(da) * daType(da));
return buffer; // return buffer;
} //}
//
void daBzero(dynarr da) //void daBzero(dynarr da)
{ //{
memset(da, '\0', daCap(da)); // memset(da, '\0', daCap(da));
*daField(da, SIZE) = 0; // *daField(da, SIZE) = 0;
} //}
//
void * daGetRef(dynarr da, size_t index) //void * daGetRef(dynarr da, size_t index)
{ //{
if (index >= daSize(da)) // if (index >= daSize(da))
{ // {
fprintf(stderr, ("*------------------------------*\n")); // fprintf(stderr, ("*------------------------------*\n"));
fprintf(stderr, ("ERROR: Access out of bounds\n")); // fprintf(stderr, ("ERROR: Access out of bounds\n"));
fprintf(stderr, ("*------------------------------*\n")); // fprintf(stderr, ("*------------------------------*\n"));
return NULL; // return NULL;
} // }
//
return (void *)((char *)da + index * daType(da)); // return (void *)((char *)da + index * daType(da));
} //}
#endif // DA_IMPLEMENTATION #endif // DA_IMPLEMENTATION
#endif // DA_H_

149
example.c
View File

@ -1,23 +1,56 @@
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#define DA_IMPLEMENTATION #define DA_IMPLEMENTATION
#include "da.h" #include "da.h"
#define EHAN_IMPLEMENTATION #if 1
#include "ehan.h" #include <stdio.h>
#if 0
int main(void) int main(void)
{ {
dynarr(char *) da = daCreate(char *,4).val; dynarr(int) da = daCreate(int, 8);
dynarr(char *) da2 = daCreate(char *, 8);
dynarr(float) da3 = daCreate(float, 1);
if (!da) goto cleanup;
if (!da2) goto cleanup;
if (!da3) goto cleanup;
for (size_t i = 0; i < 1000; ++i) { printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da));
daPushStr(da, "hi"); printf("errno: %d\n", errno);
daAppend(da, 69);
printf("errno: %d\n", errno);
printf("%d\n", da[0]);
printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da));
da = daResize(da);
if (!da) goto cleanup;
printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da));
printf("DA2 -----\n");
daAppend(da2, "Hello, ");
daAppend(da2, "World!");
#define N 100000
for (size_t i = 0; i < N; ++i)
{
daAppend(da2, "AAA");
if (errno == 1) goto cleanup;
} }
for (size_t i = 0; i < daSize(da); ++i) { printf("%s%s\n", da2[0], da2[1]);
ILog("%zu: %s\n", i, da[i]); printf("%zu %zu %zu\n", daSize(da2), daCap(da2), daType(da2));
}
printf("DA3 -----\n");
daAppend(da3, 69.69);
daAppend(da3, 420.420);
printf("%.2f:%.3f\n", da3[0], da3[1]);
cleanup:
daFree(da3);
daFree(da2);
daFree(da); daFree(da);
return 0; return 0;
@ -39,21 +72,13 @@ int main(void)
printf("DA1\n"); printf("DA1\n");
printf("----------\n"); printf("----------\n");
GenericReturn gr = daCreate(unsigned short, 1); dynarr(unsigned short) da = daCreate(unsigned short, 1);
if (ehanCheck(gr))
{
ELog("%s\n", resultError(gr));
exit(1);
}
dynarr(unsigned short) da = resultGeneric(dynarr(unsigned short), gr);
daPush(da, 69); daPush(da, 69);
daPush(da, 420); daPush(da, 420);
daPush(da, 1337); daPush(da, 1337);
daPush(da, 34); daPush(da, 34);
daPush(da, 35); daPush(da, 35);
daPush(da, 1667); daPush(da, 1667);
unsigned short x = 0; unsigned short x = 0;
@ -65,69 +90,69 @@ int main(void)
printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da)); printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da));
printf("----------\n"); //printf("----------\n");
printf("DA2\n"); //printf("DA2\n");
printf("----------\n"); //printf("----------\n");
dynarr(char) da2 = daCreate(char, 1).val; //dynarr(char) da2 = daCreate(char, 1);
daPush(da2, 'H'); //daPush(da2, 'H');
daPush(da2, 'i'); //daPush(da2, 'i');
daPush(da2, ' '); //daPush(da2, ' ');
daPush(da2, 'm'); //daPush(da2, 'm');
daPush(da2, 'o'); //daPush(da2, 'o');
daPush(da2, 'm'); //daPush(da2, 'm');
daPush(da2, '?'); //daPush(da2, '?');
daPush(da2, '?'); //daPush(da2, '?');
*(char *)daGetRef(da2, 6) = '!'; //*(char *)daGetRef(da2, 6) = '!';
daPopDiscard(da2); //daPopDiscard(da2);
heapstr message = daToCStr(da2); //heapstr message = daToCStr(da2);
printf("%s\n", message); //printf("%s\n", message);
printf("----------\n"); //printf("----------\n");
printf("DA3\n"); //printf("DA3\n");
printf("----------\n"); //printf("----------\n");
dynarr(char *) da3 = daCreate(char *, 1).val; //dynarr(char *) da3 = daCreate(char *, 1);
for (size_t i = 0; i < 1000000; ++i) { //for (size_t i = 0; i < 1000000; ++i) {
daPush(da3, "Test"); // daPush(da3, "Test");
} //}
char * str; //char * str;
daPop(da3, str); //daPop(da3, str);
printf("%s\n", str); //printf("%s\n", str);
printf("----------\n"); //printf("----------\n");
printf("DA4\n"); //printf("DA4\n");
printf("----------\n"); //printf("----------\n");
dynarr(double) da4 = daCreate(double, 1).val; //dynarr(double) da4 = daCreate(double, 1);
daPush(da4, 69.692343); //daPush(da4, 69.692343);
printf("float: %F\n", da4[0]); //printf("float: %F\n", da4[0]);
printf("----------\n"); //printf("----------\n");
printf("DA5\n"); //printf("DA5\n");
printf("----------\n"); //printf("----------\n");
dynarr(char *) da5 = daCreate(char *, 1).val; //dynarr(char *) da5 = daCreate(char *, 1);
daPush(da5, "Hello, "); //daPush(da5, "Hello, ");
daPush(da5, "World!"); //daPush(da5, "World!");
DLog("%s%s\n", da5[0], da5[1]); //DLog("%s%s\n", da5[0], da5[1]);
cleanup: cleanup:
daFree(da5); //daFree(da5);
daFree(da4); //daFree(da4);
daFree(da3); //daFree(da3);
free(message); //free(message);
daFree(da2); //daFree(da2);
daFree(da); daFree(da);
return 0; return 0;