X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=string.c;h=46b346235f17ffb696f43d22d3dcfde4c75ba4ca;hb=9055c71be97f1095dcdbd83da305b600f204f763;hp=b75d0af33959619a01a812b7838389ea1b95761a;hpb=610cb53b94af8e95326cd44b7845f35cffdb6bf3;p=paraslash.git diff --git a/string.c b/string.c index b75d0af3..46b34623 100644 --- a/string.c +++ b/string.c @@ -14,6 +14,91 @@ #include "string.h" #include "error.h" +/** + * Reallocate an array, abort on failure or bugs. + * + * \param ptr Pointer to the memory block, may be NULL. + * \param nmemb Number of elements. + * \param size The size of one element in bytes. + * + * A wrapper for realloc(3) which aborts on invalid arguments or integer + * overflow. The wrapper also terminates the current process on allocation + * errors, so the caller does not need to check for failure. + * + * \return A pointer to newly allocated memory which is suitably aligned for + * any kind of variable and may be different from ptr. + * + * \sa realloc(3). + */ +__must_check void *arr_realloc(void *ptr, size_t nmemb, size_t size) +{ + size_t pr; + + assert(size > 0); + assert(nmemb > 0); + assert(!__builtin_mul_overflow(nmemb, size, &pr)); + assert(pr != 0); + ptr = realloc(ptr, pr); + assert(ptr); + return ptr; +} + +/** + * Allocate an array, abort on failure or bugs. + * + * \param nmemb See \ref arr_realloc(). + * \param size See \ref arr_realloc(). + * + * Like \ref arr_realloc(), this aborts on invalid arguments, integer overflow + * and allocation errors. + * + * \return A pointer to newly allocated memory which is suitably aligned for + * any kind of variable. + * + * \sa See \ref arr_realloc(). + */ +__must_check __malloc void *arr_alloc(size_t nmemb, size_t size) +{ + return arr_realloc(NULL, nmemb, size); +} + +/** + * Allocate and initialize an array, abort on failure or bugs. + * + * \param nmemb See \ref arr_realloc(). + * \param size See \ref arr_realloc(). + * + * This calls \ref arr_alloc() and zeroes-out the array. + * + * \return See \ref arr_alloc(). + */ +__must_check __malloc void *arr_zalloc(size_t nmemb, size_t size) +{ + void *ptr = arr_alloc(nmemb, size); + + /* + * This multiplication can not overflow because the above call to \ref + * arr_alloc() aborts on overflow. + */ + memset(ptr, 0, nmemb * size); + return ptr; +} + +/** + * Allocate and initialize memory. + * + * \param size The desired new size. + * + * \return A pointer to the allocated and zeroed-out memory, which is suitably + * aligned for any kind of variable. + * + * \sa \ref alloc(), calloc(3). + */ +__must_check void *zalloc(size_t size) +{ + return arr_zalloc(1, size); +} + /** * Paraslash's version of realloc(). * @@ -30,17 +115,7 @@ */ __must_check void *para_realloc(void *p, size_t size) { - /* - * No need to check for NULL pointers: If p is NULL, the call - * to realloc is equivalent to malloc(size) - */ - assert(size); - if (!(p = realloc(p, size))) { - PARA_EMERG_LOG("realloc failed (size = %zu), aborting\n", - size); - exit(EXIT_FAILURE); - } - return p; + return arr_realloc(p, 1, size); } /** @@ -57,36 +132,7 @@ __must_check void *para_realloc(void *p, size_t size) */ __must_check __malloc void *alloc(size_t size) { - void *p; - - assert(size); - p = malloc(size); - if (!p) { - PARA_EMERG_LOG("malloc failed (size = %zu), aborting\n", - size); - exit(EXIT_FAILURE); - } - return p; -} - -/** - * Paraslash's version of calloc(). - * - * \param size The desired new size. - * - * A wrapper for calloc(3) which exits on errors. - * - * \return A pointer to the allocated and zeroed-out memory, which is suitably - * aligned for any kind of variable. - * - * \sa calloc(3) - */ -__must_check __malloc void *para_calloc(size_t size) -{ - void *ret = alloc(size); - - memset(ret, 0, size); - return ret; + return arr_alloc(1, size); } /** @@ -553,37 +599,6 @@ int para_atoi32(const char *str, int32_t *value) return 1; } -static inline int loglevel_equal(const char *arg, const char * const ll) -{ - return !strncasecmp(arg, ll, strlen(ll)); -} - -/** - * Compute the loglevel number from its name. - * - * \param txt The name of the loglevel (debug, info, ...). - * - * \return The numeric representation of the loglevel name. - */ -int get_loglevel_by_name(const char *txt) -{ - if (loglevel_equal(txt, "debug")) - return LL_DEBUG; - if (loglevel_equal(txt, "info")) - return LL_INFO; - if (loglevel_equal(txt, "notice")) - return LL_NOTICE; - if (loglevel_equal(txt, "warning")) - return LL_WARNING; - if (loglevel_equal(txt, "error")) - return LL_ERROR; - if (loglevel_equal(txt, "crit")) - return LL_CRIT; - if (loglevel_equal(txt, "emerg")) - return LL_EMERG; - return -E_BAD_LL; -} - static int get_next_word(const char *buf, const char *delim, char **word) { enum line_state_flags {LSF_HAVE_WORD = 1, LSF_BACKSLASH = 2, @@ -724,7 +739,7 @@ void free_argv(char **argv) static int create_argv_offset(int offset, const char *buf, const char *delim, char ***result) { - char *word, **argv = alloc((offset + 1) * sizeof(char *)); + char *word, **argv = arr_alloc(offset + 1, sizeof(char *)); const char *p; int i, ret; @@ -736,7 +751,7 @@ static int create_argv_offset(int offset, const char *buf, const char *delim, goto err; if (!ret) break; - argv = para_realloc(argv, (i + 2) * sizeof(char*)); + argv = arr_realloc(argv, i + 2, sizeof(char*)); argv[i] = word; } argv[i] = NULL; @@ -791,27 +806,6 @@ int create_shifted_argv(const char *buf, const char *delim, char ***result) return create_argv_offset(1, buf, delim, result); } -/** - * Find out if the given string is contained in the arg vector. - * - * \param arg The string to look for. - * \param argv The array to search. - * - * \return The first index whose value equals \a arg, or \p -E_ARG_NOT_FOUND if - * arg was not found in \a argv. - */ -int find_arg(const char *arg, char **argv) -{ - int i; - - if (!argv) - return -E_ARG_NOT_FOUND; - for (i = 0; argv[i]; i++) - if (strcmp(arg, argv[i]) == 0) - return i; - return -E_ARG_NOT_FOUND; -} - /** * Compile a regular expression. * @@ -1012,7 +1006,7 @@ __must_check int strwidth(const char *s, size_t *result) return -ERRNO_TO_PARA_ERROR(errno); if (num_wchars == 0) return 0; - dest = alloc((num_wchars + 1) * sizeof(*dest)); + dest = arr_alloc(num_wchars + 1, sizeof(*dest)); src = s; memset(&state, 0, sizeof(state)); num_wchars = mbsrtowcs(dest, &src, num_wchars, &state); @@ -1067,7 +1061,7 @@ __must_check int sanitize_str(const char *src, size_t max_width, num_wchars = mbsrtowcs(NULL, &src, 0, &state); if (num_wchars == (size_t)-1) return -ERRNO_TO_PARA_ERROR(errno); - wcs = alloc((num_wchars + 1) * sizeof(*wcs)); + wcs = arr_alloc(num_wchars + 1, sizeof(*wcs)); memset(&state, 0, sizeof(state)); num_wchars = mbsrtowcs(wcs, &src, num_wchars + 1, &state); assert(num_wchars != (size_t)-1);