1 #include "prism/util/pm_newline_list.h"
4 * Initialize a new newline list with the given capacity. Returns true if the
5 * allocation of the offsets succeeds, otherwise returns false.
8 pm_newline_list_init(pm_newline_list_t
*list
, const uint8_t *start
, size_t capacity
) {
9 list
->offsets
= (size_t *) xcalloc(capacity
, sizeof(size_t));
10 if (list
->offsets
== NULL
) return false;
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.
17 list
->capacity
= capacity
;
23 * Clear out the newlines that have been appended to the list.
26 pm_newline_list_clear(pm_newline_list_t
*list
) {
31 * Append a new offset to the newline list. Returns true if the reallocation of
32 * the offsets succeeds (if one was necessary), otherwise returns false.
35 pm_newline_list_append(pm_newline_list_t
*list
, const uint8_t *cursor
) {
36 if (list
->size
== list
->capacity
) {
37 size_t *original_offsets
= list
->offsets
;
39 list
->capacity
= (list
->capacity
* 3) / 2;
40 list
->offsets
= (size_t *) xcalloc(list
->capacity
, sizeof(size_t));
41 if (list
->offsets
== NULL
) return false;
43 memcpy(list
->offsets
, original_offsets
, list
->size
* sizeof(size_t));
44 xfree(original_offsets
);
47 assert(*cursor
== '\n');
48 assert(cursor
>= list
->start
);
49 size_t newline_offset
= (size_t) (cursor
- list
->start
+ 1);
51 assert(list
->size
== 0 || newline_offset
> list
->offsets
[list
->size
- 1]);
52 list
->offsets
[list
->size
++] = newline_offset
;
58 * Returns the line of the given offset. If the offset is not in the list, the
59 * line of the closest offset less than the given offset is returned.
62 pm_newline_list_line(const pm_newline_list_t
*list
, const uint8_t *cursor
, int32_t start_line
) {
63 assert(cursor
>= list
->start
);
64 size_t offset
= (size_t) (cursor
- list
->start
);
67 size_t right
= list
->size
- 1;
69 while (left
<= right
) {
70 size_t mid
= left
+ (right
- left
) / 2;
72 if (list
->offsets
[mid
] == offset
) {
73 return ((int32_t) mid
) + start_line
;
76 if (list
->offsets
[mid
] < offset
) {
83 return ((int32_t) left
) + start_line
- 1;
87 * Returns the line and column of the given offset. If the offset is not in the
88 * list, the line and column of the closest offset less than the given offset
92 pm_newline_list_line_column(const pm_newline_list_t
*list
, const uint8_t *cursor
, int32_t start_line
) {
93 assert(cursor
>= list
->start
);
94 size_t offset
= (size_t) (cursor
- list
->start
);
97 size_t right
= list
->size
- 1;
99 while (left
<= right
) {
100 size_t mid
= left
+ (right
- left
) / 2;
102 if (list
->offsets
[mid
] == offset
) {
103 return ((pm_line_column_t
) { ((int32_t) mid
) + start_line
, 0 });
106 if (list
->offsets
[mid
] < offset
) {
113 return ((pm_line_column_t
) {
114 .line
= ((int32_t) left
) + start_line
- 1,
115 .column
= (uint32_t) (offset
- list
->offsets
[left
- 1])
120 * Free the internal memory allocated for the newline list.
123 pm_newline_list_free(pm_newline_list_t
*list
) {
124 xfree(list
->offsets
);