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:
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);