Ruby 4.1.0dev (2026-03-02 revision 740bbddd2ff9b78f5eb3062cdbfcbd397d989f68)
pm_line_offset_list.c
2
7bool
8pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity) {
9 list->offsets = (uint32_t *) xcalloc(capacity, sizeof(uint32_t));
10 if (list->offsets == NULL) return false;
11
12 // This is 1 instead of 0 because we want to include the first line of the
13 // file as having offset 0, which is set because of calloc.
14 list->size = 1;
15 list->capacity = capacity;
16
17 return true;
18}
19
23void
24pm_line_offset_list_clear(pm_line_offset_list_t *list) {
25 list->size = 1;
26}
27
32bool
33pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor) {
34 if (list->size == list->capacity) {
35 uint32_t *original_offsets = list->offsets;
36
37 list->capacity = (list->capacity * 3) / 2;
38 list->offsets = (uint32_t *) xcalloc(list->capacity, sizeof(uint32_t));
39 if (list->offsets == NULL) return false;
40
41 memcpy(list->offsets, original_offsets, list->size * sizeof(uint32_t));
42 xfree_sized(original_offsets, list->size * sizeof(uint32_t));
43 }
44
45 assert(list->size == 0 || cursor > list->offsets[list->size - 1]);
46 list->offsets[list->size++] = cursor;
47
48 return true;
49}
50
55int32_t
56pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) {
57 size_t left = 0;
58 size_t right = list->size - 1;
59
60 while (left <= right) {
61 size_t mid = left + (right - left) / 2;
62
63 if (list->offsets[mid] == cursor) {
64 return ((int32_t) mid) + start_line;
65 }
66
67 if (list->offsets[mid] < cursor) {
68 left = mid + 1;
69 } else {
70 right = mid - 1;
71 }
72 }
73
74 return ((int32_t) left) + start_line - 1;
75}
76
83pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) {
84 size_t left = 0;
85 size_t right = list->size - 1;
86
87 while (left <= right) {
88 size_t mid = left + (right - left) / 2;
89
90 if (list->offsets[mid] == cursor) {
91 return ((pm_line_column_t) { ((int32_t) mid) + start_line, 0 });
92 }
93
94 if (list->offsets[mid] < cursor) {
95 left = mid + 1;
96 } else {
97 right = mid - 1;
98 }
99 }
100
101 return ((pm_line_column_t) {
102 .line = ((int32_t) left) + start_line - 1,
103 .column = cursor - list->offsets[left - 1]
104 });
105}
106
110void
111pm_line_offset_list_free(pm_line_offset_list_t *list) {
112 xfree_sized(list->offsets, list->capacity * sizeof(uint32_t));
113}
#define xcalloc
Old name of ruby_xcalloc.
Definition xmalloc.h:55
A list of byte offsets of newlines in a string.
A line and column in a string.
A list of offsets of the start of lines in a string.
uint32_t * offsets
The list of offsets.
size_t size
The number of offsets in the list.
size_t capacity
The capacity of the list that has been allocated.