aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dynstr.c51
-rw-r--r--include/dynstr.h35
2 files changed, 69 insertions, 17 deletions
diff --git a/dynstr.c b/dynstr.c
index 8779fbf..025f1fc 100644
--- a/dynstr.c
+++ b/dynstr.c
@@ -26,7 +26,7 @@ void dynstr_init(struct dynstr *const d)
memset(d, 0, sizeof *d);
}
-int dynstr_append(struct dynstr *const d, const char *const format, ...)
+enum dynstr_err dynstr_append(struct dynstr *const d, const char *const format, ...)
{
va_list ap;
@@ -34,19 +34,10 @@ int dynstr_append(struct dynstr *const d, const char *const format, ...)
{
const size_t src_len = vsnprintf(NULL, 0, format, ap);
- size_t new_len;
+ const size_t new_len = d->len + src_len + 1;
va_end(ap);
- if (!d->str)
- {
- new_len = src_len + 1;
- d->str = malloc(new_len * sizeof *d->str);
- }
- else
- {
- new_len = d->len + src_len + 1;
- d->str = realloc(d->str, new_len * sizeof *d->str);
- }
+ d->str = realloc(d->str, new_len * sizeof *d->str);
if (d->str)
{
@@ -57,11 +48,43 @@ int dynstr_append(struct dynstr *const d, const char *const format, ...)
}
else
{
- return 1;
+ return DYNSTR_ERR_ALLOC;
}
}
- return 0;
+ return DYNSTR_OK;
+}
+
+enum dynstr_err dynstr_dup(struct dynstr *const dst, const struct dynstr *const src)
+{
+ if (!dst->str && !dst->len)
+ {
+ if (src->len && src->str)
+ {
+ const size_t sz = (src->len + 1) * sizeof *dst->str;
+ dst->str = realloc(dst->str, sz);
+
+ if (dst->str)
+ {
+ memcpy(dst->str, src->str, sz);
+ dst->len = src->len;
+ }
+ else
+ {
+ return DYNSTR_ERR_ALLOC;
+ }
+ }
+ else
+ {
+ return DYNSTR_ERR_SRC;
+ }
+ }
+ else
+ {
+ return DYNSTR_ERR_INIT;
+ }
+
+ return DYNSTR_OK;
}
void dynstr_free(struct dynstr *const d)
diff --git a/include/dynstr.h b/include/dynstr.h
index a2e8f41..a545b81 100644
--- a/include/dynstr.h
+++ b/include/dynstr.h
@@ -45,7 +45,7 @@
/**
* Convenience macro that calls dynstr_append and returns its error code if failed.
*/
-#define dynstr_append_or_ret(d, format, ...) {const int err = dynstr_append(d, format, ## __VA_ARGS__); if (err) return err;}
+#define dynstr_append_or_ret(d, format, ...) {const enum dynstr_err err = dynstr_append(d, format, ## __VA_ARGS__); if (err) return err;}
/**
* Convenience macro that calls dynstr_append and returns zero if failed.
@@ -66,6 +66,19 @@ struct dynstr
};
/**
+ * List of errors that this library might return.
+ * @note If using GNU C extensions, this errors can be translated into other
+ * types by using the convenience macros above.
+ */
+enum dynstr_err
+{
+ DYNSTR_OK, /**< Operation was successful. */
+ DYNSTR_ERR_ALLOC, /**< Alloc operation failed. */
+ DYNSTR_ERR_INIT, /**< Dynamic string was not initialized. */
+ DYNSTR_ERR_SRC /**< Source string has invalid parameters. */
+};
+
+/**
* Reportedly, it initializes an empty string with zero length.
* @attention Always call this function when creating a dynstr instance.
* @param d Dynamic string to be initialized.
@@ -78,9 +91,25 @@ void dynstr_init(struct dynstr *d);
* dynamic string.
* @param d Dynamic string where new string will be appended.
* @param format String literal in printf format.
- * @return Returns 0 if successful, 1 if alloc operation failed.
+ * @return Returns one of the following error codes:
+ * # DYNSTR_OK if successful.
+ * # DYNSTR_ERR_ALLOC if no more memory is available.
+ */
+enum dynstr_err dynstr_append(struct dynstr *d, const char *format, ...);
+
+/**
+ * This function duplicates a dynamic string to another instance.
+ * @attention Destination instance must be initialized before calling
+ * this function.
+ * @attention Since this function performs a deep copy, please remember to
+ * free the source instance if no longer used to avoid memory leaks.
+ * @return Returns one of the following error codes:
+ * # DYNSTR_OK if successful.
+ * # DYNSTR_ERR_ALLOC if no more memory is available.
+ * # DYNSTR_ERR_INIT if destination dynamic string was not initialized.
+ * # DYNSTR_ERR_SRC if source dynamic string has no length or data.
*/
-int dynstr_append(struct dynstr *d, const char *format, ...);
+enum dynstr_err dynstr_dup(struct dynstr *dst, const struct dynstr *src);
/**
* This function frees memory used by the dynamic string.