aboutsummaryrefslogtreecommitdiff
path: root/cstring/include/cstring.h
blob: 644f1e1dcc72a7c12c4c579ee8685eba9a62d1c3 (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
/// Fixed-size strings with value semantics.
#pragma once

#include <assert.h>
#include <bsd/string.h>

/// A fixed-size string.
/// The string is null-terminated so that it can be used with the usual C APIs.
#define DEF_STRING(STRING, SIZE)                                               \
  typedef struct STRING {                                                      \
    int length;                                                                \
    char str[SIZE];                                                            \
  } STRING;                                                                    \
                                                                               \
  static const size_t STRING##_size = SIZE;                                    \
                                                                               \
  static inline const char* STRING##_cstring(const STRING* str) {              \
    return str->str;                                                           \
  }                                                                            \
                                                                               \
  static inline STRING STRING##_make(const char* cstr) {                       \
    if (!cstr) {                                                               \
      return (STRING){0};                                                      \
    } else {                                                                   \
      STRING str = (STRING){0};                                                \
      str.length = strlcpy(str.str, cstr, SIZE);                               \
      return str;                                                              \
    }                                                                          \
  }                                                                            \
                                                                               \
  static inline STRING STRING##_dirname(STRING path) {                         \
    STRING str = path;                                                         \
    for (int i = str.length - 1; i >= 0; --i) {                                \
      if (str.str[i] == '/' || str.str[i] == '\\') {                           \
        str.str[i] = 0;                                                        \
        str.length = i;                                                        \
        return str;                                                            \
      } else {                                                                 \
        str.str[i] = 0;                                                        \
      }                                                                        \
    }                                                                          \
    str = (STRING){0};                                                         \
    str.str[0] = '.';                                                          \
    str.length = 1;                                                            \
    return str;                                                                \
  }                                                                            \
                                                                               \
  static inline STRING STRING##_concat(STRING a, STRING b) {                   \
    assert(a.length + b.length + 1 < SIZE);                                    \
    STRING str = {0};                                                          \
    strlcpy(str.str, a.str, SIZE);                                             \
    strlcpy(str.str + a.length, b.str, SIZE);                                  \
    str.length = a.length + b.length;                                          \
    return str;                                                                \
  }                                                                            \
                                                                               \
  static inline STRING STRING##_concat_path(STRING a, STRING b) {              \
    return STRING##_concat(STRING##_concat(a, STRING##_make("/")), b);         \
  }

DEF_STRING(sstring, 32)    // Small.
DEF_STRING(mstring, 256)   // Medium.
DEF_STRING(lstring, 1024)  // Large.
DEF_STRING(xlstring, 4096) // Extra large.