view src/dmstring.c @ 2208:90ec1ec89c56

Revamp the palette handling in lib64gfx somewhat, add helper functions to lib64util for handling external palette file options and add support for specifying one of the "internal" palettes or external (.act) palette file to gfxconv and 64vw.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 Jun 2019 05:01:12 +0300
parents 9b6027d51f76
children 63dd0a611586
line wrap: on
line source

#include "dmlib.h"
#include <stdarg.h>


/* Compare two strings ignoring case [strcasecmp, strncasecmp]
 */
int dm_strcasecmp(const char *haystack, const char *needle)
{
    const char *s1 = haystack, *s2 = needle;
    assert(haystack != NULL);
    assert(needle != NULL);

    if (haystack == needle)
        return 0;

    while (*s1 && *s2)
    {
        int k = tolower(*s1) - tolower(*s2);
        if (k != 0)
            return k;
        s1++;
        s2++;
    }

    return 0;
}


int dm_strncasecmp(const char *haystack, const char *needle, size_t n)
{
    const char *s1 = haystack, *s2 = needle;
    assert(haystack != NULL);
    assert(needle != NULL);

    if (haystack == needle)
        return 0;

    while (n > 0 && *s1 && *s2)
    {
        int k = tolower(*s1) - tolower(*s2);
        if (k != 0)
            return k;
        s1++;
        s2++;
        n--;
    }

    return 0;
}


/* Check if end of the given string str matches needle
 * case-insensitively, return pointer to start of the match,
 * if found, NULL otherwise.
 */
char *dm_strrcasecmp(char *str, const char *needle)
{
    if (str == NULL || needle == NULL)
        return NULL;

    const size_t
        slen = strlen(str),
        nlen = strlen(needle);

    if (slen < nlen)
        return NULL;

    if (dm_strcasecmp(str + slen - nlen, needle) == 0)
        return str + slen - nlen;
    else
        return NULL;
}


/* Implementation of strdup() with a NULL check
 */
char *dm_strdup(const char *s)
{
    char *res;
    if (s == NULL)
        return NULL;

    if ((res = dmMalloc(strlen(s) + 1)) == NULL)
        return NULL;

    strcpy(res, s);
    return res;
}


/* Implementation of strndup() with NULL check
 */
char *dm_strndup(const char *str, const size_t n)
{
    char *res;
    if (str == NULL)
        return NULL;

    size_t len = strlen(str);
    if (len > n)
        len = n;

    if ((res = dmMalloc(len + 1)) == NULL)
        return NULL;

    memcpy(res, str, len);
    res[len] = 0;

    return res;
}


/* Like strdup, but trims whitespace from the string according to specified flags.
 * See DM_TRIM_* in dmlib.h. If the resulting string would be empty (length 0),
 * NULL is returned.
 */
static char * dm_strdup_trim_do(const char *src, size_t len, const int flags)
{
    char *res;
    size_t start, end;

    if (len == 0)
        return NULL;

    // Trim start: find first non-whitespace character
    if (flags & DM_TRIM_START)
        for (start = 0; start < len && isspace(src[start]); start++);
    else
        start = 0;

    // Trim end: find last non-whitespace character
    if (flags & DM_TRIM_END)
        for (end = len - 1; end > start && isspace(src[end]); end--);
    else
        end = len;

    // Allocate memory for result
    if (src[end] == 0 || isspace(src[end]))
        return NULL;

    len = end - start + 1;
    if ((res = dmMalloc(len + 1)) == NULL)
        return NULL;

    memcpy(res, src + start, len);
    res[len] = 0;
    return res;
}


char *dm_strdup_trim(const char *src, const int flags)
{
    if (src == NULL)
        return NULL;

    return dm_strdup_trim_do(src, strlen(src), flags);
}


char *dm_strndup_trim(const char *src, const size_t n, const int flags)
{
    size_t len;
    if (src == NULL || n == 0)
        return NULL;

    for (len = 0; len < n && src[len]; len++);

    return dm_strdup_trim_do(src, len, flags);
}


/* Simulate a sprintf() that allocates memory
 */
char *dm_strdup_vprintf_len(const char *fmt, va_list args, int *len)
{
    int size = 64;
    char *buf, *tmp;

    if ((buf = dmMalloc(size)) == NULL)
        return NULL;

    while (1)
    {
        va_list ap;
        va_copy(ap, args);
        *len = vsnprintf(buf, size, fmt, ap);
        va_end(ap);

        if (*len > -1 && *len < size)
            return buf;
        if (*len > -1)
            size = *len + 1;
        else
            size *= 2;

        if ((tmp = dmRealloc(buf, size)) == NULL)
        {
            dmFree(buf);
            return NULL;
        }
        else
            buf = tmp;
    }
}


char *dm_strdup_vprintf(const char *fmt, va_list args)
{
    int len;
    return dm_strdup_vprintf_len(fmt, args, &len);
}


char *dm_strdup_printf(const char *fmt, ...)
{
    int len;
    char *res;
    va_list ap;

    va_start(ap, fmt);
    res = dm_strdup_vprintf_len(fmt, ap, &len);
    va_end(ap);

    return res;
}