v2 / thirdparty / libgc / include / gc / cord_pos.h
151 lines · 117 sloc · 4.57 KB · a4b7f7369d5359a002beced36c1e6644403220e7
Raw
1/*
2 * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
3 *
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6 *
7 * Permission is hereby granted to use or copy this program
8 * for any purpose, provided the above notices are retained on all copies.
9 * Permission to modify the code and to distribute modified code is granted,
10 * provided the above notices are retained, and a notice that the code was
11 * modified is included with the above copyright notice.
12 */
13
14/* This should never be included directly; included only from `cord.h` file. */
15#if !defined(CORD_POSITION_H) && defined(CORD_H)
16# define CORD_POSITION_H
17
18# ifdef __cplusplus
19extern "C" {
20# endif
21
22/*
23 * The representation of `CORD_position`. This is private to the
24 * implementation, but the size is known to clients. Also the implementation
25 * of some exported macros relies on it. Do not use anything defined here
26 * and not in `cord.h` file.
27 */
28
29/**
30 * The maximum depth of a balanced cord plus one. We do not let cords get
31 * deeper than this maximum.
32 */
33# define CORD_MAX_DEPTH 48
34
35struct CORD_pe {
36 CORD pe_cord;
37 size_t pe_start_pos;
38};
39
40/**
41 * A structure describing an entry on the path from the root to current
42 * position.
43 */
44typedef struct CORD_Pos {
45 size_t cur_pos;
46
47 int path_len;
48
49 /* `path_len` is `CORD_POS_INVALID` if and only if position is invalid. */
50# define CORD_POS_INVALID 0x55555555
51
52 /*
53 * Current leaf, if it is a string. If the current leaf is a function,
54 * then this may point to `function_buf` containing the next few characters.
55 * Always points to a valid string containing the current character
56 * unless `cur_end` is zero.
57 */
58 const char *cur_leaf;
59
60 /* Start position of `cur_leaf`. */
61 size_t cur_start;
62
63 /* Ending position of `cur_leaf`; zero if `cur_leaf` is invalid. */
64 size_t cur_end;
65
66 /*
67 * `path[path_len]` is the leaf corresponding to `cur_pos`;
68 * `path[0].pe_cord` is the cord we point to.
69 */
70 struct CORD_pe path[CORD_MAX_DEPTH + 1];
71
72# define CORD_FUNCTION_BUF_SZ 8
73
74 /* Space for next few chars from function node. */
75 char function_buf[CORD_FUNCTION_BUF_SZ];
76} CORD_pos[1];
77
78/** Extract the cord from a position. */
79CORD_API CORD CORD_pos_to_cord(CORD_pos);
80
81/** Extract the current index from a position. */
82CORD_API size_t CORD_pos_to_index(CORD_pos);
83
84/** Fetch the character located at the given position. */
85CORD_API char CORD_pos_fetch(CORD_pos);
86
87/**
88 * Initialize the position to refer to the given cord and `index`.
89 * Note that this is the most expensive function on positions.
90 */
91CORD_API void CORD_set_pos(CORD_pos, CORD, size_t /* `index` */);
92
93/**
94 * Advance the position to the next character. `p` must be initialized
95 * and valid. Invalidates `p` if past end.
96 */
97CORD_API void CORD_next(CORD_pos /* `p` */);
98
99/**
100 * Move the position to the preceding character. `p` must be initialized
101 * and valid. Invalidates `p` if past beginning.
102 */
103CORD_API void CORD_prev(CORD_pos /* `p` */);
104
105/** Is the position valid, i.e. inside the cord? */
106CORD_API int CORD_pos_valid(CORD_pos);
107
108CORD_API char CORD__pos_fetch(CORD_pos);
109CORD_API void CORD__next(CORD_pos);
110CORD_API void CORD__prev(CORD_pos);
111
112# define CORD_pos_fetch(p) \
113 ((p)[0].cur_end != 0 ? (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \
114 : CORD__pos_fetch(p))
115
116# define CORD_next(p) \
117 ((p)[0].cur_pos + 1 < (p)[0].cur_end ? (p)[0].cur_pos++ \
118 : (CORD__next(p), 0U))
119
120# define CORD_prev(p) \
121 ((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start \
122 ? (p)[0].cur_pos-- \
123 : (CORD__prev(p), 0U))
124
125# define CORD_pos_to_index(p) ((p)[0].cur_pos)
126
127# define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord)
128
129# define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)
130
131/* Some grubby stuff for performance-critical friends. */
132
133/** Number of characters in cache. A non-positive value means none. */
134# define CORD_pos_chars_left(p) ((long)(p)[0].cur_end - (long)(p)[0].cur_pos)
135
136/**
137 * Advance position by `n` characters; `n` should be positive and less
138 * than `CORD_pos_chars_left(p)`.
139 */
140# define CORD_pos_advance(p, n) \
141 ((p)[0].cur_pos += (n) - (size_t)1, CORD_next(p))
142
143/** Address of the current character in cache. */
144# define CORD_pos_cur_char_addr(p) \
145 ((p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start))
146
147# ifdef __cplusplus
148} /* extern "C" */
149# endif
150
151#endif
152