commit d1da7a37b447c6730ca95e18aaf78e9a0bdbd110
parent f3e6eba1bbc7acf9c85000cee78b7d185113a82d
Author: Remy Noulin <loader2x@gmail.com>
Date: Fri, 4 Apr 2025 10:02:11 +0200
Add btt functions: toCharB, bInsertBB, copyRngB, bCropB
release/libsheepy.h | 2 +-
release/libsheepyBt.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++
release/libsheepyBt.h | 21 ++++++++-
src/libsheepy.h | 2 +-
src/libsheepyBt.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/libsheepyBt.h | 21 ++++++++-
6 files changed, 294 insertions(+), 4 deletions(-)
Diffstat:
6 files changed, 294 insertions(+), 4 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.17"
+#define LIBSHEEPY_VERSION "2.2.18"
#ifndef SH_PREFIX
#define SH_PREFIX(NAME) NAME
diff --git a/release/libsheepyBt.c b/release/libsheepyBt.c
@@ -229,6 +229,16 @@ void cleanUpFinishB(btt **val) {
finishB(val);
}
+// convert btt to char* allocated on heap
+char *toCharB(btt *b) {
+ if (not b or not b->b) ret null;
+ char *r = malloc(b->len+1);
+ if (not r) ret null;
+ if (b->len) memcpy(r, b->b, b->len);
+ r[b->len] = 0;
+ ret r;
+}
+
/**
* return a btt object with s appended to b
* b doesn't need to have a heap allocated buffer
@@ -457,6 +467,72 @@ btt *bInsertB(btt *b, int64_t index, const char *toInsert) {
}
/**
+ * buffer insert btt 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 *bInsertBB(btt *b, int64_t index, const btt *toInsert) {
+ if (!b or !b->b or !toInsert or !toInsert->b) 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 = toInsert->len;
+ 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->b, len);
+ b->len += len;
+ return b;
+}
+
+/**
* buffer delete string
*
* return string without the string between start and end
@@ -1048,6 +1124,56 @@ btt slicePB(const btt *b, int64_t start, int64_t end) {
ret sliceB(*b, start, end);
}
+btt copyRngB(const btt b, int64_t start, int64_t end) {
+ btt s = sliceB(b, start, end);
+ if (not s.b) ret s; // error return {0}
+ else ret copyB(s);
+}
+
+// cropB copy and remove
+btt bCropB(btt *b, int64_t start, int64_t end) {
+
+ // sanity checks
+ if (!b or !b->b) {
+ ret emptybt;
+ }
+ if (b->alloc == 0 and b->len > 0) {
+ // b is not allocated so it is readonly
+ ret emptybt;
+ }
+
+ checkRange(*b, emptybt);
+
+ // slice to s
+ btt s = {0};
+ s.b = b->b + start;
+ if (start == end) {
+ // empty string
+ s.len = 0;
+ ret s; // nothing to delete in b
+ }
+ else {
+ // start < end < len
+ s.len = end - start;
+ }
+
+ // copy s to r and allocate on heap
+ btt r;
+ r.len = s.len;
+ r.b = malloc(r.len);
+ r.alloc = r.len;
+ memcpy(r.b, s.b, r.len);
+
+ // delete string between start and end in b
+ // copy range to a new string
+ int64_t n;
+ n = end - start;
+ memmove(b->b+start, b->b+start+n, (size_t)(len-n-start));
+ b->len -= n;
+
+ ret r;
+}
+
/**
* return a btt object without the leading and trailing spaces
*/
diff --git a/release/libsheepyBt.h b/release/libsheepyBt.h
@@ -25,6 +25,10 @@
* } btt;
* ```
* The btt structure is managed by the *B functions.
+ * The *B (not b*B) functions don't modify the first btt parameter.
+ * The functions named b*B modify the first bbt pointer parameter and return a btt pointer.
+ * The functions named *PB take a btt pointer whereas *B function take a btt struct as parameter.
+ * *BB functions take btt struct in all string parameters
*
* - Disadvantage 1: btt doesn't work with standard C string functions
*
@@ -391,7 +395,7 @@ btt *dupPB(btt *b);
// splitLenB
// listFreeB
// join
-// toCharB convert to char*
+// ..toCharB convert to char*
// getB setB setBB set .b getBB get .b
//
// extra sds splitargs
@@ -442,6 +446,9 @@ void cleanUpFreeB(btt **val);
// finish val when it is out of scope
void cleanUpFinishB(btt **val);
+// convert btt to char* allocated on heap
+char *toCharB(btt *b);
+
// return a btt object with s appended to b
// b doesn't need to have a heap allocated buffer
#define appendB pushB
@@ -507,6 +514,7 @@ btt pushPBPB(const btt *b, const btt *s);
// insert string in string
btt *bInsertB(btt *b, int64_t index, const char *s);
+btt *bInsertBB(btt *b, int64_t index, const btt *s);
// delete range in string
btt *bDelB(btt *string, int64_t start, int64_t end);
@@ -827,6 +835,17 @@ btt slicePB(const btt *b, int64_t start, int64_t end);
const btt*: slicePB\
)(b, start, end);
+// copyRngB
+// return a btt object with a heap allocated copy of b.b from start to end
+btt copyRngB(const btt b, int64_t start, int64_t end);
+
+// copyRngPB
+// return a btt object with a heap allocated copy of b.b from start to end
+// TODO btt copyRngPB(btt *b, int64_t start, int64_t end);
+
+// cropB copy and remove
+btt bCropB(btt *b, int64_t start, int64_t end);
+
// return a btt object without the leading and trailing spaces
btt trimB(const btt b);
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.17"
+#define LIBSHEEPY_VERSION "2.2.18"
#ifndef SH_PREFIX
#define SH_PREFIX(NAME) NAME
diff --git a/src/libsheepyBt.c b/src/libsheepyBt.c
@@ -229,6 +229,16 @@ void cleanUpFinishB(btt **val) {
finishB(val);
}
+// convert btt to char* allocated on heap
+char *toCharB(btt *b) {
+ if (not b or not b->b) ret null;
+ char *r = malloc(b->len+1);
+ if (not r) ret null;
+ if (b->len) memcpy(r, b->b, b->len);
+ r[b->len] = 0;
+ ret r;
+}
+
/**
* return a btt object with s appended to b
* b doesn't need to have a heap allocated buffer
@@ -457,6 +467,72 @@ btt *bInsertB(btt *b, int64_t index, const char *toInsert) {
}
/**
+ * buffer insert btt 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 *bInsertBB(btt *b, int64_t index, const btt *toInsert) {
+ if (!b or !b->b or !toInsert or !toInsert->b) 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 = toInsert->len;
+ 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->b, len);
+ b->len += len;
+ return b;
+}
+
+/**
* buffer delete string
*
* return string without the string between start and end
@@ -1048,6 +1124,56 @@ btt slicePB(const btt *b, int64_t start, int64_t end) {
ret sliceB(*b, start, end);
}
+btt copyRngB(const btt b, int64_t start, int64_t end) {
+ btt s = sliceB(b, start, end);
+ if (not s.b) ret s; // error return {0}
+ else ret copyB(s);
+}
+
+// cropB copy and remove
+btt bCropB(btt *b, int64_t start, int64_t end) {
+
+ // sanity checks
+ if (!b or !b->b) {
+ ret emptybt;
+ }
+ if (b->alloc == 0 and b->len > 0) {
+ // b is not allocated so it is readonly
+ ret emptybt;
+ }
+
+ checkRange(*b, emptybt);
+
+ // slice to s
+ btt s = {0};
+ s.b = b->b + start;
+ if (start == end) {
+ // empty string
+ s.len = 0;
+ ret s; // nothing to delete in b
+ }
+ else {
+ // start < end < len
+ s.len = end - start;
+ }
+
+ // copy s to r and allocate on heap
+ btt r;
+ r.len = s.len;
+ r.b = malloc(r.len);
+ r.alloc = r.len;
+ memcpy(r.b, s.b, r.len);
+
+ // delete string between start and end in b
+ // copy range to a new string
+ int64_t n;
+ n = end - start;
+ memmove(b->b+start, b->b+start+n, (size_t)(len-n-start));
+ b->len -= n;
+
+ ret r;
+}
+
/**
* return a btt object without the leading and trailing spaces
*/
diff --git a/src/libsheepyBt.h b/src/libsheepyBt.h
@@ -25,6 +25,10 @@
* } btt;
* ```
* The btt structure is managed by the *B functions.
+ * The *B (not b*B) functions don't modify the first btt parameter.
+ * The functions named b*B modify the first bbt pointer parameter and return a btt pointer.
+ * The functions named *PB take a btt pointer whereas *B function take a btt struct as parameter.
+ * *BB functions take btt struct in all string parameters
*
* - Disadvantage 1: btt doesn't work with standard C string functions
*
@@ -391,7 +395,7 @@ btt *dupPB(btt *b);
// splitLenB
// listFreeB
// join
-// toCharB convert to char*
+// ..toCharB convert to char*
// getB setB setBB set .b getBB get .b
//
// extra sds splitargs
@@ -442,6 +446,9 @@ void cleanUpFreeB(btt **val);
// finish val when it is out of scope
void cleanUpFinishB(btt **val);
+// convert btt to char* allocated on heap
+char *toCharB(btt *b);
+
// return a btt object with s appended to b
// b doesn't need to have a heap allocated buffer
#define appendB pushB
@@ -507,6 +514,7 @@ btt pushPBPB(const btt *b, const btt *s);
// insert string in string
btt *bInsertB(btt *b, int64_t index, const char *s);
+btt *bInsertBB(btt *b, int64_t index, const btt *s);
// delete range in string
btt *bDelB(btt *string, int64_t start, int64_t end);
@@ -827,6 +835,17 @@ btt slicePB(const btt *b, int64_t start, int64_t end);
const btt*: slicePB\
)(b, start, end);
+// copyRngB
+// return a btt object with a heap allocated copy of b.b from start to end
+btt copyRngB(const btt b, int64_t start, int64_t end);
+
+// copyRngPB
+// return a btt object with a heap allocated copy of b.b from start to end
+// TODO btt copyRngPB(btt *b, int64_t start, int64_t end);
+
+// cropB copy and remove
+btt bCropB(btt *b, int64_t start, int64_t end);
+
// return a btt object without the leading and trailing spaces
btt trimB(const btt b);