Codebase list massdns / 1fdacb08-88cf-4a4b-82c3-5eb6e4436f15/main string.h
1fdacb08-88cf-4a4b-82c3-5eb6e4436f15/main

Tree @1fdacb08-88cf-4a4b-82c3-5eb6e4436f15/main (Download .tar.gz)

string.h @1fdacb08-88cf-4a4b-82c3-5eb6e4436f15/mainraw · history · blame

#ifndef INC_STRING
#define INC_STRING

#include "security.h"

#include <stdbool.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>

char *strmcpy(const char *str)
{
    size_t len = strlen(str);
    char *result = safe_malloc(len + 1);
    memcpy(result, str, len);
    result[len] = 0;
    return result;
}

size_t string_copy(char *dest, const char *src, size_t n)
{
    size_t i;

    for (i = 0; i < n - 1 && src[i] != '\0'; i++) {
        dest[i] = src[i];
    }
    dest[i] = 0;
    return i;
}

void *flatcopy(void *src, size_t len)
{
    void *dst = safe_malloc(len);
    memcpy(dst, src, len);
    return dst;
}

void strtolower(char *str)
{
    while (*str != '\0')
    {
        if (*str >= 'A' && *str <= 'Z')
        {
            *str = (char) (*str | (1 << 5));
        }
        str++;
    }
}

char *trim_start(char *str)
{
    while (0 != *str)
    {
        if(!isspace(*str))
        {
            return str;
        }
        str++;
    }
    return str;
}

void trim_end(char* str)
{
    char *last = str + strlen(str) - 1;
    while (last >= str)
    {
        if(!isspace(*last))
        {
            return;
        }
        *last = 0;
        last--;
    }
}

bool endswith(char* haystack, char* needle, bool case_sensitive)
{
    int (*cmp)(const char*, const char*) = strcmp;
    if(!case_sensitive)
    {
        cmp = strcasecmp;
    }
    size_t haystack_len = strlen(haystack);
    size_t needle_len = strlen(needle);
    return needle_len <= haystack_len && cmp(haystack + haystack_len - needle_len, needle) == 0;
}

bool startswith(char* haystack, char* needle, bool case_sensitive) // Supports ASCII only
{
    while(true)
    {
        char nchar = *needle++;
        char hchar = *haystack++;
        if(nchar == 0)
        {
            return true;
        }
        else if(hchar == 0)
        {
            return false;
        }
        if(case_sensitive)
        {
            nchar = (char)tolower(nchar);
            hchar = (char)tolower(hchar);
        }
        if(nchar != hchar)
        {
            return false;
        }
    }
}

#define require_space(N) if(dst_idx >= dst_len - (N)) goto json_escape_finalize;

#define json_escape_body(BREAK_COND) \
    const char complex_chars[] = "abtnvfr"; \
    size_t dst_idx = 0; \
 \
    for(size_t i = 0; (BREAK_COND); i++) \
    { \
        size_t complex_idx = 0; \
        switch(src[i]) \
        { \
            case '\\': \
            case '\"': \
                require_space(2); \
                dst[dst_idx++] = '\\'; \
                dst[dst_idx++] = src[i]; \
                break; \
            case '\r': complex_idx++; \
            case '\f': complex_idx++; \
            case '\v': complex_idx++; \
            case '\n': complex_idx++; \
            case '\t': complex_idx++; \
            case '\b': complex_idx++; \
            case '\a': \
                require_space(2); \
                dst[dst_idx++] = '\\'; \
                dst[dst_idx++] = complex_chars[complex_idx]; \
                break; \
            default: \
                if(isprint(src[i])) \
                { \
                    require_space(1); \
                    dst[dst_idx++] = src[i]; \
                } \
                else \
                { \
                    require_space(4); \
                    dst[dst_idx++] = '\\'; \
                    dst[dst_idx++] = (char)(((src[i] & 0300) >> 6) + '0'); \
                    dst[dst_idx++] = (char)(((src[i] & 0070) >> 3) + '0'); \
                    dst[dst_idx++] = (char)(((src[i] & 0007) >> 0) + '0'); \
                } \
                break; \
        } \
    } \
    json_escape_finalize: \
    dst[dst_idx++] = 0; \
    return dst_idx;

size_t json_escape_str(char *dst, size_t dst_len, const char *src)
{
    json_escape_body(src[i] != 0);
}

// Buffer needs to have at least one byte.
size_t json_escape(char *dst, size_t dst_len, const uint8_t *src, size_t src_len)
{
    json_escape_body(i != src_len);
}

#undef require_space
#undef json_escape_body

#endif