Ruby 4.1.0dev (2026-03-28 revision 6035121c933c965cebf93f624066c95dabbc6d1d)
line_offset_list.c
2#include "prism/internal/line_offset_list.h"
3#include "prism/internal/arena.h"
4
5#include <assert.h>
6#include <string.h>
7
11void
12pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity) {
13 list->offsets = (uint32_t *) pm_arena_alloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
14
15 // The first line always has offset 0.
16 list->offsets[0] = 0;
17 list->size = 1;
18 list->capacity = capacity;
19}
20
24void
25pm_line_offset_list_clear(pm_line_offset_list_t *list) {
26 list->size = 1;
27}
28
32void
33pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) {
34 size_t new_capacity = (list->capacity * 3) / 2;
35 uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t));
36
37 memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t));
38
39 list->offsets = new_offsets;
40 list->capacity = new_capacity;
41
42 assert(list->size == 0 || cursor > list->offsets[list->size - 1]);
43 list->offsets[list->size++] = cursor;
44}
45
50int32_t
51pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) {
52 size_t left = 0;
53 size_t right = list->size - 1;
54
55 while (left <= right) {
56 size_t mid = left + (right - left) / 2;
57
58 if (list->offsets[mid] == cursor) {
59 return ((int32_t) mid) + start_line;
60 }
61
62 if (list->offsets[mid] < cursor) {
63 left = mid + 1;
64 } else {
65 right = mid - 1;
66 }
67 }
68
69 return ((int32_t) left) + start_line - 1;
70}
71
78pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) {
79 size_t left = 0;
80 size_t right = list->size - 1;
81
82 while (left <= right) {
83 size_t mid = left + (right - left) / 2;
84
85 if (list->offsets[mid] == cursor) {
86 return ((pm_line_column_t) { ((int32_t) mid) + start_line, 0 });
87 }
88
89 if (list->offsets[mid] < cursor) {
90 left = mid + 1;
91 } else {
92 right = mid - 1;
93 }
94 }
95
96 return ((pm_line_column_t) {
97 .line = ((int32_t) left) + start_line - 1,
98 .column = cursor - list->offsets[left - 1]
99 });
100}
#define PRISM_ALIGNOF
Get the alignment requirement of a type.
Definition align.h:15
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.