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 9d8a2307b35e4943508386531e888888f40dad01
parent 0315d26d9fbef3339d5549025cf60d2b85c400e0
Author: Remy Noulin <loader2x@gmail.com>
Date:   Thu, 24 Oct 2024 15:53:45 +0200

add btt functions reallocB, bInsertB, bDelB, bDelElemB, readFileB, writeFileB

release/libsheepy.h   |   2 +-
release/libsheepyBt.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++
release/libsheepyBt.h |  19 +++++
src/libsheepy.h       |   2 +-
src/libsheepyBt.c     | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/libsheepyBt.h     |  19 +++++
6 files changed, 502 insertions(+), 2 deletions(-)

Diffstat:
Mrelease/libsheepy.h | 2+-
Mrelease/libsheepyBt.c | 231+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mrelease/libsheepyBt.h | 19+++++++++++++++++++
Msrc/libsheepy.h | 2+-
Msrc/libsheepyBt.c | 231+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/libsheepyBt.h | 19+++++++++++++++++++
6 files changed, 502 insertions(+), 2 deletions(-)

diff --git a/release/libsheepy.h b/release/libsheepy.h @@ -98,7 +98,7 @@ // version accoring to the version package: Release.Major.minor.patch // https://noulin.net/version/file/README.md.html -#define LIBSHEEPY_VERSION "2.2.14" +#define LIBSHEEPY_VERSION "2.2.15" #ifndef SH_PREFIX #define SH_PREFIX(NAME) NAME diff --git a/release/libsheepyBt.c b/release/libsheepyBt.c @@ -62,6 +62,18 @@ btt *allocNewB(u32 allocateSize) { ret r; } +bool reallocB(btt *b, size_t newSize) { + if (!b or (/*read only*/b->alloc == 0 and b->len > 0) or newSize == 0/*==0 will free the b->b buffer*/) ret false; + u8 *tmp = realloc(b->b, newSize); + if (!tmp) ret false; /*realloc failed*/ + b->b = tmp; + b->alloc = newSize; + // when newSize is shorter than the buffer length + // truncate the buffer + if (newSize < b->len) b->len = newSize; + ret true; +} + // not needed, use charB or ccharB // /** // * set buf in the b btt object @@ -359,6 +371,225 @@ btt pushPBPB(const btt *b, const btt *s) { // TODO pushManyPBPB... /** + * buffer insert string in string at index + * + * return string with toInsert at index + * negative indexes are allowed + * index -1 is the end of the array and is equivalent to index len + * + * \param + * string + * \param + * index in string + * \param + * toInsert string + * \return + * modified string + * NULL unchanged string when string is NULL or invalid index + */ +btt *bInsertB(btt *b, int64_t index, const char *toInsert) { + if (!b or !b->b or !toInsert) return NULL; + if (b->alloc == 0 and b->len > 0) { + // string is not allocated so it is readonly + return(NULL); + } + int64_t blen = (int64_t)b->len; + + if (!blen && index == -1) { + // empty string, index -1 is equal to 0 + index = 0; + } + bool neg = false; + if (index < 0) { + neg = true; + } + + if (index > blen) { + return(NULL); + } + if (neg) { + index++; + } + if (index < -blen) { + return(NULL); + } + if (neg) { + index = blen + index; + } + + size_t len = strlen(toInsert); + u32 newsize = makeRoom(b->len, b->alloc, len); + // check if there is enough space + if (newsize > b->alloc) { + u8 *tmp = realloc(b->b, newsize); + if (!tmp) return NULL; + b->b = tmp; + b->alloc = newsize; + } + // when index == b->len, just add toInsert at the end + if (index < b->len) { + memmove(b->b+index+len, b->b+index, b->len - index); + } + // copy toInsert at index in b + memcpy(b->b+index, toInsert, len); + b->len += len; + return b; +} + +/** + * buffer delete string + * + * return string without the string between start and end + * negative indexes are allowed + * + * \param + * string to delete + * \param + * start: start index, must be in the string + * \param + * end: end index, must be in the string after start + * \return + * sliced string + * unchanged string when start=end + * NULL when start and end are not set correctly + * or when input string is NULL or when malloc failed or when end is under start + */ +btt *bDelB(btt *string, int64_t start, int64_t end) { + int64_t len; + + // sanity checks + if (!string or !string->b) { + return(NULL); + } + if (string->alloc == 0 and string->len > 0) { + // string is not allocated so it is readonly + return(NULL); + } + + len = (int64_t)string->len; + + if (start >= len) { + start = len; + } + if (end > len) { + end = len; + } + if (start <= -len) { + start = -len; + } + if (end <= -len) { + end = -len; + } + if (start < 0) { + start = len + start; + } + if (end <= 0) { + end = len + end; + } + if (end < start) { + return(NULL); + } + + if (start == end) { + return(string); + } + + // start < end < len + // copy range to a new string + int64_t n; + n = end - start; + memmove(string->b+start, string->b+start+n, (size_t)(len-n-start)); + string->len -= n; + + return(string); +} + +/** + * buffer delete element/character string + * + * return string without the character at given index + * negative indexes are allowed + * + * \param + * string to delete + * \param + * index: must be in the string, -1 is the last character in the string + * \return + * string with one less character + * NULL when input string is NULL or invalid index + */ +btt *bDelElemB(btt *string, int64_t index) { + int64_t len; + + // sanity checks + if (!string or !string->b) { + return(NULL); + } + if (string->alloc == 0 and string->len > 0) { + // string is not allocated so it is readonly + return(NULL); + } + + len = (int64_t)string->len; + if (index >= len) { + return(NULL); + } + if (index < -len) { + return(NULL); + } + if (index < 0) { + index = len + index; + } + + // when index == len-1 only decrement len, delete last char and there is nothing to move + if (index < len-1) { + memmove(string->b+index, string->b+index+1, string->len - index-1); + } + string->len--; + return string; +} + +/** + * read file to new btt + * + * The function allocates the buffer + * + * \param + * filePath path to file + * \return + * data from file in a btt (you must free the pointer) + * (btt).b==NULL error + */ +btt readFileB(const char *filePath) { + btt r = init0Var; + ssize_t len = readFile(filePath, (void**)&r.b); + if (len == -1) { + r.b = NULL; + return r; + } + r.len = r.alloc = len; + return r; +} + +/** + * write btt to file + * + * \param + * filePath path to file + * btt + * \return + * 1 success + * 0 error + */ +int writeFileB(const char *filePath, btt b) { + // sanity checks + if (!b.b) { + return 0; + } + return writeFile(filePath, b.b, b.len); +} + +/** * split b in vb static vector * the vector is not reallocated */ diff --git a/release/libsheepyBt.h b/release/libsheepyBt.h @@ -324,6 +324,9 @@ btt newB(u32 allocateSize); // return a heap allocated btt object with a heap allocated buffer of size allocateSize btt *allocNewB(u32 allocateSize); +// reallocate b.b +bool reallocB(btt *b, size_t newSize); + // return a heap allocated btt object with buf assigned to it btt *allocCharB(char *buf); @@ -378,6 +381,8 @@ btt *dupPB(btt *b); // // NO - growzero: memset 0 to new part // ..slice // ..trim +// countB +// findB // formatB // iFormatB // bFormatB @@ -497,6 +502,15 @@ btt pushPBB(const btt *b, const btt s); btt pushPBPB(const btt *b, const btt *s); // TODO pushManyPBPB... +// insert string in string +btt *bInsertB(btt *b, int64_t index, const char *s); + +// delete range in string +btt *bDelB(btt *string, int64_t start, int64_t end); + +// del a character in string +btt *bDelElemB(btt *string, int64_t index); + #define appendBG pushBG #define pushBG(b, s) _Generic( b,\ btt: _Generic(s,\ @@ -569,6 +583,11 @@ btt pushPBPB(const btt *b, const btt *s); // return(1); // } + +// (btt).b is NULL on error +btt readFileB(const char *filePath) MUST_CHECK; +int writeFileB(const char *filePath, btt b) MUST_CHECK; + // split b in vb static vector // the vector is not reallocated vbtt *sasplitB(vbtt *vb, const btt b, const btt delim); diff --git a/src/libsheepy.h b/src/libsheepy.h @@ -98,7 +98,7 @@ // version accoring to the version package: Release.Major.minor.patch // https://noulin.net/version/file/README.md.html -#define LIBSHEEPY_VERSION "2.2.14" +#define LIBSHEEPY_VERSION "2.2.15" #ifndef SH_PREFIX #define SH_PREFIX(NAME) NAME diff --git a/src/libsheepyBt.c b/src/libsheepyBt.c @@ -62,6 +62,18 @@ btt *allocNewB(u32 allocateSize) { ret r; } +bool reallocB(btt *b, size_t newSize) { + if (!b or (/*read only*/b->alloc == 0 and b->len > 0) or newSize == 0/*==0 will free the b->b buffer*/) ret false; + u8 *tmp = realloc(b->b, newSize); + if (!tmp) ret false; /*realloc failed*/ + b->b = tmp; + b->alloc = newSize; + // when newSize is shorter than the buffer length + // truncate the buffer + if (newSize < b->len) b->len = newSize; + ret true; +} + // not needed, use charB or ccharB // /** // * set buf in the b btt object @@ -359,6 +371,225 @@ btt pushPBPB(const btt *b, const btt *s) { // TODO pushManyPBPB... /** + * buffer insert string in string at index + * + * return string with toInsert at index + * negative indexes are allowed + * index -1 is the end of the array and is equivalent to index len + * + * \param + * string + * \param + * index in string + * \param + * toInsert string + * \return + * modified string + * NULL unchanged string when string is NULL or invalid index + */ +btt *bInsertB(btt *b, int64_t index, const char *toInsert) { + if (!b or !b->b or !toInsert) return NULL; + if (b->alloc == 0 and b->len > 0) { + // string is not allocated so it is readonly + return(NULL); + } + int64_t blen = (int64_t)b->len; + + if (!blen && index == -1) { + // empty string, index -1 is equal to 0 + index = 0; + } + bool neg = false; + if (index < 0) { + neg = true; + } + + if (index > blen) { + return(NULL); + } + if (neg) { + index++; + } + if (index < -blen) { + return(NULL); + } + if (neg) { + index = blen + index; + } + + size_t len = strlen(toInsert); + u32 newsize = makeRoom(b->len, b->alloc, len); + // check if there is enough space + if (newsize > b->alloc) { + u8 *tmp = realloc(b->b, newsize); + if (!tmp) return NULL; + b->b = tmp; + b->alloc = newsize; + } + // when index == b->len, just add toInsert at the end + if (index < b->len) { + memmove(b->b+index+len, b->b+index, b->len - index); + } + // copy toInsert at index in b + memcpy(b->b+index, toInsert, len); + b->len += len; + return b; +} + +/** + * buffer delete string + * + * return string without the string between start and end + * negative indexes are allowed + * + * \param + * string to delete + * \param + * start: start index, must be in the string + * \param + * end: end index, must be in the string after start + * \return + * sliced string + * unchanged string when start=end + * NULL when start and end are not set correctly + * or when input string is NULL or when malloc failed or when end is under start + */ +btt *bDelB(btt *string, int64_t start, int64_t end) { + int64_t len; + + // sanity checks + if (!string or !string->b) { + return(NULL); + } + if (string->alloc == 0 and string->len > 0) { + // string is not allocated so it is readonly + return(NULL); + } + + len = (int64_t)string->len; + + if (start >= len) { + start = len; + } + if (end > len) { + end = len; + } + if (start <= -len) { + start = -len; + } + if (end <= -len) { + end = -len; + } + if (start < 0) { + start = len + start; + } + if (end <= 0) { + end = len + end; + } + if (end < start) { + return(NULL); + } + + if (start == end) { + return(string); + } + + // start < end < len + // copy range to a new string + int64_t n; + n = end - start; + memmove(string->b+start, string->b+start+n, (size_t)(len-n-start)); + string->len -= n; + + return(string); +} + +/** + * buffer delete element/character string + * + * return string without the character at given index + * negative indexes are allowed + * + * \param + * string to delete + * \param + * index: must be in the string, -1 is the last character in the string + * \return + * string with one less character + * NULL when input string is NULL or invalid index + */ +btt *bDelElemB(btt *string, int64_t index) { + int64_t len; + + // sanity checks + if (!string or !string->b) { + return(NULL); + } + if (string->alloc == 0 and string->len > 0) { + // string is not allocated so it is readonly + return(NULL); + } + + len = (int64_t)string->len; + if (index >= len) { + return(NULL); + } + if (index < -len) { + return(NULL); + } + if (index < 0) { + index = len + index; + } + + // when index == len-1 only decrement len, delete last char and there is nothing to move + if (index < len-1) { + memmove(string->b+index, string->b+index+1, string->len - index-1); + } + string->len--; + return string; +} + +/** + * read file to new btt + * + * The function allocates the buffer + * + * \param + * filePath path to file + * \return + * data from file in a btt (you must free the pointer) + * (btt).b==NULL error + */ +btt readFileB(const char *filePath) { + btt r = init0Var; + ssize_t len = readFile(filePath, (void**)&r.b); + if (len == -1) { + r.b = NULL; + return r; + } + r.len = r.alloc = len; + return r; +} + +/** + * write btt to file + * + * \param + * filePath path to file + * btt + * \return + * 1 success + * 0 error + */ +int writeFileB(const char *filePath, btt b) { + // sanity checks + if (!b.b) { + return 0; + } + return writeFile(filePath, b.b, b.len); +} + +/** * split b in vb static vector * the vector is not reallocated */ diff --git a/src/libsheepyBt.h b/src/libsheepyBt.h @@ -324,6 +324,9 @@ btt newB(u32 allocateSize); // return a heap allocated btt object with a heap allocated buffer of size allocateSize btt *allocNewB(u32 allocateSize); +// reallocate b.b +bool reallocB(btt *b, size_t newSize); + // return a heap allocated btt object with buf assigned to it btt *allocCharB(char *buf); @@ -378,6 +381,8 @@ btt *dupPB(btt *b); // // NO - growzero: memset 0 to new part // ..slice // ..trim +// countB +// findB // formatB // iFormatB // bFormatB @@ -497,6 +502,15 @@ btt pushPBB(const btt *b, const btt s); btt pushPBPB(const btt *b, const btt *s); // TODO pushManyPBPB... +// insert string in string +btt *bInsertB(btt *b, int64_t index, const char *s); + +// delete range in string +btt *bDelB(btt *string, int64_t start, int64_t end); + +// del a character in string +btt *bDelElemB(btt *string, int64_t index); + #define appendBG pushBG #define pushBG(b, s) _Generic( b,\ btt: _Generic(s,\ @@ -569,6 +583,11 @@ btt pushPBPB(const btt *b, const btt *s); // return(1); // } + +// (btt).b is NULL on error +btt readFileB(const char *filePath) MUST_CHECK; +int writeFileB(const char *filePath, btt b) MUST_CHECK; + // split b in vb static vector // the vector is not reallocated vbtt *sasplitB(vbtt *vb, const btt b, const btt delim);