#ifndef UC_DSTR_H_ #define UC_DSTR_H_ #include #include #ifdef __cplusplus extern "C" { #endif /**@file * A managed C-string, using dynamically allocated memory for the string. * * The .str member might not always be nul terminated, and should not be * accessed directly. Instead use uc_dstr_str() to retreive the managed string * which will always ensure the string is nul terminated * * Normally, let the DSTR manage the nul terminator as manually adding * a nul byte and potintially adding more data to the DStr would append * it after that nul terminator. */ /** Dynamic string struct. The user is responsible for managing * the struct Dstr memory, and the uc_dstr_ functions will manage * the memory held in .str. */ struct DStr { /** Length of the managed string.*/ size_t len; //internal fields: size_t allocated; char *str; }; #define UC_DSTR_INITIALIZER {0, 0, NULL} /** Initialize a DStr. * Note that str->str will be NULL after initialization. * (However uc_dstr_str() will return a valid (empty) string. * */ void uc_dstr_init(struct DStr *str); /** Initialize a DStr from an existing string * * @return 0 on success (!= 0 if an allocation fail) */ int uc_dstr_init_str(struct DStr *str, const char *init); /** Initialize a DStr from an existing string with a given length * * @return 0 on success (!= 0 if an allocation fail) */ int uc_dstr_init_str_sz(struct DStr *str, const char *init, size_t len); /** Destroy/free the string. * (Frees str->str, not str itself) */ void uc_dstr_destroy(struct DStr *str); /** Copy a DStr. * The @dest string should not be an initialized string since it will be * initialized by uc_dstr_copy, and would cause a memory leak if it's already * initialized. * * @param dest destination string to copy to, must not contain an existing string * @param src DStr to copy * * @return 0 if success, != 0 if allocation fails */ int uc_dstr_copy(struct DStr *restrict dest, const struct DStr *restrict src); /** * @return the available/unused tail bytes in the string. */ size_t uc_dstr_available(const struct DStr *str); /** Ensure the DStr have room for least 'len' bytes, * allocating room if needed. * * This includes the length of the existing string, * to ensure e.g an additional 10 bytes can be appended, * one would do uc_dstr_ensure(str, str->len + 10) * * @return 0 on success (!= 0 if an allocation fail) */ int uc_dstr_ensure(struct DStr *str, size_t total); /** Reset the DStr, setting its length to 0 */ void uc_dstr_reset(struct DStr *str); /** nul terminate the DStr */ void uc_dstr_terminate(struct DStr *str); /** Retreive the managed string, the returned string * is always nul terminated. The DStr will still be managing * the returned char *. */ char *uc_dstr_str(struct DStr *str); /** Reserve len bytes for appending to the dstr * you must copy characters to all bytes in the [0-len) range of * the returned pointer. * * @param len bytes to reseve * @return poiinter to the start of the data to append */ char *uc_dstr_put(struct DStr *str, size_t len); /** Append a string, filtering out characters. * e.g. pass in the ctype.h isdigit as the is_x function * to append only the digits in the supplied string. * * @param s string to append * @param is_x ctype.h compatible function to use as a filter. * @return number of chars appended */ size_t uc_dstr_append_str_filter(struct DStr *str, const char *restrict s, int (*is_x)(int c)); /* Append a string of the give size. * (The nul terminator is not appended) * * @param s string to append * @param len bytes to append (not including the nul terminator) * @return 0 on success (!= 0 if an allocation fail) */ int uc_dstr_append_str_sz(struct DStr *str, const char *restrict s, size_t len); /* Append a string. * (The nul terminator is not appended) * * @return 0 on success (!= 0 if an allocation fail) */ int uc_dstr_append_str(struct DStr *str, const char *restrict s); /* Append a single char. * * @return 0 on success (!= 0 if an allocation fail) */ int uc_dstr_append_char(struct DStr *str, char c); /* Make the DStr take ownership of the given dynamically allocated string. * Any existing string in the DStr is freed. */ void uc_dstr_own(struct DStr *str, char *restrict s); /** Release the managed string. * The caller is now responsible for managing/free'ing the returned string. * The DStr is considered empty afterwards. * * @return The dynamically allocated string that was managed. */ char *uc_dstr_steal(struct DStr *str); /** Swap the A and B DStr */ void uc_str_swap(struct DStr *restrict a, struct DStr *restrict b); /** Replace all occurences in the DStr * (This may be used to replace any embedded nul bytes too) * * @param f char to find * @param r char to replace with */ size_t uc_dstr_replace(struct DStr *str, char f, char r); /** Remove leading and trailing spaces in the DStr * Spaces are the ascii ones: " \t\r\v\t\n" */ void uc_dstr_trim(struct DStr *str); /** Append formatted string (just as sprintf)*/ int uc_dstr_sprintf(struct DStr *str, const char *restrict fmt, ...) __attribute__((format(printf,2,3))); /** va_list variant */ int uc_dstr_vsprintf(struct DStr *str, const char *restrict fmt, va_list ap_)__attribute__((format(printf,2,0))); #ifdef __cplusplus } #endif #endif