From ad0a224e916a0bfbb24d049dabdc3bf9fa7a8203 Mon Sep 17 00:00:00 2001 From: parys Date: Mon, 22 Jan 2024 12:05:01 +0100 Subject: [PATCH] minor changes --- .gitignore | 3 ++ LICENSE | 2 +- README.md | 3 +- da.h | 74 ++++++++++++++++++--------- example.c | 28 +++++++--- valgrind-out.txt | 130 ----------------------------------------------- 6 files changed, 76 insertions(+), 164 deletions(-) create mode 100644 .gitignore delete mode 100644 valgrind-out.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dfe31db --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.ctags +main +.valgrind-out.txt diff --git a/LICENSE b/LICENSE index d60e310..1410b8a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 parys +Copyright (c) 2023 Maciej Samborski 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: diff --git a/README.md b/README.md index a8d2d50..9b1786e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ # da -Simple dynamic array in C. \ No newline at end of file +A generic dynamic array in C. + diff --git a/da.h b/da.h index a2ca538..3d5214c 100644 --- a/da.h +++ b/da.h @@ -13,23 +13,27 @@ enum daFields { DATA = 3, }; -void * _daCreate(size_t initCapacity, size_t type, size_t size); -void * _daPush(void * da, void * item); -void _daPop(void * da, void * element); -void daFree(void * da); +typedef void * dynarr; +dynarr _daCreate(size_t initCapacity, size_t type, size_t size); +dynarr _daPush(dynarr da, void * item); +void _daPop(dynarr da, void * element); +void daFree(dynarr da); -size_t daSize(void * da); -size_t daCap(void * da); -size_t daType(void * da); +size_t daSize(dynarr da); +size_t daCap(dynarr da); +size_t daType(dynarr da); + +size_t * daField(dynarr da, enum daFields field); +void * daGetRef(dynarr da, size_t index); -size_t * daField(void * da, enum daFields field); typedef void(* func)(void * item); -void daForeach(void * da, func f); +void daForeach(dynarr da, func f); typedef char * heapstr; -heapstr daToCStr(void * da); -void daBzero(void * da); +heapstr daToCStr(dynarr da); +void daBzero(dynarr da); +#define dynarr(type) type * #define daCreate(type, cap) _daCreate(cap, sizeof(type), 0) #define daPush(da, item) da = _daPush(da, &item) #define daPop(da, item) _daPop(da, &item) @@ -38,30 +42,37 @@ void daBzero(void * da); #ifdef DA_IMPLEMENTATION -void * _daCreate(size_t cap, size_t type, size_t size) +dynarr _daCreate(size_t cap, size_t type, size_t size) { size_t * da = (size_t *) malloc(type * cap + DATA * sizeof(size_t)); da[SIZE] = size; da[CAPACITY] = cap; da[TYPE] = type; - return (void *) (da + DATA); + return (dynarr) (da + DATA); } -void daFree(void * da) +void daFree(dynarr da) { free((size_t *) da - DATA); } -void * daResize(void * da) +dynarr daCopy(dynarr da) { - void * temp = _daCreate(daCap(da) * 2, daType(da), daSize(da)); + dynarr temp = _daCreate(daCap(da), daType(da), daSize(da)); + memcpy(temp, da, daSize(da) * daType(da)); + return temp; +} + +dynarr daResize(dynarr da) +{ + dynarr temp = _daCreate(daCap(da) * 2, daType(da), daSize(da)); memcpy(temp, da, daSize(da) * daType(da)); daFree(da); return temp; } -void * _daPush(void * da, void * item) +dynarr _daPush(dynarr da, void * item) { if (daSize(da) >= daCap(da)) da = daResize(da); memcpy((char *)da + daSize(da) * daType(da), item, daType(da)); @@ -69,13 +80,13 @@ void * _daPush(void * da, void * item) return da; } -void _daPop(void * da, void * elem) +void _daPop(dynarr da, void * elem) { *daField(da, SIZE) -= 1; memcpy(elem, (char *)da + daSize(da) * daType(da), daType(da)); } -size_t * daField(void * da, enum daFields field) +size_t * daField(dynarr da, enum daFields field) { if (field < SIZE || field > TYPE) { @@ -89,38 +100,51 @@ size_t * daField(void * da, enum daFields field) return ((size_t *) da - DATA + field); } -size_t daSize(void * da) +size_t daSize(dynarr da) { return ((size_t *) da - DATA)[SIZE]; } -size_t daCap(void * da) +size_t daCap(dynarr da) { return ((size_t *) da - DATA)[CAPACITY]; } -size_t daType(void * da) +size_t daType(dynarr da) { return ((size_t *) da - DATA)[TYPE]; } -void daForeach(void * da, func f) +void daForeach(dynarr da, func f) { for (size_t i = 0; i < daSize(da); ++i) f((char *) da + i * daType(da)); } -heapstr daToCStr(void * da) +heapstr daToCStr(dynarr da) { char * buffer = (char *) calloc(1, daSize(da) + 1); memcpy(buffer, da,daSize(da) * daType(da)); return buffer; } -void daBzero(void * da) +void daBzero(dynarr da) { memset(da, '\0', daCap(da)); *daField(da, SIZE) = 0; } +void * daGetRef(dynarr da, size_t index) +{ + if (index >= daSize(da)) + { + fprintf(stderr, "*------------------------------*\n"); + fprintf(stderr, "ERROR: Access out of bounds\n"); + fprintf(stderr, "*------------------------------*\n"); + exit(1); + } + + return (void *)((char *)da + index * daType(da)); +} + #endif // DA_IMPLEMENTATION diff --git a/example.c b/example.c index 2774f94..97937c7 100644 --- a/example.c +++ b/example.c @@ -3,14 +3,23 @@ #define DA_IMPLEMENTATION #include "da.h" -void printDa(void * item) +void printDaU16(void * item) { printf("%hu\n", *((unsigned short *) item)); } +void printDaS32(void * item) +{ + printf("%hu\n", *((int *) item)); +} + int main(void) { - unsigned short * da = daCreate(unsigned short, 1); + printf("----------\n"); + printf("DA1\n"); + printf("----------\n"); + + dynarr(unsigned short) * da = daCreate(unsigned short, 1); unsigned short x = 69; daPush(da, x); @@ -24,16 +33,19 @@ int main(void) daPush(da, x); x = 1667; - x = 1667; daPush(da, x); daPop(da, x); - printf("popd: %hu\n", x); + printf("x: %hu\n", x); - daForeach(da, printDa); + daForeach(da, printDaU16); printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da)); - char * da2 = daCreate(char, 1); + printf("----------\n"); + printf("DA2\n"); + printf("----------\n"); + + dynarr(char) da2 = daCreate(char, 1); char y = 'H'; daPush(da2, y); @@ -47,9 +59,11 @@ int main(void) daPush(da2, y); y = 'm'; daPush(da2, y); - y = '!'; + y = '?'; daPush(da2, y); + *(char *)daGetRef(da2, 6) = '!'; + heapstr message = daToCStr(da2); printf("%s\n", message); diff --git a/valgrind-out.txt b/valgrind-out.txt deleted file mode 100644 index 7acd06f..0000000 --- a/valgrind-out.txt +++ /dev/null @@ -1,130 +0,0 @@ -==13091== Memcheck, a memory error detector -==13091== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. -==13091== Using Valgrind-3.21.0-d97fed7c3e-20230428 and LibVEX; rerun with -h for copyright info -==13091== Command: ./main -==13091== Parent PID: 12429 -==13091== ---13091-- ---13091-- Valgrind options: ---13091-- --leak-check=full ---13091-- --show-leak-kinds=all ---13091-- --track-origins=yes ---13091-- --verbose ---13091-- --log-file=valgrind-out.txt ---13091-- Contents of /proc/version: ---13091-- Linux version 6.5.7-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Tue, 10 Oct 2023 21:10:21 +0000 ---13091-- ---13091-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand-rdseed ---13091-- Page sizes: currently 4096, max supported 4096 ---13091-- Valgrind library directory: /usr/lib/valgrind ---13091-- Reading syms from /home/parys/programming/projects/da/main -==13091== Downloading debug info for /home/parys/programming/projects/da/main... -==13091== Server query failed: No such file or directory ---13091-- Reading syms from /usr/lib/ld-linux-x86-64.so.2 -==13091== Downloading debug info for /usr/lib/ld-linux-x86-64.so.2... ---13091-- Considering /home/parys/.cache/debuginfod_client/6ebd6e95dffa2afcbdaf7b7c91103b23ecf2b012/debuginfo .. ---13091-- .. CRC is valid -==13091== Successfully downloaded debug file for /usr/lib/ld-linux-x86-64.so.2 ---13091-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux -==13091== Downloading debug info for /usr/lib/valgrind/memcheck-amd64-linux... ---13091-- Considering /home/parys/.cache/debuginfod_client/4efee52aade45b84c3c34acbcf7e3a30dbc49e62/debuginfo .. ---13091-- .. CRC is valid -==13091== Successfully downloaded debug file for /usr/lib/valgrind/memcheck-amd64-linux ---13091-- object doesn't have a dynamic symbol table ---13091-- Scheduler: using generic scheduler lock implementation. ---13091-- Reading suppressions file: /usr/lib/valgrind/default.supp -==13091== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-13091-by-parys-on-??? -==13091== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-13091-by-parys-on-??? -==13091== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-13091-by-parys-on-??? -==13091== -==13091== TO CONTROL THIS PROCESS USING vgdb (which you probably -==13091== don't want to do, unless you know exactly what you're doing, -==13091== or are doing some strange experiment): -==13091== /usr/lib/valgrind/../../bin/vgdb --pid=13091 ...command... -==13091== -==13091== TO DEBUG THIS PROCESS USING GDB: start GDB like this -==13091== /path/to/gdb ./main -==13091== and then give GDB the following command -==13091== target remote | /usr/lib/valgrind/../../bin/vgdb --pid=13091 -==13091== --pid is optional if only one valgrind process is running -==13091== ---13091-- REDIR: 0x40241e0 (ld-linux-x86-64.so.2:strlen) redirected to 0x580c1122 (vgPlain_amd64_linux_REDIR_FOR_strlen) ---13091-- REDIR: 0x4022990 (ld-linux-x86-64.so.2:index) redirected to 0x580c113c (vgPlain_amd64_linux_REDIR_FOR_index) ---13091-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so -==13091== Downloading debug info for /usr/lib/valgrind/vgpreload_core-amd64-linux.so... ---13091-- Considering /home/parys/.cache/debuginfod_client/060a58c2256ae9a895586d0231020becccaadf3a/debuginfo .. ---13091-- .. CRC is valid -==13091== Successfully downloaded debug file for /usr/lib/valgrind/vgpreload_core-amd64-linux.so ---13091-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so -==13091== Downloading debug info for /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so... ---13091-- Considering /home/parys/.cache/debuginfod_client/23b76fcedd76ac77e136ed69676378bd047b5ff2/debuginfo .. ---13091-- .. CRC is valid -==13091== Successfully downloaded debug file for /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so -==13091== WARNING: new redirection conflicts with existing -- ignoring it ---13091-- old: 0x040241e0 (strlen ) R-> (0000.0) 0x580c1122 vgPlain_amd64_linux_REDIR_FOR_strlen ---13091-- new: 0x040241e0 (strlen ) R-> (2007.0) 0x04847fe0 strlen ---13091-- REDIR: 0x4022bc0 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4849100 (strcmp) ---13091-- REDIR: 0x4021ff0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x484cef0 (mempcpy) ---13091-- Reading syms from /usr/lib/libc.so.6 -==13091== Downloading debug info for /usr/lib/libc.so.6... ---13091-- Considering /home/parys/.cache/debuginfod_client/8bfe03f6bf9b6a6e2591babd0bbc266837d8f658/debuginfo .. ---13091-- .. CRC is valid -==13091== Successfully downloaded debug file for /usr/lib/libc.so.6 ---13091-- REDIR: 0x4024380 (ld-linux-x86-64.so.2:strncmp) redirected to 0x4848930 (strncmp) ---13091-- REDIR: 0x4937e10 (libc.so.6:strncasecmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49351c0 (libc.so.6:mempcpy) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4935520 (libc.so.6:stpcpy) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49b3430 (libc.so.6:__memmove_chk) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4958740 (libc.so.6:wmemcmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4936070 (libc.so.6:strcat) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4934950 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49b3310 (libc.so.6:__memcpy_chk) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) -==13091== WARNING: new redirection conflicts with existing -- ignoring it ---13091-- old: 0x049ec150 (__memcpy_chk_avx_una) R-> (2024.0) 0x0484c960 __memmove_chk ---13091-- new: 0x049ec150 (__memcpy_chk_avx_una) R-> (2030.0) 0x0484cff0 __memcpy_chk ---13091-- REDIR: 0x494ca00 (libc.so.6:wcslen) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4935370 (libc.so.6:memset) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x494d280 (libc.so.6:wcsnlen) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4938100 (libc.so.6:strnlen) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4938190 (libc.so.6:strpbrk) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49361f0 (libc.so.6:strcmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49352e0 (libc.so.6:memrchr) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x494b7c0 (libc.so.6:wcschr) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49360e0 (libc.so.6:index) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49381c0 (libc.so.6:rindex) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x494b870 (libc.so.6:wcscmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4935590 (libc.so.6:stpncpy) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49586c0 (libc.so.6:wmemchr) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4937fb0 (libc.so.6:strncmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49355f0 (libc.so.6:strcasecmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4937390 (libc.so.6:strcspn) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x494c7f0 (libc.so.6:wcscpy) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4937eb0 (libc.so.6:strncasecmp_l) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4936160 (libc.so.6:strchrnul) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4934860 (libc.so.6:bcmp) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4937320 (libc.so.6:strcpy) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4935690 (libc.so.6:strcasecmp_l) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4937d80 (libc.so.6:strlen) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4938050 (libc.so.6:strncpy) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49350a0 (libc.so.6:memmove) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) -==13091== Preferring higher priority redirection: ---13091-- old: 0x049ec180 (__memcpy_avx_unalign) R-> (2018.0) 0x0484a4e0 __memcpy_avx_unaligned_erms ---13091-- new: 0x049ec180 (__memcpy_avx_unalign) R-> (2018.1) 0x0484bf80 memmove ---13091-- REDIR: 0x49347e0 (libc.so.6:memchr) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x4938380 (libc.so.6:strspn) redirected to 0x48361c0 (_vgnU_ifunc_wrapper) ---13091-- REDIR: 0x49f0d70 (libc.so.6:__strrchr_avx2) redirected to 0x48479c0 (rindex) ---13091-- REDIR: 0x4930c10 (libc.so.6:malloc) redirected to 0x48417d0 (malloc) ---13091-- REDIR: 0x49ec180 (libc.so.6:__memcpy_avx_unaligned_erms) redirected to 0x484bf80 (memmove) ---13091-- REDIR: 0x49312e0 (libc.so.6:free) redirected to 0x48440c0 (free) ---13091-- REDIR: 0x49ee520 (libc.so.6:__strchrnul_avx2) redirected to 0x484c9d0 (strchrnul) ---13091-- REDIR: 0x49ec140 (libc.so.6:__mempcpy_avx_unaligned_erms) redirected to 0x484caf0 (mempcpy) ---13091-- REDIR: 0x4931c30 (libc.so.6:calloc) redirected to 0x4846900 (calloc) ---13091-- REDIR: 0x49eeec0 (libc.so.6:__strlen_avx2) redirected to 0x4847ec0 (strlen) -==13091== -==13091== HEAP SUMMARY: -==13091== in use at exit: 0 bytes in 0 blocks -==13091== total heap usage: 10 allocs, 10 frees, 1,269 bytes allocated -==13091== -==13091== All heap blocks were freed -- no leaks are possible -==13091== -==13091== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)