Various changes and improvements
- Replaced int by specific, more meaningful error codes. - C99 states realloc can be safely called using NULL pointers. - New function dynstr_dup().
This commit is contained in:
parent
0cc52ff5be
commit
34643b8a8d
51
dynstr.c
51
dynstr.c
|
@ -26,7 +26,7 @@ void dynstr_init(struct dynstr *const d)
|
||||||
memset(d, 0, sizeof *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;
|
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);
|
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);
|
va_end(ap);
|
||||||
|
|
||||||
if (!d->str)
|
d->str = realloc(d->str, new_len * sizeof *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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->str)
|
if (d->str)
|
||||||
{
|
{
|
||||||
|
@ -57,11 +48,43 @@ int dynstr_append(struct dynstr *const d, const char *const format, ...)
|
||||||
}
|
}
|
||||||
else
|
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)
|
void dynstr_free(struct dynstr *const d)
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
/**
|
/**
|
||||||
* Convenience macro that calls dynstr_append and returns its error code if failed.
|
* 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.
|
* Convenience macro that calls dynstr_append and returns zero if failed.
|
||||||
|
@ -65,6 +65,19 @@ struct dynstr
|
||||||
size_t len; /**< String length, null character not included. */
|
size_t len; /**< String length, null character not included. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Reportedly, it initializes an empty string with zero length.
|
||||||
* @attention Always call this function when creating a dynstr instance.
|
* @attention Always call this function when creating a dynstr instance.
|
||||||
|
@ -78,9 +91,25 @@ void dynstr_init(struct dynstr *d);
|
||||||
* dynamic string.
|
* dynamic string.
|
||||||
* @param d Dynamic string where new string will be appended.
|
* @param d Dynamic string where new string will be appended.
|
||||||
* @param format String literal in printf format.
|
* @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.
|
||||||
*/
|
*/
|
||||||
int dynstr_append(struct dynstr *d, const char *format, ...);
|
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.
|
||||||
|
*/
|
||||||
|
enum dynstr_err dynstr_dup(struct dynstr *dst, const struct dynstr *src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function frees memory used by the dynamic string.
|
* This function frees memory used by the dynamic string.
|
||||||
|
|
Loading…
Reference in New Issue