/Users/alexjokela/projects/lattice/src/format_ops.c
Line | Count | Source |
1 | | #include "format_ops.h" |
2 | | |
3 | | #include <stdlib.h> |
4 | | #include <string.h> |
5 | | |
6 | 75 | char *format_string(const char *fmt, const LatValue *args, size_t argc, char **err) { |
7 | 75 | size_t buf_cap = 128; |
8 | 75 | size_t buf_len = 0; |
9 | 75 | char *buf = malloc(buf_cap); |
10 | 75 | if (!buf) { *err = strdup("format: out of memory"); return NULL; } |
11 | | |
12 | 75 | size_t arg_idx = 0; |
13 | 75 | const char *p = fmt; |
14 | | |
15 | 822 | while (*p) { |
16 | | /* Escaped braces: {{ -> {, }} -> } */ |
17 | 750 | if (p[0] == '{' && p[1] == '{') { |
18 | 3 | if (buf_len + 1 >= buf_cap) { buf_cap *= 2; buf = realloc(buf, buf_cap); } |
19 | 3 | buf[buf_len++] = '{'; |
20 | 3 | p += 2; |
21 | 3 | continue; |
22 | 3 | } |
23 | 747 | if (p[0] == '}' && p[1] == '}') { |
24 | 3 | if (buf_len + 1 >= buf_cap) { buf_cap *= 2; buf = realloc(buf, buf_cap); } |
25 | 3 | buf[buf_len++] = '}'; |
26 | 3 | p += 2; |
27 | 3 | continue; |
28 | 3 | } |
29 | | |
30 | | /* Placeholder: {} */ |
31 | 744 | if (p[0] == '{' && p[1] == '}') { |
32 | 105 | if (arg_idx >= argc) { |
33 | 3 | free(buf); |
34 | 3 | *err = strdup("format: not enough arguments for placeholders"); |
35 | 3 | return NULL; |
36 | 3 | } |
37 | 102 | char *display = value_display(&args[arg_idx]); |
38 | 102 | size_t dlen = strlen(display); |
39 | 102 | while (buf_len + dlen >= buf_cap) { buf_cap *= 2; buf = realloc(buf, buf_cap); } |
40 | 102 | memcpy(buf + buf_len, display, dlen); |
41 | 102 | buf_len += dlen; |
42 | 102 | free(display); |
43 | 102 | arg_idx++; |
44 | 102 | p += 2; |
45 | 102 | continue; |
46 | 105 | } |
47 | | |
48 | | /* Regular character */ |
49 | 639 | if (buf_len + 1 >= buf_cap) { buf_cap *= 2; buf = realloc(buf, buf_cap); } |
50 | 639 | buf[buf_len++] = *p; |
51 | 639 | p++; |
52 | 639 | } |
53 | | |
54 | 72 | buf[buf_len] = '\0'; |
55 | | *err = NULL; |
56 | 72 | return buf; |
57 | 75 | } |