*
* str_ncpy - copy initial part of a string (a better strncpy)
*
+ * str_dup,
+ * str_ndup - duplicate (part of) a string
+ *
+ * str_app,
+ * str_napp - append (part of) a string to another
+ *
*/
#ifndef STR_H_
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
+#include <stdlib.h>
/*
}
+/*
+ * str_dup, str_ndup - duplicate (part of) a string
+ *
+ * The str_dup() function returns a pointer to a new string which is a
+ * duplicate of the string s. Memory for the new string is obtained with
+ * malloc(), and can be freed with free().
+ *
+ * The str_ndup() function is similar, but copies at most n bytes. If s
+ * is longer than n, only n bytes are copied, and a terminating null byte
+ * ('\0') is added. For str_ndup() s2 does not need to be null-
+ * terminated, if it contains n or more bytes.
+ *
+ * On success, the str_dup() and str_ndup() functions return a pointer to
+ * the duplicated string. NULL is returned if insufficient memory was
+ * available, with errno set to indicate the cause of the error.
+ */
+static inline char *str_dup(const char *s) {
+ char *d;
+ size_t n;
+
+ n = strlen(s) + 1;
+ d = malloc(n);
+ if (d) {
+ memcpy(d, s, n);
+ }
+ return d;
+}
+
+static inline char *str_ndup(const char *s, size_t n) {
+ char *d;
+
+ n = str_nlen(s, n);
+ d = malloc(n + 1);
+ if (d) {
+ memcpy(d, s, n);
+ d[n] = '\0';
+ }
+ return d;
+}
+
+
+/*
+ * str_app, str_napp - append one string to another
+ *
+ * The str_app() function appends the string s2 to the string *s1. It
+ * first resizes the buffer pointed to by *s1 using realloc() to fit the
+ * resulting null terminated combined string. Then the string s2 is
+ * appended to the end of *s1. The pointer pointed to by s1 shall either
+ * equal NULL or else must have been returned by a previous call to
+ * malloc(), calloc(), or realloc().
+ *
+ * The str_napp() function is similar, but copies at most n bytes of s2.
+ * If s2 is longer than n, only n bytes are copied, and a terminating
+ * null byte ('\0') is added. For str_napp() s2 does not need to be
+ * null-terminated, if it contains n or more bytes.
+ *
+ * On success str_app() and str_napp() return the memory location
+ * returned by realloc() and the pointer in *s1 is updated to refer to
+ * the same location. If insufficient memory was available, NULL is
+ * returned with errno set to indicate the cause of the error, and the
+ * original pointer in *s1 remains unchanged.
+ *
+ * CAVEAT:
+ * If any attempt is made to dereference a pointer to the location *s1
+ * originally pointed to after a successful invocation of str_append(),
+ * the behavior is undefined.
+ */
+static inline char *str_app(char **s1, const char *s2) {
+ char *d;
+ size_t l1, l2;
+
+ l1 = *s1 ? strlen(*s1) : 0;
+ l2 = strlen(s2) + 1;
+ d = realloc(*s1, l1 + l2);
+ if (d) {
+ memcpy(d + l1, s2, l2);
+ *s1 = d;
+ }
+ return d;
+}
+
+static inline char *str_napp(char **s1, const char *s2, size_t n) {
+ char *d;
+ size_t l1;
+
+ l1 = *s1 ? strlen(*s1) : 0;
+ n = str_nlen(s2, n);
+ d = realloc(*s1, l1 + n + 1);
+ if (d) {
+ memcpy(d + l1, s2, n);
+ d[l1 + n] = '\0';
+ *s1 = d;
+ }
+ return d;
+}
+
+
#ifdef cplusplus
}
#endif
#include <assert.h>
#include <inttypes.h>
-#include <stdbool.h>
#include <stdio.h>
#include "str.h"
/*****************************************/
+ {
+ H("str_dup, str_ndup");
+ char *p, *q, s[] = "fizzbuzz\0..x";
+ D(s);
+ T((p=str_dup(s)) != NULL);
+ T((q=str_dup(s)) != NULL);
+ T(p!=s);
+ T(p!=q);
+ T(strcmp(p,s) == 0);
+ T(strcmp(p,q) == 0);
+ free(p);
+ free(q);
+ char t[] = { 'f', 'o', 'o', 'x' }; /* unterminated! */
+ D(t);
+ T((p=str_ndup(t, 3)) != NULL);
+ T((q=str_ndup(t, 4)) != NULL);
+ T(p!=s);
+ T(p!=q);
+ T(strcmp(p, "foo") == 0);
+ T(strcmp(q, "foox") == 0);
+ free(p);
+ free(q);
+ }
+
+ /*****************************************/
+
+ {
+ H("str_app, str_napp");
+ char *p, *s, s_[] = "pfx ";
+ D(s_);
+ T((s = str_dup(s_)) != NULL);
+ T((p=str_app(&s, " 01")) != NULL);
+ T((p=str_app(&s, " 02")) != NULL);
+ T(strcmp(s, "pfx 01 02") == 0);
+ free(s);
+ char t[] = { 'f', 'o', 'o', 'x' }; /* unterminated! */
+ char u[] = "uhu ";
+ D(t);
+ D(u);
+ T((s = str_dup(s_)) != NULL);
+ T((p=str_napp(&s, t, 2)) != NULL);
+ T((p=str_napp(&s, u, 42)) != NULL);
+ T((p=str_napp(&s, t, 4)) != NULL);
+ T(strcmp(s, "pfx fouhu foox") == 0);
+ free(s);
+ }
+
+ /*****************************************/
+
H("All tests passed.");
return 0;
}