summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2014-05-04 18:29:53 +0100
committerVincent Sanders <vince@kyllikki.org>2014-05-07 16:24:30 +0100
commitc1e2da80dfa62793ea107cf12408c814e268a54b (patch)
treea2013312a9f24e2f1027dc343f9d9516d6945112 /utils
parent283cd05d0112b08753cb0b0c505a370ebccc52d1 (diff)
downloadnetsurf-c1e2da80dfa62793ea107cf12408c814e268a54b.tar.gz
netsurf-c1e2da80dfa62793ea107cf12408c814e268a54b.tar.bz2
add string utility to join strings
Diffstat (limited to 'utils')
-rw-r--r--utils/errors.h4
-rw-r--r--utils/utils.c79
-rw-r--r--utils/utils.h46
3 files changed, 128 insertions, 1 deletions
diff --git a/utils/errors.h b/utils/errors.h
index 4c02adb2d..bfb659d03 100644
--- a/utils/errors.h
+++ b/utils/errors.h
@@ -73,7 +73,9 @@ typedef enum {
NSERROR_FRAME_DEPTH, /**< Exceeded frame depth */
- NSERROR_PERMISSION /**< Permission error */
+ NSERROR_PERMISSION, /**< Permission error */
+
+ NSERROR_NOSPACE /**< Insufficient space */
} nserror;
#endif
diff --git a/utils/utils.c b/utils/utils.c
index 8cb1987d4..bb30f921e 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -160,6 +160,85 @@ bool is_dir(const char *path)
return S_ISDIR(s.st_mode) ? true : false;
}
+/* exported interface documented in utils/utils.h */
+nserror vsnstrjoin(char **str, size_t *size, char sep, size_t nelm, va_list ap)
+{
+ const char *elm[16];
+ size_t elm_len[16];
+ size_t elm_idx;
+ char *fname;
+ size_t fname_len = 0;
+ char *curp;
+
+ /* check the parameters are all sensible */
+ if ((nelm == 0) || (nelm > 16)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+ if ((*str != NULL) && (size == NULL)) {
+ /* if the caller is providing the buffer they must say
+ * how much space is available.
+ */
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* calculate how much storage we need for the complete path
+ * with all the elements.
+ */
+ for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
+ elm[elm_idx] = va_arg(ap, const char *);
+ elm_len[elm_idx] = strlen(elm[elm_idx]);
+ fname_len += elm_len[elm_idx];
+ }
+ fname_len += nelm; /* allow for separators and terminator */
+
+ /* ensure there is enough space */
+ fname = *str;
+ if (fname != NULL) {
+ if (fname_len > *size) {
+ return NSERROR_NOSPACE;
+ }
+ } else {
+ fname = malloc(fname_len);
+ if (fname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ }
+
+ /* copy the elements in with apropriate separator */
+ curp = fname;
+ for (elm_idx = 0; elm_idx < nelm; elm_idx++) {
+ memmove(curp, elm[elm_idx], elm_len[elm_idx]);
+ curp += elm_len[elm_idx];
+ /* ensure string are separated */
+ if (curp[-1] != sep) {
+ *curp = sep;
+ curp++;
+ }
+ }
+ curp[-1] = 0; /* NULL terminate */
+
+ assert((curp - fname) <= (int)fname_len);
+
+ *str = fname;
+ if (size != NULL) {
+ *size = fname_len;
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in utils/utils.h */
+nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...)
+{
+ va_list ap;
+ nserror ret;
+
+ va_start(ap, nelm);
+ ret = vsnstrjoin(str, size, sep, nelm, ap);
+ va_end(ap);
+
+ return ret;
+}
/**
* Compile a regular expression, handling errors.
diff --git a/utils/utils.h b/utils/utils.h
index db26ed176..33cb0e99a 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -28,6 +28,9 @@
#include <sys/time.h>
#include <regex.h>
#include <assert.h>
+#include <stdarg.h>
+
+#include "utils/errors.h"
struct dirent;
@@ -145,6 +148,49 @@ char *human_friendly_bytesize(unsigned long bytesize);
const char *rfc1123_date(time_t t);
unsigned int wallclock(void);
+/**
+ * Generate a string from one or more component elemnts separated with
+ * a single value.
+ *
+ * This is similar in intent to the perl join function creating a
+ * single delimited string from an array of several.
+ *
+ * @note If a string is allocated it must be freed by the caller.
+ *
+ * @param[in,out] str pointer to string pointer if this is NULL enough
+ * storage will be allocated for the complete path.
+ * @param[in,out] size The size of the space available if \a str not
+ * NULL on input and if not NULL set to the total
+ * output length on output.
+ * @param[in] sep The character to separete the elemnts with.
+ * @param[in] nemb The number of elements up to a maximum of 16.
+ * @param[in] ap The elements of the path as string pointers.
+ * @return NSERROR_OK and the complete path is written to str or error
+ * code on faliure.
+ */
+nserror vsnstrjoin(char **str, size_t *size, char sep, size_t nelm, va_list ap);
+
+/**
+ * Generate a string from one or more component elemnts separated with
+ * a single value.
+ *
+ * This is similar in intent to the perl join function creating a
+ * single delimited string from an array of several.
+ *
+ * @note If a string is allocated it must be freed by the caller.
+ *
+ * @param[in,out] str pointer to string pointer if this is NULL enough
+ * storage will be allocated for the complete path.
+ * @param[in,out] size The size of the space available if \a str not
+ * NULL on input and if not NULL set to the total
+ * output length on output.
+ * @param[in] sep The character to separete the elemnts with.
+ * @param[in] nemb The number of elements up to a maximum of 16.
+ * @param[in] ... The elements of the path as string pointers.
+ * @return NSERROR_OK and the complete path is written to str or error
+ * code on faliure.
+ */
+nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...);
/**
* Comparison function for sorting directories.