add strdup
authorgit <redacted>
Fri, 1 May 2026 12:44:57 +0000 (08:44 -0400)
committergit <redacted>
Fri, 1 May 2026 12:44:57 +0000 (08:44 -0400)
README.md
strdup.h [new file with mode: 0644]

index a5126fda69da03a2caf422fd3b627bee7f6e52cc..a10245f5216bf49a464dd99263ef1e9695eed633 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-A (WIP) collection of portable, strict C99, single-header implementations of common libc extensions.
+A collection of portable, strict C99, single-header implementations of common libc extensions.
 
 All functions are implemented as macros expanding to an internal function reference, this allows to use the headers with no meta build system - it compiles even if the extensions are already present, see _How to_ on disabling this behaviour.
 
@@ -59,3 +59,9 @@ permuting, defining those enables it per function (GNU behaviour, can still be d
 includes `strlcat()` and `strlcpy()`
 
 ---
+
+### strdup
+
+includes `strdup()` and `strndup()`
+
+`strndup()` follows the latest standard, meaning that it copies at most _n_ chars, not _n_ + 1.
diff --git a/strdup.h b/strdup.h
new file mode 100644 (file)
index 0000000..34617ea
--- /dev/null
+++ b/strdup.h
@@ -0,0 +1,71 @@
+/*
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to <https://unlicense.org>
+ */
+
+/* https://git.datadissipation.net */
+#ifndef STRDUP_H_
+ #define STRDUP_H_      1
+
+ #ifdef STRDUP_INCLUDE_LIBC
+  #include <stdlib.h>
+  #include <string.h>
+ #endif /* STRDUP_INCLUDE_LIBC */
+
+ #ifndef HAVE_STRDUP
+  #define HAVE_STRDUP   1
+  #define strdup        i_strdup_
+  #define strndup       i_strndup_
+char *i_strdup_(const char *s);
+char *i_strndup_(const char *s, size_t n);
+ #endif /* !HAVE_STRDUP */
+
+ #ifdef STRDUP_IMPLEMENTATION
+char *
+i_strdup_(const char *s)
+{
+       char *t = s;
+
+       /* avoid calling strlen twice by passing the maximum */
+       return i_strndup_(s, ~(size_t) 0);
+}
+
+char *
+i_strndup_(const char *s, size_t n)
+{
+       char *d;
+       size_t t;
+
+       t = strlen(s) + 1;
+       t = t < n ? t : n;
+       d = malloc(t);
+
+       if (!d) return NULL;
+       *(d + t) = '\0';
+
+       return memcpy(d, s, t - 1);
+}
+ #endif /* STRDUP_IMPLEMENTATION */
+#endif /* !STRDUP_H_ */