Ruby: prism/util/pm_newline_list.c Source File

Ruby 3.3.4p94 (2024-07-09 revision be1089c8ec5ba40e09b1553e36b3174bf4014d9d)

pm_newline_list.c
1#include "prism/util/pm_newline_list.h"
2
7bool
8pm_newline_list_init(pm_newline_list_t *list, const uint8_t *start, size_t capacity) {
9 list->offsets = (size_t *) calloc(capacity, sizeof(size_t));
10 if (list->offsets == NULL) return false;
11
12 list->start = start;
13
14 // This is 1 instead of 0 because we want to include the first line of the
15 // file as having offset 0, which is set because of calloc.
16 list->size = 1;
17 list->capacity = capacity;
18
19 return true;
20}
21
26bool
27pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor) {
28 if (list->size == list->capacity) {
29 size_t *original_offsets = list->offsets;
30
31 list->capacity = (list->capacity * 3) / 2;
32 list->offsets = (size_t *) calloc(list->capacity, sizeof(size_t));
33 memcpy(list->offsets, original_offsets, list->size * sizeof(size_t));
34 free(original_offsets);
35 if (list->offsets == NULL) return false;
36 }
37
38 assert(*cursor == '\n');
39 assert(cursor >= list->start);
40 size_t newline_offset = (size_t) (cursor - list->start + 1);
41
42 assert(list->size == 0 || newline_offset > list->offsets[list->size - 1]);
43 list->offsets[list->size++] = newline_offset;
44
45 return true;
46}
47
52bool
53pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor) {
54 if (*cursor != '\n') {
55 return true;
56 }
57 return pm_newline_list_append(list, cursor);
58}
59
65 pm_line_column_t
66pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor) {
67 assert(cursor >= list->start);
68 size_t offset = (size_t) (cursor - list->start);
69
70 size_t left = 0;
71 size_t right = list->size - 1;
72
73 while (left <= right) {
74 size_t mid = left + (right - left) / 2;
75
76 if (list->offsets[mid] == offset) {
77 return ((pm_line_column_t) { mid, 0 });
78 }
79
80 if (list->offsets[mid] < offset) {
81 left = mid + 1;
82 } else {
83 right = mid - 1;
84 }
85 }
86
87 return ((pm_line_column_t) { left - 1, offset - list->offsets[left - 1] });
88}
89
93void
94pm_newline_list_free(pm_newline_list_t *list) {
95 free(list->offsets);
96}
pm_newline_list.h
A list of byte offsets of newlines in a string.
pm_line_column_t
A line and column in a string.
Definition pm_newline_list.h:45
pm_newline_list_t
A list of offsets of newlines in a string.
Definition pm_newline_list.h:28
pm_newline_list_t::start
const uint8_t * start
A pointer to the start of the source string.
Definition pm_newline_list.h:30
pm_newline_list_t::capacity
size_t capacity
The capacity of the list that has been allocated.
Definition pm_newline_list.h:36
pm_newline_list_t::offsets
size_t * offsets
The list of offsets.
Definition pm_newline_list.h:39
pm_newline_list_t::size
size_t size
The number of offsets in the list.
Definition pm_newline_list.h:33