kiba-engine
pointer.c
1 #include <kiba/format/defaults/pointer.h>
2 
3 #include <kiba/core/memory.h>
4 #include <kiba/core/string.h>
5 
6 b8 format_read_address(format_buffer *buf, format_options options, uptr *value) {
7  usize left_pad_length = 0;
8  while (format_buffer_match_char(buf, FORMAT_PADDING_CHAR)) {
9  ++left_pad_length;
10  }
11  if (!(format_buffer_match_char(buf, '0') && format_buffer_match_char(buf, 'x'))) {
12  return false;
13  }
14  char c;
15  if (!(format_buffer_peak_char(buf, &c) && character_is_hexadecimal(c))) {
16  return false;
17  }
18  format_buffer_advance(buf);
19  usize digits = 3; // account for leading 0x
20  uptr res = (uptr) c - '0';
21  if (res > 9) {
22  res -= 'a' - '0' - 10;
23  }
24  while (format_buffer_peak_char(buf, &c) && character_is_hexadecimal(c)) {
25  format_buffer_advance(buf);
26  uptr digit = (uptr) c - '0';
27  if (digit > 9) {
28  digit -= 'a' - '0' - 10;
29  }
30  res = res * 16 + digit;
31  ++digits;
32  }
33  *value = res;
34  usize left_pad, right_pad;
35  format_calculate_padding(options, digits, &left_pad, &right_pad);
36  usize i = 0;
37  for (; i < right_pad && format_buffer_match_char(buf, FORMAT_PADDING_CHAR); ++i)
38  ;
39  return left_pad_length == left_pad && i == right_pad;
40 }
41 
42 b8 format_write_address(format_buffer *buf, format_options options, uptr value) {
43  const char *symbols = "0123456789abcdef";
44  char buffer[18];
45  const usize size = sizeof(buffer) / sizeof(buffer[0]);
46  memory_set(buffer, (u8) '0', size * sizeof(char)); // kind of relies on 1 char == 1 byte
47  usize digits = 0;
48  for (; value != 0; value /= 16, ++digits) {
49  uptr digit = value % 16;
50  buffer[size - digits - 1] = symbols[digit];
51  }
52  usize min_digits = 1;
53  if (options.precision > 0 && options.precision <= 16) {
54  min_digits = options.precision;
55  }
56  digits = KB_MAX(digits, min_digits);
57  buffer[size - digits++ - 1] = 'x';
58  usize left_pad, right_pad;
59  format_calculate_padding(options, ++digits, &left_pad, &right_pad); // account for leading 0
60  return format_buffer_add_char_n(buf, FORMAT_PADDING_CHAR, left_pad)
61  && format_buffer_add_chars(buf, buffer + size - digits, digits)
62  && format_buffer_add_char_n(buf, FORMAT_PADDING_CHAR, right_pad);
63 }
64 
65 FORMAT_FUNCTION(format_read_uptr) {
66  uptr *arg = VA_ARG(*args, uptr *);
67  return format_read_address(buf, options, arg);
68 }
69 
70 FORMAT_FUNCTION(format_write_uptr) {
71  uptr arg = VA_ARG(*args, uptr);
72  return format_write_address(buf, options, arg);
73 }
74 
75 FORMAT_FUNCTION(format_read_pointer) {
76  void **arg = VA_ARG(*args, void **);
77  return format_read_address(buf, options, (uptr *) arg);
78 }
79 
80 FORMAT_FUNCTION(format_write_pointer) {
81  void *arg = VA_ARG(*args, void *);
82  return format_write_address(buf, options, (uptr) arg);
83 }
void * memory_set(void *mem, u8 byte, usize size)
Set content of memory block.
Definition: memory.c:81
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