Ruby 4.1.0dev (2026-03-20 revision eb04ab9117336f2b3613244cfe8a528c52faf6d6)
pm_line_offset_list.c
2
6void
7pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity) {
8 list->offsets = (uint32_t *) pm_arena_alloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
9
10 // The first line always has offset 0.
11 list->offsets[0] = 0;
12 list->size = 1;
13 list->capacity = capacity;
14}
15
19void
20pm_line_offset_list_clear(pm_line_offset_list_t *list) {
21 list->size = 1;
22}
23
27void
28pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) {
29 size_t new_capacity = (list->capacity * 3) / 2;
30 uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
31
32 memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t));
33
34 list->offsets = new_offsets;
35 list->capacity = new_capacity;
36
37 assert(list->size == 0 || cursor > list->offsets[list->size - 1]);
38 list->offsets[list->size++] = cursor;
39}
40
45int32_t
46pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) {
47 size_t left = 0;
48 size_t right = list->size - 1;
49
50 while (left <= right) {
51 size_t mid = left + (right - left) / 2;
52
53 if (list->offsets[mid] == cursor) {
54 return ((int32_t) mid) + start_line;
55 }
56
57 if (list->offsets[mid] < cursor) {
58 left = mid + 1;
59 } else {
60 right = mid - 1;
61 }
62 }
63
64 return ((int32_t) left) + start_line - 1;
65}
66
73pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) {
74 size_t left = 0;
75 size_t right = list->size - 1;
76
77 while (left <= right) {
78 size_t mid = left + (right - left) / 2;
79
80 if (list->offsets[mid] == cursor) {
81 return ((pm_line_column_t) { ((int32_t) mid) + start_line, 0 });
82 }
83
84 if (list->offsets[mid] < cursor) {
85 left = mid + 1;
86 } else {
87 right = mid - 1;
88 }
89 }
90
91 return ((pm_line_column_t) {
92 .line = ((int32_t) left) + start_line - 1,
93 .column = cursor - list->offsets[left - 1]
94 });
95}
static PRISM_FORCE_INLINE void * pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment)
Allocate memory from the arena.
Definition pm_arena.h:80
A list of byte offsets of newlines in a string.
#define PRISM_ALIGNOF
Get the alignment requirement of a type.
Definition defines.h:358
A bump allocator.
Definition pm_arena.h:39
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.