Welcome to little lamb

Code » limb » commit cb5f2a9

Add sacoloff(), saoff2ptr() and sacolptr()

author Olivier Brunel
2023-02-28 09:20:39 UTC
committer Olivier Brunel
2023-02-28 15:26:31 UTC
parent 9318e9bca2ef6755b6d9c9da4de0c3e4999ef89a

Add sacoloff(), saoff2ptr() and sacolptr()

These functions allow to collect offsets (or pointers) to NUL-terminated
strings from an stralloc into a array of said offsets/pointers.

Can be useful to use said strings with others functions not stralloc
aware, e.g. to simply sort them.

doc/sacoloff.3.md +43 -0
doc/sacolptr.3.md +88 -0
doc/saoff2ptr.3.md +29 -0
include/limb/samisc.h +10 -0
meta/libs/limb +4 -0
src/sacoloff.c +21 -0
src/sacolptr.c +15 -0
src/saoff2ptr.c +13 -0

diff --git a/doc/sacoloff.3.md b/doc/sacoloff.3.md
new file mode 100644
index 0000000..e3fba94
--- /dev/null
+++ b/doc/sacoloff.3.md
@@ -0,0 +1,43 @@
+% limb manual
+% sacoloff(3)
+
+# NAME
+
+sacoloff - append an array of offsets to strings from an stralloc into it
+
+# SYNOPSIS
+
+    #include <limb/samisc.h>
+
+```pre hl
+int sacoloff(stralloc *<em>sa</em>, size_t <em>from</em>, size_t <em>end</em>)
+```
+
+# DESCRIPTION
+
+The `sacoloff`() function will scan the content of the given stralloc `sa`
+starting at offset `from`, expecting to find a succession of NUL-terminated
+strings, up to `end`. It will append into `sa` an array of offsets where each
+string is located within `sa->s`.
+
+! INFO:
+! The offsets added into `sa` are actually casted as *uintptr_t* so that they
+! can later be turned into full string pointers (*char \**) if needed.
+! Such a conversion can be done using [saoff2ptr](3).
+
+# RETURN VALUE
+
+Upon successful completion, the `sacoloff`() function returns the number of
+strings found, or the number of elements in the array. Otherwise, it returns -1
+and sets `errno` to indicate the error.
+
+# ERRORS
+
+The `sacoloff`() function may fail if :
+
+: *ENOMEM*
+:: Out of memory to add pointers into `sa`
+
+# SEE ALSO
+
+[saoff2ptr](3), [sacolptr](3)
diff --git a/doc/sacolptr.3.md b/doc/sacolptr.3.md
new file mode 100644
index 0000000..c373aed
--- /dev/null
+++ b/doc/sacolptr.3.md
@@ -0,0 +1,88 @@
+% limb manual
+% sacolptr(3)
+
+# NAME
+
+sacolptr - append an array of pointers to strings from an stralloc into it
+
+# SYNOPSIS
+
+    #include <limb/samisc.h>
+
+```pre hl
+int sacolptr(stralloc *<em>sa</em>, size_t <em>from</em>, size_t <em>end</em>)
+```
+
+# DESCRIPTION
+
+The `sacolptr`() function will scan the content of the given stralloc `sa`
+starting at offset `from`, expecting to find a succession of NUL-terminated
+strings, up to `end`. It will append into `sa` an array of pointers to the
+strings.
+
+This allows to use said array easily with other functions not stralloc-aware.
+
+! INFO:
+! This function is merely is wrapper around [sacoloff](3) and [saoff2ptr](3).
+
+# RETURN VALUE
+
+Upon successful completion, the `sacolptr`() function returns the number of
+strings found, or the number of elements in the array. Otherwise, it returns -1
+and sets `errno` to indicate the error.
+
+# ERRORS
+
+The `sacolptr`() function may fail and set `errno` for any of the errors
+specified on [sacoloff](3).
+
+# EXAMPLE
+
+To get the list of files in the current directory, and sort them using
+[qsort](3), one could do the following (Note the lack of error checking) :
+
+```c
+#include <stdlib.h>
+#include <string.h>
+#include <skalibs/stralloc.h>
+#include <limb/output.h>
+#include <limb/samisc.h>
+
+static int
+cmp(const void *p1, const void *p2)
+{
+    const char *s1 = * (const char **) p1;
+    const char *s2 = * (const char **) p2;
+    return strcmp(s1, s2);
+}
+
+int
+main(void)
+{
+    stralloc sa = STRALLOC_ZERO;
+
+    /* append the list of all files in the current directory into sa */
+    salst(&sa, ".", NULL);
+
+    /* offset where the array will be stored */
+    size_t arroff = sa.len;
+
+    /* append the array from strings contained within */
+    int n = sacolptr(&sa, 0, sa.len);
+
+    /* sort the array */
+    char **arr = (char **) (sa.s + arroff);
+    qsort(arr, n, sizeof(char *), cmp);
+
+    /* show ordered listing */
+    for (int i = 0; i < n; ++i, ++arr)
+        out(*arr);
+
+    stralloc_free(&sa);
+    return 0;
+}
+```
+
+# SEE ALSO
+
+[sacoloff](3), [saoff2ptr](3)
diff --git a/doc/saoff2ptr.3.md b/doc/saoff2ptr.3.md
new file mode 100644
index 0000000..3f3a2a4
--- /dev/null
+++ b/doc/saoff2ptr.3.md
@@ -0,0 +1,29 @@
+% limb manual
+% saoff2ptr(3)
+
+# NAME
+
+saoff2ptr - turn an array of offsets from an stralloc into an array of strings
+
+# SYNOPSIS
+
+    #include <limb/samisc.h>
+
+```pre hl
+void saoff2ptr(stralloc *<em>sa</em>, size_t <em>arroff</em>, size_t <em>n</em>)
+```
+
+# DESCRIPTION
+
+The `saoff2ptr`() function will transform an array of `n` offsets located at
+`arroff` into `sa->s` into an array of string pointers.
+
+This allows to use said array easily with other functions not stralloc-aware.
+
+! HINT:
+! You can easily append such an array of offsets from a concatenation of
+! NUL-terminated strings into a stralloc using [sacoloff](3).
+
+# SEE ALSO
+
+[sacoloff](3), [sacolptr](3)
diff --git a/include/limb/samisc.h b/include/limb/samisc.h
new file mode 100644
index 0000000..0c32b25
--- /dev/null
+++ b/include/limb/samisc.h
@@ -0,0 +1,10 @@
+#ifndef LIMB_SAMISC_H
+#define LIMB_SAMISC_H
+
+#include <skalibs/stralloc.h>
+
+extern int  sacoloff(stralloc *sa, size_t from, size_t end);
+extern void saoff2ptr(stralloc *sa, size_t arroff, size_t n);
+extern int  sacolptr(stralloc *sa, size_t from, size_t end);
+
+#endif /* LIMB_SAMISC_H */
diff --git a/meta/libs/limb b/meta/libs/limb
index 76c5560..6a447d2 100644
--- a/meta/libs/limb
+++ b/meta/libs/limb
@@ -16,6 +16,10 @@ obj/rmstar_in_tmpat.o
 obj/rmstar_tmpat.o
 obj/salsat.o
 obj/sareadlinkat.o
+# samisc.h
+obj/sacoloff.o
+obj/saoff2ptr.o
+obj/sacolptr.o
 # buffer.h
 obj/buffer_putescall.o
 obj/buffer_putesc.o
diff --git a/src/sacoloff.c b/src/sacoloff.c
new file mode 100644
index 0000000..25ea28e
--- /dev/null
+++ b/src/sacoloff.c
@@ -0,0 +1,21 @@
+#include <stdint.h> /* uintptr_t */
+#include "limb/samisc.h"
+
+int
+sacoloff(stralloc *sa, size_t from, size_t end)
+{
+    size_t salen = sa->len;
+    int ret = 0;
+
+    for (uintptr_t off = from; off < end; ) {
+        if (!stralloc_catb(sa, (char *) &off, sizeof(off))) {
+            sa->len = salen;
+            return -1;
+        }
+
+        off += strlen(sa->s + off) + 1;
+        ++ret;
+    }
+
+    return ret;
+}
diff --git a/src/sacolptr.c b/src/sacolptr.c
new file mode 100644
index 0000000..4193581
--- /dev/null
+++ b/src/sacolptr.c
@@ -0,0 +1,15 @@
+#include "limb/samisc.h"
+
+int
+sacolptr(stralloc *sa, size_t from, size_t end)
+{
+    size_t arroff = sa->len;
+    /* first collect the offsets from sa->s, as relocation might happen as we
+     * grow sa to store the array */
+    int n = sacoloff(sa, from, end);
+    if (n < 0)
+        return n;
+    /* then turn offsets into pointers */
+    saoff2ptr(sa, arroff, n);
+    return n;
+}
diff --git a/src/saoff2ptr.c b/src/saoff2ptr.c
new file mode 100644
index 0000000..08e1546
--- /dev/null
+++ b/src/saoff2ptr.c
@@ -0,0 +1,13 @@
+#include <stdint.h> /* uintptr_t */
+#include "limb/samisc.h"
+
+void
+saoff2ptr(stralloc *sa, size_t arroff, size_t n)
+{
+    uintptr_t *a = (uintptr_t *) (sa->s + arroff);
+    for (int i = 0; i < n; ++i) {
+        /* add the base, and turn this into a proper pointer */
+        *a += (uintptr_t) sa->s;
+        ++a;
+    }
+}