| 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 |
| 19 | extern "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 | |
| 35 | struct 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 | */ |
| 44 | typedef 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. */ |
| 79 | CORD_API CORD CORD_pos_to_cord(CORD_pos); |
| 80 | |
| 81 | /** Extract the current index from a position. */ |
| 82 | CORD_API size_t CORD_pos_to_index(CORD_pos); |
| 83 | |
| 84 | /** Fetch the character located at the given position. */ |
| 85 | CORD_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 | */ |
| 91 | CORD_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 | */ |
| 97 | CORD_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 | */ |
| 103 | CORD_API void CORD_prev(CORD_pos /* `p` */); |
| 104 | |
| 105 | /** Is the position valid, i.e. inside the cord? */ |
| 106 | CORD_API int CORD_pos_valid(CORD_pos); |
| 107 | |
| 108 | CORD_API char CORD__pos_fetch(CORD_pos); |
| 109 | CORD_API void CORD__next(CORD_pos); |
| 110 | CORD_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 | |