diff options
Diffstat (limited to 'boot/common.c')
| -rw-r--r-- | boot/common.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/boot/common.c b/boot/common.c index 79f5d63..1c65deb 100644 --- a/boot/common.c +++ b/boot/common.c @@ -343,6 +343,7 @@ _slice_at(const struct _Slice* slice, uint index) REGION(ascii, string) // a string. +// an immutable sequence of ascii characters. struct String { ascii* data; @@ -818,6 +819,154 @@ _internal_string_format(FILE* stream, uint string_length, const ascii* format, . va_end(args); } +// a string buffer with a fixed capacity, the contents +// of which can be modified. +// essentially, a mutable string with a maximum size. +struct String_Buffer +{ + ascii* data; + uint length; + uint capacity; +}; + +// creates a new string buffer with the given capacity. +struct String_Buffer +string_buffer_new(uint capacity) +{ + check(capacity + 1 < REGION_SIZE - region_string_cursor, "out of string memory for string buffer"); + + ascii* at = region_string + region_string_cursor; + region_string_cursor += capacity + 1; + + at[0] = '\0'; + + return (struct String_Buffer){ + .data = at, + .length = 0, + .capacity = capacity, + }; +} + +// creates a new empty string buffer. +struct String_Buffer +string_buffer_empty(void) +{ + // we still technically allocate one byte of string memory for the + // empty string buffer and its null-terminator, but that shouldn't be an issue. + return string_buffer_new(0); +} + +// returns the length of the string buffer. +uint +string_buffer_length(const struct String_Buffer* buffer) +{ + return buffer->length; +} + +// returns the capacity of the string buffer. +uint +string_buffer_capacity(const struct String_Buffer* buffer) +{ + return buffer->capacity; +} + +// checks if the string buffer is empty. +bool +string_buffer_is_empty(const struct String_Buffer* buffer) +{ + return buffer->length == 0; +} + +// returns the character at a given index. +// does bounds-checking. +ascii +string_buffer_at(const struct String_Buffer* buffer, uint index) +{ + check(index < buffer->length, "index out of bounds"); + return buffer->data[index]; +} + +// clears the string buffer, setting its length to zero. +void +string_buffer_clear(struct String_Buffer* buffer) +{ + buffer->length = 0; + buffer->data[0] = '\0'; +} + +// appends a character to the string buffer. +void +string_buffer_push(struct String_Buffer* buffer, ascii c) +{ + check(buffer->length < buffer->capacity, "string buffer is full: %u/%u", buffer->length, buffer->capacity); + buffer->data[buffer->length] = c; + ++buffer->length; + buffer->data[buffer->length] = '\0'; +} + +// removes the last character from the string buffer. +// pass a non-nil pointer as `removed_char` to retrieve +// the removed character. +void +string_buffer_pop(struct String_Buffer* buffer, ascii* removed_char) +{ + check(buffer->length > 0, "cannot pop from an empty string buffer"); + + --buffer->length; + if (removed_char) *removed_char = buffer->data[buffer->length]; + buffer->data[buffer->length] = '\0'; +} + +// appends a string to the string buffer. +void +string_buffer_append(struct String_Buffer* buffer, struct String s) +{ + if (string_is_empty(s)) return; + + check(buffer->length + s.length <= buffer->capacity, + "string buffer overflow: %u + %u > %u", + buffer->length, s.length, buffer->capacity); + + for (uint i = 0; i < s.length; ++i) { + buffer->data[buffer->length + i] = s.data[i]; + } + buffer->length += s.length; + buffer->data[buffer->length] = '\0'; +} + +// appends a C-style string to the string buffer. +void +string_buffer_append_c_str(struct String_Buffer* buffer, const ascii* c_str) +{ + uint c_str_len = strlen(c_str); + if (c_str_len == 0) return; + + check(buffer->length + c_str_len <= buffer->capacity, + "string buffer overflow: %u + %u > %u", + buffer->length, c_str_len, buffer->capacity); + + for (uint i = 0; i < c_str_len; ++i) + buffer->data[buffer->length + i] = c_str[i]; + + buffer->length += c_str_len; + buffer->data[buffer->length] = '\0'; +} + +// converts the string buffer to an immutable string. +// allocates a new string in the string region. +struct String +string_buffer_to_string(const struct String_Buffer* buffer) +{ + return string_new(buffer->data, buffer->length); +} + +// prints the contents of the string buffer to stdout. +void +string_buffer_print(const struct String_Buffer* buffer) +{ + printf("%.*s", (int32)buffer->length, buffer->data); +} + // a source file given to the compiler. struct Source_File { |
