libsheepy

C lib for handling text files, strings and json like data structure with an object oriented system
git clone https://spartatek.se/git/libsheepy.git
Log | Files | Refs | README | LICENSE

commit b119ae6bb2caf40d84abaf30ed6036a17ed156c7
parent 73e1ceda198b9145ac29a9a99bfcbdda4acade59
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sun, 21 Jul 2019 16:38:06 +0200

add macro defines, add bitfield array, add define for packed attribute

completion.txt      |  14 +++++
documentation.md    | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
release/libsheepy.h | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++-
src/libsheepy.h     | 154 +++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 470 insertions(+), 3 deletions(-)

Diffstat:
Mcompletion.txt | 14++++++++++++++
Mdocumentation.md | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mrelease/libsheepy.h | 158++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/libsheepy.h | 154++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 470 insertions(+), 3 deletions(-)

diff --git a/completion.txt b/completion.txt @@ -9,6 +9,10 @@ boolS(x) XSUCCESS XFAILURE exitFailure(data) +procbegin +procend +funcbegin +funcend stringifyExpr(expr) stringifyExpr1(expr) libsheepyErrorMask @@ -1037,6 +1041,7 @@ vectorAppend(name, v) vectorClearPush(name) vectorPop vectorDelLast +vectorPushCount(name, countp) vectorSet(name, index, v) vectorAt vectorPtr @@ -1283,6 +1288,13 @@ bitset1(name, at, index) bitsetSet(name, at, index, value) bitsetInv(name, at, index) bitsetGet(name, at, index) +FIELD_SET(dst, val, msb, lsb) +FIELD_GET +FIELD_SETL(dst, index, val, len) +BITFIELD_SET(array, index, val, len) +BITFIELD_GET(array, index, len) +BITFIELD_SIZE(count, len, containerType) +BITFIELD_VAR(array, count, len) uint64_t getMonotonicTime(void) int nanoSleepF(uint64_t time) nanoSleep(time) @@ -1291,7 +1303,9 @@ nanoSleepE(time, cmd) usSleep(time) msSleep(time) DEPRECATED +PACKED DEPRECATED +PACKED initiateG(self) allocG(value) freeO(obj) diff --git a/documentation.md b/documentation.md @@ -38,6 +38,10 @@ boolS(x) XSUCCESS XFAILURE exitFailure(data) +procbegin +procend +funcbegin +funcend stringifyExpr(expr) stringifyExpr1(expr) libsheepyErrorMask @@ -1066,6 +1070,7 @@ vectorAppend(name, v) vectorClearPush(name) vectorPop vectorDelLast +vectorPushCount(name, countp) vectorSet(name, index, v) vectorAt vectorPtr @@ -1312,6 +1317,13 @@ bitset1(name, at, index) bitsetSet(name, at, index, value) bitsetInv(name, at, index) bitsetGet(name, at, index) +FIELD_SET(dst, val, msb, lsb) +FIELD_GET +FIELD_SETL(dst, index, val, len) +BITFIELD_SET(array, index, val, len) +BITFIELD_GET(array, index, len) +BITFIELD_SIZE(count, len, containerType) +BITFIELD_VAR(array, count, len) uint64_t getMonotonicTime(void) int nanoSleepF(uint64_t time) nanoSleep(time) @@ -1320,7 +1332,9 @@ nanoSleepE(time, cmd) usSleep(time) msSleep(time) DEPRECATED +PACKED DEPRECATED +PACKED ``` ## Prototypes and macros @@ -1353,6 +1367,32 @@ extern const bool FALSE; */ #define exitFailure(data) \ /* + * defines for macro begin and end + * + * Macros not returning values are usually written as do while loops: + * #define macro(value) do{ + * puts(value); + * } while(0) + * + * Using the defines below: + * #define macro(value) procbegin\ + * puts(value);\ + * procend + * + * procbegin and procend are for macros not returning a value (like procedure in pascal) + * funcbegin and funcend are for macros returning a value like functions + * + * Macro returning a value (GNU extension): + * #define macro(value) funcbegin\ + * int returnResult = value + 2;\ + * returnResult;\ + * funcend + */ +#define procbegin do{ +#define procend }while(0) +#define funcbegin ({ +#define funcend }) +/* * stringify Expression - Turn expression into a string literal * * Example: @@ -1510,6 +1550,9 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount]; #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #define COUNT_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) #define ARRAY_SIZE COUNT_ELEMENTS +/* + * get a bitfield in an integer (opposite of FIELD_SET) + */ #define EXTRACT(x, msb, lsb) ((~(0xFFFFFFFFFFFFFFFEUL << (msb)) & (x)) >> (lsb)) /* * compare a to b @@ -4364,6 +4407,15 @@ void **iListDel(void ***list, intmax_t start, intmax_t end); */ #define vectorDelLast sliceDelLast /* + * push multiple elements at once + * + * \param + * name vector + * \param + * countp number of elements to add + */ +#define vectorPushCount(name, countp) procbegin\ +/* * set value at index and clearResize vector when index is outside vector maxCount */ #define vectorSet(name, index, v) do{\ @@ -6022,6 +6074,99 @@ bool fiberPrepend(void *ctx, int thisSlot, fiberFT func); /* * end bitset */ +/* + * bitfield array + * + * a field is a group of bit representing an int stored in a larger int + * + * bitfield array is an array of fields (short int) similar to bitset + * + * Example: + * + * u64 v = 0; // field storage + * FIELD_SET(v, 3, 1, 0); // field is 2 bits from bit 0 to bit 1, set value 3 + * + * u8 field = FIELD_GET(v, 1, 0); // get value in field at bit 0 to 1 + * + * // declare a bitfield array + * // the array has 256 elements and each element is a 2 bit integer + * BITFIELD_VAR(bitfields, 256, 2) = init0Var; + * + * // set value for element at index 255 + * BITFIELD_SET(bitfields, 255, 3, 2); + * // get value for element at index 255 + * v = BITFIELD_GET(bitfields, 255, 2); + * + */ +/* + * set bitfield value in destination (opposite of EXTRACT macro) + * + * only bits between msb and lsb are set in dst + * + * \param + * dst destination, unsigned integer (u8, u16, u32, u64) + * \param + * val value to set, the value is shifted to lsb + * \param + * msb most significant bit in dst to be set + * \param + * lsb least significant bit in dst to be set + */ +#define FIELD_SET(dst, val, msb, lsb) dst = (/*clear field in dst*/ (dst) & ((0xFFFFFFFFFFFFFFFEUL << (msb)) | ((1UL<<(lsb))-1) )) | (/*clear highest bits in val and shift to field lsb*/(~(0xFFFFFFFFFFFFFFFEUL << ((msb)-(lsb))) & (val)) << (lsb)) +#define FIELD_GET EXTRACT +/* + * set bitfield value in destination, given bitfield index and length + * + * (index+1)*len-1 must be lower or equal to 8*sizeof(dst), + * otherwise val will be truncated + * + * \param + * dst destination, unsigned integer (u8, u16, u32, u64) + * \param + * index index of the bitfield in dst (bit index*len is lsb) + * \param + * val value to set, the value is shifted to lsb + * \param + * len bitfield length in dst + */ +#define FIELD_SETL(dst, index, val, len) FIELD_SET(dst, val, ((index)+1)*(len)-1, (index)*(len)) +/* + * set bitfield value in array of bitfields + * the boundaries are not checked + * + * \param + * array array of u64 + * \param + * index index of the bitfield in array (bit index*len is lsb) + * \param + * val value to set, the value is shifted to the correct position + * \param + * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) + */ +#define BITFIELD_SET(array, index, val, len) FIELD_SET((array)[((index)*(len))/64], val, ((index)*(len))%64+(len)-1, ((index)*(len))%64) +/* + * get bitfield value in array of bitfields + * the boundaries are not checked + * + * \param + * array array of u64 + * \param + * index index of the bitfield in array (bit index*len is lsb) + * \param + * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) + */ +#define BITFIELD_GET(array, index, len) EXTRACT((array)[((index)*(len))/64], ((index)*(len))%64+(len)-1, ((index)*(len))%64) +/* + * return number of u64 necessary to hold count bitfields of length len + */ +#define BITFIELD_SIZE(count, len, containerType) BUCKETS((count)*(len), 8 * sizeof(containerType)) +/* + * declare an array to hold count bitfields of length len + */ +#define BITFIELD_VAR(array, count, len) u64 array[BITFIELD_SIZE(count, len, u64)] +/* + * end bitfield + */ // get monotonic time in ns uint64_t getMonotonicTime(void); // sleep nanoseconds @@ -6036,7 +6181,9 @@ int nanoSleepF(uint64_t time); /** sleep miliseconds */ #define msSleep(time) pError0(nanoSleepF(1000000 * (uint64_t)time)) #define DEPRECATED __attribute__ ((deprecated)) +#define PACKED __attribute__((__packed__)) #define DEPRECATED +#define PACKED // vim: set expandtab ts=2 sw=2: ``` diff --git a/release/libsheepy.h b/release/libsheepy.h @@ -96,7 +96,7 @@ // version accoring to the version package: Release.Major.minor.patch // https://noulin.net/version/file/README.md.html -#define LIBSHEEPY_VERSION "1.0.6" +#define LIBSHEEPY_VERSION "1.0.7" #ifndef SH_PREFIX #define SH_PREFIX(NAME) NAME @@ -140,6 +140,34 @@ extern const bool FALSE; if (!data) \ exit(EXIT_FAILURE); + +/** + * defines for macro begin and end + * + * Macros not returning values are usually written as do while loops: + * #define macro(value) do{ + * puts(value); + * } while(0) + * + * Using the defines below: + * #define macro(value) procbegin\ + * puts(value);\ + * procend + * + * procbegin and procend are for macros not returning a value (like procedure in pascal) + * funcbegin and funcend are for macros returning a value like functions + * + * Macro returning a value (GNU extension): + * #define macro(value) funcbegin\ + * int returnResult = value + 2;\ + * returnResult;\ + * funcend + */ +#define procbegin do{ +#define procend }while(0) +#define funcbegin ({ +#define funcend }) + /** * stringify Expression - Turn expression into a string literal * @@ -323,6 +351,10 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount]; #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #define COUNT_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) #define ARRAY_SIZE COUNT_ELEMENTS + +/** + * get a bitfield in an integer (opposite of FIELD_SET) + */ #define EXTRACT(x, msb, lsb) ((~(0xFFFFFFFFFFFFFFFEUL << (msb)) & (x)) >> (lsb)) /** @@ -3370,7 +3402,9 @@ void **iListDel(void ***list, intmax_t start, intmax_t end); #define sliceInject(name, index) do {\ var UNIQVAR(idx) = index;\ slicePush(name);\ - memmove(slicePtr(name, UNIQVAR(idx) +1), slicePtr(name, UNIQVAR(idx)), ((name)->count - UNIQVAR(idx)) * sizeof (name)->array[0]);\ + if (index < sliceCount(name)) {\ + memmove(slicePtr(name, UNIQVAR(idx) +1), slicePtr(name, UNIQVAR(idx)), ((name)->count - UNIQVAR(idx)-1) * sizeof (name)->array[0]);\ + }\ } while(0) /** @@ -4616,6 +4650,24 @@ void **iListDel(void ***list, intmax_t start, intmax_t end); #define vectorDelLast sliceDelLast /** + * push multiple elements at once + * + * \param + * name vector + * \param + * countp number of elements to add + */ +#define vectorPushCount(name, countp) procbegin\ + u32 UNIQVAR(count) = countp;\ + if (((name)->count + UNIQVAR(count)) > (name)->maxCount) {\ + (name)->maxCount += UNIQVAR(count);\ + (name)->array = realloc((name)->array, (name)->maxCount * sizeof (name)->array[0]);\ + }\ + (name)->count += UNIQVAR(count);\ + procend + + +/** * set value at index and clearResize vector when index is outside vector maxCount */ #define vectorSet(name, index, v) do{\ @@ -7185,7 +7237,107 @@ bool fiberPrepend(void *ctx, int thisSlot, fiberFT func); * end bitset */ +/** + * bitfield array + * + * a field is a group of bit representing an int stored in a larger int + * + * bitfield array is an array of fields (short int) similar to bitset + * + * Example: + * + * u64 v = 0; // field storage + * FIELD_SET(v, 3, 1, 0); // field is 2 bits from bit 0 to bit 1, set value 3 + * + * u8 field = FIELD_GET(v, 1, 0); // get value in field at bit 0 to 1 + * + * // declare a bitfield array + * // the array has 256 elements and each element is a 2 bit integer + * BITFIELD_VAR(bitfields, 256, 2) = init0Var; + * + * // set value for element at index 255 + * BITFIELD_SET(bitfields, 255, 3, 2); + * // get value for element at index 255 + * v = BITFIELD_GET(bitfields, 255, 2); + * + */ + +/** + * set bitfield value in destination (opposite of EXTRACT macro) + * + * only bits between msb and lsb are set in dst + * + * \param + * dst destination, unsigned integer (u8, u16, u32, u64) + * \param + * val value to set, the value is shifted to lsb + * \param + * msb most significant bit in dst to be set + * \param + * lsb least significant bit in dst to be set + */ +#define FIELD_SET(dst, val, msb, lsb) dst = (/*clear field in dst*/ (dst) & ((0xFFFFFFFFFFFFFFFEUL << (msb)) | ((1UL<<(lsb))-1) )) | (/*clear highest bits in val and shift to field lsb*/(~(0xFFFFFFFFFFFFFFFEUL << ((msb)-(lsb))) & (val)) << (lsb)) + +#define FIELD_GET EXTRACT +/** + * set bitfield value in destination, given bitfield index and length + * + * (index+1)*len-1 must be lower or equal to 8*sizeof(dst), + * otherwise val will be truncated + * + * \param + * dst destination, unsigned integer (u8, u16, u32, u64) + * \param + * index index of the bitfield in dst (bit index*len is lsb) + * \param + * val value to set, the value is shifted to lsb + * \param + * len bitfield length in dst + */ +#define FIELD_SETL(dst, index, val, len) FIELD_SET(dst, val, ((index)+1)*(len)-1, (index)*(len)) + +/** + * set bitfield value in array of bitfields + * the boundaries are not checked + * + * \param + * array array of u64 + * \param + * index index of the bitfield in array (bit index*len is lsb) + * \param + * val value to set, the value is shifted to the correct position + * \param + * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) + */ +#define BITFIELD_SET(array, index, val, len) FIELD_SET((array)[((index)*(len))/64], val, ((index)*(len))%64+(len)-1, ((index)*(len))%64) + +/** + * get bitfield value in array of bitfields + * the boundaries are not checked + * + * \param + * array array of u64 + * \param + * index index of the bitfield in array (bit index*len is lsb) + * \param + * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) + */ +#define BITFIELD_GET(array, index, len) EXTRACT((array)[((index)*(len))/64], ((index)*(len))%64+(len)-1, ((index)*(len))%64) + +/** + * return number of u64 necessary to hold count bitfields of length len + */ +#define BITFIELD_SIZE(count, len, containerType) BUCKETS((count)*(len), 8 * sizeof(containerType)) + +/** + * declare an array to hold count bitfields of length len + */ +#define BITFIELD_VAR(array, count, len) u64 array[BITFIELD_SIZE(count, len, u64)] + +/** + * end bitfield + */ // get monotonic time in ns uint64_t getMonotonicTime(void); @@ -7210,9 +7362,11 @@ int nanoSleepF(uint64_t time); #ifdef __GNUC__ #define UNUSED __attribute__ ((unused)) #define DEPRECATED __attribute__ ((deprecated)) +#define PACKED __attribute__((__packed__)) #else #define UNUSED #define DEPRECATED +#define PACKED #endif #endif // _libsheepyH diff --git a/src/libsheepy.h b/src/libsheepy.h @@ -96,7 +96,7 @@ // version accoring to the version package: Release.Major.minor.patch // https://noulin.net/version/file/README.md.html -#define LIBSHEEPY_VERSION "1.0.6" +#define LIBSHEEPY_VERSION "1.0.7" #ifndef SH_PREFIX #define SH_PREFIX(NAME) NAME @@ -140,6 +140,34 @@ extern const bool FALSE; if (!data) \ exit(EXIT_FAILURE); + +/** + * defines for macro begin and end + * + * Macros not returning values are usually written as do while loops: + * #define macro(value) do{ + * puts(value); + * } while(0) + * + * Using the defines below: + * #define macro(value) procbegin\ + * puts(value);\ + * procend + * + * procbegin and procend are for macros not returning a value (like procedure in pascal) + * funcbegin and funcend are for macros returning a value like functions + * + * Macro returning a value (GNU extension): + * #define macro(value) funcbegin\ + * int returnResult = value + 2;\ + * returnResult;\ + * funcend + */ +#define procbegin do{ +#define procend }while(0) +#define funcbegin ({ +#define funcend }) + /** * stringify Expression - Turn expression into a string literal * @@ -323,6 +351,10 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount]; #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #define COUNT_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) #define ARRAY_SIZE COUNT_ELEMENTS + +/** + * get a bitfield in an integer (opposite of FIELD_SET) + */ #define EXTRACT(x, msb, lsb) ((~(0xFFFFFFFFFFFFFFFEUL << (msb)) & (x)) >> (lsb)) /** @@ -4618,6 +4650,24 @@ void **iListDel(void ***list, intmax_t start, intmax_t end); #define vectorDelLast sliceDelLast /** + * push multiple elements at once + * + * \param + * name vector + * \param + * countp number of elements to add + */ +#define vectorPushCount(name, countp) procbegin\ + u32 UNIQVAR(count) = countp;\ + if (((name)->count + UNIQVAR(count)) > (name)->maxCount) {\ + (name)->maxCount += UNIQVAR(count);\ + (name)->array = realloc((name)->array, (name)->maxCount * sizeof (name)->array[0]);\ + }\ + (name)->count += UNIQVAR(count);\ + procend + + +/** * set value at index and clearResize vector when index is outside vector maxCount */ #define vectorSet(name, index, v) do{\ @@ -7187,7 +7237,107 @@ bool fiberPrepend(void *ctx, int thisSlot, fiberFT func); * end bitset */ +/** + * bitfield array + * + * a field is a group of bit representing an int stored in a larger int + * + * bitfield array is an array of fields (short int) similar to bitset + * + * Example: + * + * u64 v = 0; // field storage + * FIELD_SET(v, 3, 1, 0); // field is 2 bits from bit 0 to bit 1, set value 3 + * + * u8 field = FIELD_GET(v, 1, 0); // get value in field at bit 0 to 1 + * + * // declare a bitfield array + * // the array has 256 elements and each element is a 2 bit integer + * BITFIELD_VAR(bitfields, 256, 2) = init0Var; + * + * // set value for element at index 255 + * BITFIELD_SET(bitfields, 255, 3, 2); + * // get value for element at index 255 + * v = BITFIELD_GET(bitfields, 255, 2); + * + */ +/** + * set bitfield value in destination (opposite of EXTRACT macro) + * + * only bits between msb and lsb are set in dst + * + * \param + * dst destination, unsigned integer (u8, u16, u32, u64) + * \param + * val value to set, the value is shifted to lsb + * \param + * msb most significant bit in dst to be set + * \param + * lsb least significant bit in dst to be set + */ +#define FIELD_SET(dst, val, msb, lsb) dst = (/*clear field in dst*/ (dst) & ((0xFFFFFFFFFFFFFFFEUL << (msb)) | ((1UL<<(lsb))-1) )) | (/*clear highest bits in val and shift to field lsb*/(~(0xFFFFFFFFFFFFFFFEUL << ((msb)-(lsb))) & (val)) << (lsb)) + +#define FIELD_GET EXTRACT + +/** + * set bitfield value in destination, given bitfield index and length + * + * (index+1)*len-1 must be lower or equal to 8*sizeof(dst), + * otherwise val will be truncated + * + * \param + * dst destination, unsigned integer (u8, u16, u32, u64) + * \param + * index index of the bitfield in dst (bit index*len is lsb) + * \param + * val value to set, the value is shifted to lsb + * \param + * len bitfield length in dst + */ +#define FIELD_SETL(dst, index, val, len) FIELD_SET(dst, val, ((index)+1)*(len)-1, (index)*(len)) + +/** + * set bitfield value in array of bitfields + * the boundaries are not checked + * + * \param + * array array of u64 + * \param + * index index of the bitfield in array (bit index*len is lsb) + * \param + * val value to set, the value is shifted to the correct position + * \param + * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) + */ +#define BITFIELD_SET(array, index, val, len) FIELD_SET((array)[((index)*(len))/64], val, ((index)*(len))%64+(len)-1, ((index)*(len))%64) + +/** + * get bitfield value in array of bitfields + * the boundaries are not checked + * + * \param + * array array of u64 + * \param + * index index of the bitfield in array (bit index*len is lsb) + * \param + * len bitfield length in array, must divide 64 (2, 4, 8, 16, 32) + */ +#define BITFIELD_GET(array, index, len) EXTRACT((array)[((index)*(len))/64], ((index)*(len))%64+(len)-1, ((index)*(len))%64) + +/** + * return number of u64 necessary to hold count bitfields of length len + */ +#define BITFIELD_SIZE(count, len, containerType) BUCKETS((count)*(len), 8 * sizeof(containerType)) + +/** + * declare an array to hold count bitfields of length len + */ +#define BITFIELD_VAR(array, count, len) u64 array[BITFIELD_SIZE(count, len, u64)] + +/** + * end bitfield + */ // get monotonic time in ns uint64_t getMonotonicTime(void); @@ -7212,9 +7362,11 @@ int nanoSleepF(uint64_t time); #ifdef __GNUC__ #define UNUSED __attribute__ ((unused)) #define DEPRECATED __attribute__ ((deprecated)) +#define PACKED __attribute__((__packed__)) #else #define UNUSED #define DEPRECATED +#define PACKED #endif #endif // _libsheepyH