kiba-engine
integer.c
1 #include <kiba/format/defaults/integer.h>
2 
3 #include <kiba/core/memory.h>
4 #include <kiba/core/string.h>
5 
6 b8 format_read_unsigned_decimal(format_buffer *buf, format_options options, u64 *value) {
7  usize left_pad_length = 0;
8  while (format_buffer_match_char(buf, FORMAT_PADDING_CHAR)) {
9  ++left_pad_length;
10  }
11  char c;
12  if (!(format_buffer_peak_char(buf, &c) && character_is_decimal(c))) {
13  return false;
14  }
15  format_buffer_advance(buf);
16  u64 res = (u64) c - '0';
17  usize digits = 1;
18  while (format_buffer_peak_char(buf, &c) && character_is_decimal(c)) {
19  format_buffer_advance(buf);
20  u64 digit = (u64) c - '0';
21  res = res * 10 + digit;
22  ++digits;
23  }
24  *value = res;
25  usize left_pad, right_pad;
26  format_calculate_padding(options, digits, &left_pad, &right_pad);
27  usize i = 0;
28  for (; i < right_pad && format_buffer_match_char(buf, FORMAT_PADDING_CHAR); ++i)
29  ;
30  return left_pad_length == left_pad && i == right_pad;
31 }
32 
33 b8 format_write_unsigned_decimal(format_buffer *buf, format_options options, u64 value) {
34  char buffer[20];
35  const usize size = sizeof(buffer) / sizeof(buffer[0]);
36  buffer[19] = '0'; // used in case the value is just 0
37  usize digits = 0;
38  for (; value != 0LU; value /= 10LU, ++digits) {
39  u64 digit = value % 10LU;
40  buffer[size - digits - 1] = (char) digit + '0';
41  }
42  digits = KB_MAX(digits, 1); // account for value of 0
43  usize left_pad, right_pad;
44  format_calculate_padding(options, digits, &left_pad, &right_pad);
45  return format_buffer_add_char_n(buf, FORMAT_PADDING_CHAR, left_pad)
46  && format_buffer_add_chars(buf, buffer + size - digits, digits)
47  && format_buffer_add_char_n(buf, FORMAT_PADDING_CHAR, right_pad);
48 }
49 
50 b8 format_read_signed_decimal(format_buffer *buf, format_options options, i64 *value) {
51  usize left_pad_length = 0;
52  while (format_buffer_match_char(buf, FORMAT_PADDING_CHAR)) {
53  ++left_pad_length;
54  }
55  char c;
56  if (!format_buffer_peak_char(buf, &c)) {
57  return false;
58  }
59  i64 factor = 1;
60  usize digits = 1;
61  if (c == '-') {
62  factor = -1;
63  ++digits;
64  if (!(format_buffer_advance(buf) && format_buffer_peak_char(buf, &c))) {
65  return false;
66  }
67  }
68  if (!character_is_decimal(c)) {
69  return false;
70  }
71  format_buffer_advance(buf);
72  i64 res = (i64) c - '0';
73  while (format_buffer_peak_char(buf, &c) && character_is_decimal(c)) {
74  format_buffer_advance(buf);
75  i64 digit = (i64) c - '0';
76  res = res * 10 + digit;
77  ++digits;
78  }
79  res *= factor;
80  *value = res;
81  usize left_pad, right_pad;
82  format_calculate_padding(options, digits, &left_pad, &right_pad);
83  usize i = 0;
84  for (; i < right_pad && format_buffer_match_char(buf, FORMAT_PADDING_CHAR); ++i)
85  ;
86  return left_pad_length == left_pad && i == right_pad;
87 }
88 
89 b8 format_write_signed_decimal(format_buffer *buf, format_options options, i64 value) {
90  char buffer[20];
91  const usize size = sizeof(buffer) / sizeof(buffer[0]);
92  buffer[19] = '0'; // used in case the value is just 0
93  usize digits = 0;
94  b8 negative = value < 0L;
95  if (negative) {
96  value *= -1L;
97  }
98  for (; value != 0L; value /= 10L, ++digits) {
99  i64 digit = value % 10L;
100  buffer[size - digits - 1] = (char) digit + '0';
101  }
102  if (negative) {
103  buffer[size - digits++ - 1] = '-';
104  }
105  digits = KB_MAX(digits, 1); // account for value of 0
106  usize left_pad, right_pad;
107  format_calculate_padding(options, digits, &left_pad, &right_pad);
108  return format_buffer_add_char_n(buf, FORMAT_PADDING_CHAR, left_pad)
109  && format_buffer_add_chars(buf, buffer + size - digits, digits)
110  && format_buffer_add_char_n(buf, FORMAT_PADDING_CHAR, right_pad);
111 }
112 
113 FORMAT_FUNCTION(format_read_u64) {
114  u64 *arg = VA_ARG(*args, u64 *);
115  return format_read_unsigned_decimal(buf, options, arg);
116 }
117 
118 FORMAT_FUNCTION(format_write_u64) {
119  u64 arg = VA_ARG(*args, u64);
120  return format_write_unsigned_decimal(buf, options, arg);
121 }
122 
123 FORMAT_FUNCTION(format_read_i64) {
124  i64 *arg = VA_ARG(*args, i64 *);
125  return format_read_signed_decimal(buf, options, arg);
126 }
127 
128 FORMAT_FUNCTION(format_write_i64) {
129  i64 arg = VA_ARG(*args, i64);
130  return format_write_signed_decimal(buf, options, arg);
131 }
132 
133 FORMAT_FUNCTION(format_read_u32) {
134  u32 *arg = VA_ARG(*args, u32 *);
135  u64 tmp;
136  if (!format_read_unsigned_decimal(buf, options, &tmp)) {
137  return false;
138  }
139  *arg = (u32) tmp;
140  return true;
141 }
142 
143 FORMAT_FUNCTION(format_write_u32) {
144  u32 arg = VA_ARG(*args, u32);
145  return format_write_unsigned_decimal(buf, options, arg);
146 }
147 
148 FORMAT_FUNCTION(format_read_i32) {
149  i32 *arg = VA_ARG(*args, i32 *);
150  i64 tmp;
151  if (!format_read_signed_decimal(buf, options, &tmp)) {
152  return false;
153  }
154  *arg = (i32) tmp;
155  return true;
156 }
157 
158 FORMAT_FUNCTION(format_write_i32) {
159  i32 arg = VA_ARG(*args, i32);
160  return format_write_signed_decimal(buf, options, arg);
161 }
162 
163 FORMAT_FUNCTION(format_read_u16) {
164  u16 *arg = VA_ARG(*args, u16 *);
165  u64 tmp;
166  if (!format_read_unsigned_decimal(buf, options, &tmp)) {
167  return false;
168  }
169  *arg = (u16) tmp;
170  return true;
171 }
172 
173 FORMAT_FUNCTION(format_write_u16) { return format_write_u32(buf, options, args); }
174 
175 FORMAT_FUNCTION(format_read_i16) {
176  i16 *arg = VA_ARG(*args, i16 *);
177  i64 tmp;
178  if (!format_read_signed_decimal(buf, options, &tmp)) {
179  return false;
180  }
181  *arg = (i16) tmp;
182  return true;
183 }
184 
185 FORMAT_FUNCTION(format_write_i16) { return format_write_i32(buf, options, args); }
186 
187 FORMAT_FUNCTION(format_read_u8) {
188  u8 *arg = VA_ARG(*args, u8 *);
189  u64 tmp;
190  if (!format_read_unsigned_decimal(buf, options, &tmp)) {
191  return false;
192  }
193  *arg = (u8) tmp;
194  return true;
195 }
196 
197 FORMAT_FUNCTION(format_write_u8) { return format_write_u32(buf, options, args); }
198 
199 FORMAT_FUNCTION(format_read_i8) {
200  i8 *arg = VA_ARG(*args, i8 *);
201  i64 tmp;
202  if (!format_read_signed_decimal(buf, options, &tmp)) {
203  return false;
204  }
205  *arg = (i8) tmp;
206  return true;
207 }
208 
209 FORMAT_FUNCTION(format_write_i8) { return format_write_i32(buf, options, args); }
210 
211 FORMAT_FUNCTION(format_read_usize) {
212  usize *arg = VA_ARG(*args, usize *);
213  u64 tmp;
214  if (!format_read_unsigned_decimal(buf, options, &tmp)) {
215  return false;
216  }
217  *arg = (usize) tmp;
218  return true;
219 }
220 
221 FORMAT_FUNCTION(format_write_usize) {
222  usize arg = VA_ARG(*args, usize);
223  return format_write_unsigned_decimal(buf, options, arg);
224 }
Lightweight layer between platform and other engine components to enable tracing/monitoring.
Custom library for interactions with strings using string views.
#define KB_MAX(x, y)
Ternary to get the maximum of two numbers.
Definition: defines.h:43