summaryrefslogtreecommitdiff
path: root/42sh/src/utils/basicstring.c
blob: 6efbe1fcfe84168f5b27a654bf090a1cc2a022db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <stdio.h>
#include <stdlib.h>

#include "libstring.h"

struct string *string_create(char *s)
{
    if (!s)
    {
        struct string *r = calloc(1, sizeof(struct string));
        char *data = calloc((BASE_STRING_SIZE + 1), sizeof(char));
        if (!r || !data)
        {
            fprintf(stderr, "string_create: calloc failed.\n");
            return NULL;
        }
        r->data = data;
        r->capacity = BASE_STRING_SIZE;
        return r;
    }

    struct string *str = malloc(1 * sizeof(struct string));
    if (!str)
    {
        fprintf(stderr, "string_create: malloc failed.\n");
        return NULL;
    }

    // Align the capacity on the string base size
    size_t l = strlen(s);
    size_t m = (l + 1) % BASE_STRING_SIZE;
    str->length = l;
    str->capacity = (l + 1) + (BASE_STRING_SIZE - m);
    str->data = calloc(str->capacity, sizeof(char));
    if (!str->data)
    {
        fprintf(stderr, "string_create: malloc failed.\n");
        return NULL;
    }
    memcpy(str->data, s, l);

    return str;
}

void string_free(struct string *str)
{
    if (str)
    {
        free(str->data);
        free(str);
    }
}

static bool _resize_string(struct string *str, int p)
{
    char *new_data = realloc(
        str->data, ((p >= 0) ? str->capacity * 2 : str->capacity / 2) + 1);
    if (!new_data)
    {
        fprintf(stderr, "_resize_string: realloc failed.\n");
        return false;
    }

    str->data = new_data;
    str->capacity = ((p >= 0) ? str->capacity * 2 : str->capacity / 2);
    return true;
}

bool string_pushc(struct string *str, char c)
{
    if (str->length == str->capacity)
    {
        if (!_resize_string(str, 1))
        {
            return false;
        }
    }
    str->data[str->length] = c;
    str->length++;
    str->data[str->length] = 0;
    return true;
}

bool string_pushstr(struct string *str, char *s)
{
    if (!s || !s[0])
    {
        return true;
    }
    size_t l = strlen(s);
    while (str->length + l >= str->capacity)
    {
        if (!_resize_string(str, 1))
        {
            return false;
        }
    }

    memcpy(str->data + str->length, s, l);
    str->length += l;
    str->data[str->length] = 0;
    return true;
}

bool string_catenate(struct string *dst, struct string *src)
{
    if (!src)
    {
        return true;
    }

    if (!dst || !string_pushstr(dst, src->data))
    {
        return false;
    }

    string_free(src);
    return true;
}

struct string *string_deepcopy(struct string *str)
{
    return string_create(str->data);
}