libclod
C library for interacting with NBTs, region files, LOD data and other things.
Loading...
Searching...
No Matches
serialise.c
1#include <clod/string.h>
2
3static bool base_valid(const int base, const struct clod_string alphabet) {
4 return 2 <= base && base <= 64 && base <= alphabet.len;
5}
6
7static int digit_count(uintmax_t value, const int base) {
8 int count = 0;
9 do {
10 value /= (uintmax_t)base;
11 count++;
12 } while (value > 0);
13 return count;
14}
15
16size_t clod_string_put_int(struct clod_string *dst, intmax_t val,
17 const struct clod_string alphabet, const unsigned char base, const unsigned char min_digits, const unsigned char max_digits) {
18 if (!base_valid(base, alphabet)) {
19 return 0;
20 }
21
22 if (val < 0) {
23 clod_string_put_char(dst, '-');
24 val = -val;
25 } else {
26 clod_string_put_char(dst, '+');
27 }
28
29 return clod_string_put_uint(dst, (uintmax_t)val, alphabet, base, min_digits, max_digits) + 1;
30}
31intmax_t clod_string_get_int(struct clod_string *str, const struct clod_string alphabet, const unsigned char base) {
32 if (!str->ptr || str->len < 2 || !base_valid(base, alphabet)) {
33 return 0;
34 }
35
36 if (str->ptr[0] != '+' && str->ptr[0] != '-') {
37 return 0;
38 }
39
40 if (!clod_string_find(alphabet, str->ptr[0], 1).ptr) {
41 return 0;
42 }
43
44 if (str->ptr[0] == '+') {
45 return (intmax_t)clod_string_get_uint(str, alphabet, base);
46 } else {
47 return -(intmax_t)clod_string_get_uint(str, alphabet, base);
48 }
49}
50size_t clod_string_put_uint(struct clod_string *dst, uintmax_t val,
51 const struct clod_string alphabet, const unsigned char base, const unsigned char min_digits, const unsigned char max_digits) {
52 if (!dst->ptr || !base_valid(base, alphabet)) {
53 return 0;
54 }
55
56 int size = digit_count(val, base);
57 if (max_digits && size > max_digits) size = max_digits;
58 if (size < min_digits) size = min_digits;
59
60 for (int i = size - 1; i >= 0; i--) {
61 if (dst->cap - dst->len - i > 0) {
62 dst->ptr[dst->len + i] = alphabet.ptr[val % (uintmax_t)base];
63 }
64 val /= (uintmax_t)base;
65 }
66
67 dst->len += size;
68 return (size_t)size;
69}
70uintmax_t clod_string_get_uint(struct clod_string *str, const struct clod_string alphabet, const unsigned char base) {
71 if (!str->ptr || str->len < 1 || !base_valid(base, alphabet)) {
72 return 0;
73 }
74
75 uintmax_t result = 0;
76 while (str->len > 0) {
77 struct clod_string digit = clod_string_find(alphabet, str->ptr[0], 1);
78 if (!digit.ptr || digit.ptr - alphabet.ptr >= base) break;
79
80 result *= (uintmax_t)base;
81 result += (uintmax_t)(digit.ptr - alphabet.ptr);
82 str->ptr++;
83 str->len--;
84 }
85
86 return result;
87}
Sized string helpers.
CLOD_API size_t clod_string_put_int(struct clod_string *dst, intmax_t val, struct clod_string alphabet, unsigned char base, unsigned char min_digits, unsigned char max_digits)
Definition serialise.c:16
CLOD_API size_t clod_string_put_uint(struct clod_string *dst, uintmax_t val, struct clod_string alphabet, unsigned char base, unsigned char min_digits, unsigned char max_digits)
Definition serialise.c:50
CLOD_API struct clod_string clod_string_find(struct clod_string str, char elem, int occurrence)
Definition string.c:147
CLOD_API uintmax_t clod_string_get_uint(struct clod_string *str, struct clod_string alphabet, unsigned char base)
Definition serialise.c:70
void clod_string_put_char(struct clod_string *str, char c)
Append a single char to the end of the string.
Definition string.c:87
CLOD_API intmax_t clod_string_get_int(struct clod_string *str, struct clod_string alphabet, unsigned char base)
Definition serialise.c:31
char * ptr
Definition string.h:28
ptrdiff_t len
Definition string.h:32
ptrdiff_t cap
Definition string.h:36