strings.c 2.6 KiB raw
1
#include <string.h>
2
3
#include "strings.h"
4
#include "types.h"
5
6
/* Global string interning system */
7
static struct {
8
    char  strings[MAX_STRINGS][MAX_STRING_LEN];
9
    usize nstrings;
10
    bool  initialized;
11
} table = { 0 };
12
13
/* Initialize the global string interning system */
14
void strings_init(void) {
15
    table.nstrings    = 0;
16
    table.initialized = true;
17
}
18
19
/* Process escape sequences in a string */
20
static usize escape(const char *src, usize src_len, char *dst, usize dst_size) {
21
    usize dst_idx = 0;
22
23
    for (usize i = 0; i < src_len && dst_idx < dst_size - 1; i++) {
24
        if (src[i] == '\\' && i + 1 < src_len) {
25
            switch (src[i + 1]) {
26
            case 'n':
27
                dst[dst_idx++] = '\n';
28
                i++; /* Skip the next character */
29
                break;
30
            case 't':
31
                dst[dst_idx++] = '\t';
32
                i++;
33
                break;
34
            case 'r':
35
                dst[dst_idx++] = '\r';
36
                i++;
37
                break;
38
            case '\\':
39
                dst[dst_idx++] = '\\';
40
                i++;
41
                break;
42
            case '"':
43
                dst[dst_idx++] = '"';
44
                i++;
45
                break;
46
            case '0':
47
                dst[dst_idx++] = '\0';
48
                i++;
49
                break;
50
            default:
51
                /* Unknown escape sequence, keep the backslash */
52
                dst[dst_idx++] = src[i];
53
                break;
54
            }
55
        } else {
56
            dst[dst_idx++] = src[i];
57
        }
58
    }
59
    dst[dst_idx] = '\0';
60
61
    return dst_idx;
62
}
63
64
/* Find an existing interned string */
65
static const char *find(const char *str) {
66
    for (usize i = 0; i < table.nstrings; i++) {
67
        if (!strcmp(table.strings[i], str)) {
68
            return table.strings[i];
69
        }
70
    }
71
    return NULL;
72
}
73
74
/* Intern a raw string without escape sequence processing */
75
static const char *strings_alloc_raw(const char *str) {
76
    /* Check if already interned */
77
    const char *existing = find(str);
78
    if (existing) {
79
        return existing;
80
    }
81
82
    char *slot = table.strings[table.nstrings++];
83
    strncpy(slot, str, MAX_STRING_LEN);
84
85
    return slot;
86
}
87
88
/* Intern a string with escape sequence processing */
89
const char *strings_alloc_len(const char *str, u16 len) {
90
    /* Process escape sequences first */
91
    char escaped[MAX_STRING_LEN];
92
    escape(str, len, escaped, MAX_STRING_LEN);
93
94
    return strings_alloc_raw(escaped);
95
}
96
97
/* Intern a string with escape sequence processing */
98
const char *strings_alloc(const char *str) {
99
    return strings_alloc_len(str, strlen(str));
100
}