Compare commits
6 Commits
e0eaf50fdc
...
601a813325
Author | SHA1 | Date |
---|---|---|
Xavier Del Campo Romero | 601a813325 | |
Xavier Del Campo Romero | 837c9427de | |
Xavier Del Campo Romero | 083eca5323 | |
Xavier Del Campo Romero | 3e9016f23f | |
Xavier Del Campo Romero | c862d84d0b | |
Xavier Del Campo Romero | 8bd1123857 |
55
dynstr.c
55
dynstr.c
|
@ -30,45 +30,55 @@ void dynstr_init(struct dynstr *const d)
|
|||
memset(d, 0, sizeof *d);
|
||||
}
|
||||
|
||||
enum dynstr_err dynstr_append(struct dynstr *const d, const char *const format, ...)
|
||||
enum dynstr_err dynstr_vappend(struct dynstr *const d, const char *const format, va_list ap)
|
||||
{
|
||||
va_list ap;
|
||||
enum dynstr_err err = DYNSTR_OK;
|
||||
va_list apc;
|
||||
|
||||
va_start(ap, format);
|
||||
va_copy(apc, ap);
|
||||
|
||||
{
|
||||
const size_t src_len = vsnprintf(NULL, 0, format, ap);
|
||||
const size_t new_len = d->len + src_len + 1;
|
||||
va_end(ap);
|
||||
|
||||
d->str = realloc(d->str, new_len * sizeof *d->str);
|
||||
|
||||
if (d->str)
|
||||
{
|
||||
va_start(ap, format);
|
||||
vsprintf(d->str + d->len, format, ap);
|
||||
va_end(ap);
|
||||
vsprintf(d->str + d->len, format, apc);
|
||||
d->len += src_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DYNSTR_ERR_ALLOC;
|
||||
err = DYNSTR_ERR_ALLOC;
|
||||
}
|
||||
}
|
||||
|
||||
return DYNSTR_OK;
|
||||
va_end(apc);
|
||||
return err;
|
||||
}
|
||||
|
||||
enum dynstr_err dynstr_prepend(struct dynstr *const d, const char *const format, ...)
|
||||
enum dynstr_err dynstr_append(struct dynstr *const d, const char *const format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
enum dynstr_err err;
|
||||
|
||||
va_start(ap, format);
|
||||
err = dynstr_vappend(d, format, ap);
|
||||
va_end(ap);
|
||||
return err;
|
||||
}
|
||||
|
||||
enum dynstr_err dynstr_vprepend(struct dynstr *const d, const char *const format, va_list ap)
|
||||
{
|
||||
enum dynstr_err err = DYNSTR_OK;
|
||||
va_list apc;
|
||||
|
||||
va_copy(apc, ap);
|
||||
|
||||
{
|
||||
const size_t src_len = vsnprintf(NULL, 0, format, ap);
|
||||
const size_t new_len = d->len + src_len + 1;
|
||||
va_end(ap);
|
||||
|
||||
d->str = realloc(d->str, new_len * sizeof *d->str);
|
||||
|
||||
|
@ -82,26 +92,33 @@ enum dynstr_err dynstr_prepend(struct dynstr *const d, const char *const format,
|
|||
d->str[i] = d->str[j];
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
vsprintf(d->str, format, ap);
|
||||
va_end(ap);
|
||||
vsprintf(d->str, format, apc);
|
||||
d->str[src_len] = c;
|
||||
}
|
||||
else if (!d->len)
|
||||
{
|
||||
va_start(ap, format);
|
||||
vsprintf(d->str + d->len, format, ap);
|
||||
va_end(ap);
|
||||
vsprintf(d->str + d->len, format, apc);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DYNSTR_ERR_ALLOC;
|
||||
err = DYNSTR_ERR_ALLOC;
|
||||
}
|
||||
|
||||
d->len += src_len;
|
||||
}
|
||||
|
||||
return DYNSTR_OK;
|
||||
va_end(apc);
|
||||
return err;
|
||||
}
|
||||
|
||||
enum dynstr_err dynstr_prepend(struct dynstr *const d, const char *const format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
enum dynstr_err err;
|
||||
|
||||
va_start(ap, format);
|
||||
err = dynstr_vprepend(d, format, ap);
|
||||
return err;
|
||||
}
|
||||
|
||||
enum dynstr_err dynstr_dup(struct dynstr *const dst, const struct dynstr *const src)
|
||||
|
|
134
include/dynstr.h
134
include/dynstr.h
|
@ -21,45 +21,10 @@
|
|||
#error C99 support is mandatory for dynstr
|
||||
#endif /* __STDC_VERSION < 199901L */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Since dynstr_append() might fail (as it is based on dynamic memory
|
||||
* allocation), these macros can be used to avoid boilerplate code. */
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns NULL if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_null(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return NULL;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns false if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_false(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return false;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns its error code if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret(...) \
|
||||
{ \
|
||||
const enum dynstr_err err = dynstr_append(__VA_ARGS__); \
|
||||
if (err != DYNSTR_OK) return err; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns zero if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_zero(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return 0;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns one if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_nonzero(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return 1;} while (0)
|
||||
|
||||
/**
|
||||
* Dynamic string type used for this library.
|
||||
* @note If needed, members can be safely read but should not be modified
|
||||
|
@ -108,6 +73,19 @@ void dynstr_init(struct dynstr *d);
|
|||
*/
|
||||
enum dynstr_err dynstr_append(struct dynstr *d, const char *format, ...);
|
||||
|
||||
/**
|
||||
* This function takes a string literal in printf format and a variable
|
||||
* argument list, calculates its size and concatenates it into the
|
||||
* dynamic string.
|
||||
* @param d Dynamic string where new string will be appended.
|
||||
* @param format String literal in printf format.
|
||||
* @param ap Variable argument list.
|
||||
* @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_vappend(struct dynstr *d, const char *format, va_list ap);
|
||||
|
||||
/**
|
||||
* This function takes a string literal in printf format and a variable
|
||||
* number of arguments, calculates its size and prepends it into the
|
||||
|
@ -120,6 +98,19 @@ enum dynstr_err dynstr_append(struct dynstr *d, const char *format, ...);
|
|||
*/
|
||||
enum dynstr_err dynstr_prepend(struct dynstr *d, const char *format, ...);
|
||||
|
||||
/**
|
||||
* This function takes a string literal in printf format and a variable
|
||||
* argument list, calculates its size and prepends it into the beginning of the
|
||||
* dynamic string.
|
||||
* @param d Dynamic string where new string will be prepended.
|
||||
* @param format String literal in printf format.
|
||||
* @param ap Variable argument list.
|
||||
* @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_vprepend(struct dynstr *d, const char *format, va_list ap);
|
||||
|
||||
/**
|
||||
* This function duplicates a dynamic string to another instance.
|
||||
* @attention Destination instance must be initialized before calling
|
||||
|
@ -153,4 +144,75 @@ enum dynstr_err dynstr_dup(struct dynstr *dst, const struct dynstr *src);
|
|||
*/
|
||||
void dynstr_free(struct dynstr *d);
|
||||
|
||||
/* Since dynstr_append() might fail (as it is based on dynamic memory
|
||||
* allocation), these macros can be used to avoid boilerplate code. */
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns NULL if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_null(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return NULL;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns false if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_false(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return false;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns its error code if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret(...) \
|
||||
do \
|
||||
{ \
|
||||
const enum dynstr_err err = dynstr_append(__VA_ARGS__); \
|
||||
if (err != DYNSTR_OK) return err; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns zero if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_zero(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return 0;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_append and returns one if failed.
|
||||
*/
|
||||
#define dynstr_append_or_ret_nonzero(...) \
|
||||
do {if (dynstr_append(__VA_ARGS__) != DYNSTR_OK) return 1;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_prepend and returns NULL if failed.
|
||||
*/
|
||||
#define dynstr_prepend_or_ret_null(...) \
|
||||
do {if (dynstr_prepend(__VA_ARGS__) != DYNSTR_OK) return NULL;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_prepend and returns false if failed.
|
||||
*/
|
||||
#define dynstr_prepend_or_ret_false(...) \
|
||||
do {if (dynstr_prepend(__VA_ARGS__) != DYNSTR_OK) return false;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_prepend and returns its error code if failed.
|
||||
*/
|
||||
#define dynstr_prepend_or_ret(...) \
|
||||
do \
|
||||
{ \
|
||||
const enum dynstr_err err = dynstr_prepend(__VA_ARGS__); \
|
||||
if (err != DYNSTR_OK) return err; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_prepend and returns zero if failed.
|
||||
*/
|
||||
#define dynstr_prepend_or_ret_zero(...) \
|
||||
do {if (dynstr_prepend(__VA_ARGS__) != DYNSTR_OK) return 0;} while (0)
|
||||
|
||||
/**
|
||||
* Convenience macro that calls dynstr_prepend and returns one if failed.
|
||||
*/
|
||||
#define dynstr_prepend_or_ret_nonzero(...) \
|
||||
do {if (dynstr_prepend(__VA_ARGS__) != DYNSTR_OK) return 1;} while (0)
|
||||
|
||||
#endif /* DYNSTR_H */
|
||||
|
|
Loading…
Reference in New Issue