andre@25: /* Copyright (C) 2015 by ETH Zürich andre@25: * Software engineering by Intevation GmbH andre@0: * andre@0: * This file is Free Software under the GNU GPL (v>=2) andre@0: * and comes with ABSOLUTELY NO WARRANTY! andre@0: * See LICENSE.txt for details. andre@0: */ andre@0: /* Needed to get asprintf */ andre@0: #define _GNU_SOURCE 1 andre@0: andre@0: /** @file See strhelp.h for documentation. */ andre@0: andre@0: #include andre@0: #include andre@0: #include andre@0: #include andre@0: #include andre@0: #include andre@0: #include andre@0: andre@112: #ifdef _WIN32 andre@0: #include andre@0: #endif andre@0: andre@0: static void andre@0: out_of_core(void) andre@0: { andre@0: fputs("\nfatal: out of memory\n", stderr); andre@0: exit(2); andre@0: } andre@0: andre@0: void * andre@0: xmalloc( size_t n ) andre@0: { andre@0: void *p = malloc( n ); andre@0: if( !p ) andre@0: out_of_core(); andre@0: return p; andre@0: } andre@0: andre@0: void * andre@0: xmalloc0( size_t n ) andre@0: { andre@0: void *p = malloc( n ); andre@0: if( !p ) andre@0: out_of_core(); andre@0: memset (p, 0, n); andre@0: return p; andre@0: } andre@0: andre@0: void * andre@0: xrealloc( void *a, size_t n ) andre@0: { andre@0: void *p = realloc( a, n ); andre@0: if( !p ) andre@0: out_of_core(); andre@0: return p; andre@0: } andre@0: andre@0: char * andre@0: xstrndup( const char *string, const size_t len ) andre@0: { andre@0: char *p = xmalloc( len + 1 ); andre@0: memcpy( p, string, len ); andre@0: p[len] = '\0'; andre@0: return p; andre@0: } andre@0: andre@0: unsigned int andre@0: strv_length (char **str_array) andre@0: { andre@0: unsigned int i = 0; andre@0: andre@0: if (!str_array) andre@0: return 0; andre@0: andre@0: while (str_array[i]) andre@0: ++i; andre@0: andre@0: return i; andre@0: } andre@0: andre@0: void strv_append (char ***pArray, const char *string, const size_t len) andre@0: { andre@0: unsigned int old_len = 0; andre@0: andre@0: if (!*pArray) andre@0: { andre@0: *pArray = xmalloc(2 * sizeof(char*)); andre@0: (*pArray)[0] = xstrndup(string, len); andre@0: (*pArray)[1] = NULL; andre@0: return; andre@0: } andre@0: old_len = strv_length(*pArray); andre@0: *pArray = xrealloc(*pArray, sizeof(char**) * (old_len + 2)); andre@0: andre@0: (*pArray)[old_len] = xstrndup(string, len); andre@0: (*pArray)[old_len + 1] = NULL; andre@0: } andre@0: andre@0: void andre@0: str_append_str(char **pDst, size_t *dst_len, const char *appendage, const size_t len) andre@0: { andre@0: if (!appendage) andre@0: return; andre@0: andre@0: if (!(*pDst)) andre@0: { andre@0: *pDst = xstrndup(appendage, len); andre@0: *dst_len = len; andre@0: } andre@0: else andre@0: { andre@0: size_t new_size = (*dst_len) + len + 1; andre@0: char *p_old = *pDst; andre@0: *pDst = xmalloc(new_size); andre@0: strncpy(*pDst, p_old, *dst_len); andre@0: strncpy(*pDst + *dst_len, appendage, len); andre@0: *dst_len = new_size - 1; andre@0: (*pDst)[*dst_len] = '\0'; andre@0: free (p_old); andre@0: } andre@0: } andre@0: andre@0: void andre@0: strv_free (char **str_array) andre@0: { andre@0: if (str_array) andre@0: { andre@0: int i; andre@0: andre@0: for (i = 0; str_array[i] != NULL; i++) andre@0: free (str_array[i]); andre@0: andre@0: free (str_array); andre@0: } andre@0: } andre@0: andre@0: bool andre@0: str_equal (char *s1, char *s2) andre@0: { andre@0: size_t l1 = strlen(s1); andre@0: size_t l2 = strlen(s2); andre@0: if ((l1 == l2) && andre@0: (strcmp(s1, s2) == 0)) andre@0: return true; andre@0: else andre@0: return false; andre@0: } andre@0: andre@0: bool andre@0: str_starts_with (char *s1, char *s2) andre@0: { andre@0: size_t l2 = strlen(s2); andre@0: if (strncmp(s1, s2, l2) == 0) andre@0: return true; andre@0: else andre@0: return false; andre@0: } andre@0: andre@0: void andre@0: str_trim (char **s) andre@0: { andre@0: size_t i; andre@0: if (*s != NULL) andre@0: { andre@0: while (isspace(**s)) andre@0: (*s)++; andre@0: i = strlen(*s); andre@0: while (isspace((*s)[--i])) andre@0: (*s)[i] = '\0'; andre@0: } andre@0: } andre@0: andre@0: void andre@0: xfree (void *p) andre@0: { andre@0: if (p) andre@0: free (p); andre@0: } andre@0: andre@0: int andre@0: xasprintf (char **strp, const char *fmt, ...) andre@0: { andre@0: int ret; andre@0: va_list ap; andre@0: va_start(ap, fmt); andre@0: ret = vasprintf(strp, fmt, ap); andre@0: va_end(ap); andre@0: andre@0: if (ret == -1) andre@0: out_of_core(); andre@0: andre@0: return ret; andre@0: } andre@0: andre@112: #ifdef _WIN32 andre@0: /* Adapted from GPGOL rev. e512053 */ andre@0: char * andre@0: wchar_to_utf8 (const wchar_t *string, size_t len) andre@0: { andre@0: int n, ilen; andre@0: char *result; andre@0: andre@0: ilen = (int) len; andre@0: if (ilen < 0) andre@0: return NULL; andre@0: andre@0: /* Note, that CP_UTF8 is not defined in Windows versions earlier andre@0: than NT.*/ andre@0: n = WideCharToMultiByte (CP_UTF8, 0, string, ilen, NULL, 0, NULL, NULL); andre@0: if (n < 0) andre@0: return NULL; andre@0: andre@0: result = xmalloc ((size_t)n+1); andre@0: n = WideCharToMultiByte (CP_UTF8, 0, string, ilen, result, n, NULL, NULL); andre@0: if (n < 0) andre@0: { andre@0: xfree (result); andre@0: return NULL; andre@0: } andre@0: result[n] = 0; andre@0: return result; andre@0: } andre@0: andre@0: /* Adapted from GPGOL rev. e512053 */ andre@0: wchar_t * andre@0: utf8_to_wchar (const char *string, size_t len) andre@0: { andre@0: int n, ilen; andre@0: wchar_t *result; andre@0: andre@0: ilen = (int) len; andre@0: if (ilen < 0) andre@0: return NULL; andre@0: andre@0: n = MultiByteToWideChar (CP_UTF8, 0, string, ilen, NULL, 0); andre@0: if (n < 0 || n + 1 < 0) andre@0: return NULL; andre@0: andre@0: result = xmalloc ((size_t)(n+1) * sizeof *result); andre@0: n = MultiByteToWideChar (CP_UTF8, 0, string, ilen, result, n); andre@0: if (n < 0) andre@0: { andre@0: xfree (result); andre@0: return NULL; andre@0: } andre@0: result[n] = 0; andre@0: return result; andre@0: } andre@0: andre@0: wchar_t andre@0: *acp_to_wchar (const char *string, size_t len) andre@0: { andre@0: int n, ilen; andre@0: wchar_t *result; andre@0: andre@0: ilen = (int) len; andre@0: if (ilen < 0) andre@0: return NULL; andre@0: andre@0: n = MultiByteToWideChar (CP_ACP, 0, string, ilen, NULL, 0); andre@0: if (n < 0 || n + 1 < 0) andre@0: return NULL; andre@0: andre@0: result = xmalloc ((size_t)(n+1) * sizeof *result); andre@0: n = MultiByteToWideChar (CP_ACP, 0, string, ilen, result, n); andre@0: if (n < 0) andre@0: { andre@0: xfree (result); andre@0: return NULL; andre@0: } andre@0: result[n] = 0; andre@0: return result; andre@0: } andre@0: #endif andre@0: