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. */ 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 /* The representation of CORD_position. This is private to the */ 23 /* implementation, but the size is known to clients. Also */ 24 /* the implementation of some exported macros relies on it. */ 25 /* Don't use anything defined here and not in cord.h. */ 26 27 # define MAX_DEPTH 48 28 /* The maximum depth of a balanced cord + 1. */ 29 /* We don't let cords get deeper than MAX_DEPTH. */ 30 31 struct CORD_pe { 32 CORD pe_cord; 33 size_t pe_start_pos; 34 }; 35 36 /* A structure describing an entry on the path from the root */ 37 /* to current position. */ 38 typedef struct CORD_Pos { 39 size_t cur_pos; 40 int path_len; 41 # define CORD_POS_INVALID (0x55555555) 42 /* path_len == INVALID <==> position invalid */ 43 const char *cur_leaf; /* Current leaf, if it is a string. */ 44 /* If the current leaf is a function, */ 45 /* then this may point to function_buf */ 46 /* containing the next few characters. */ 47 /* Always points to a valid string */ 48 /* containing the current character */ 49 /* unless cur_end is 0. */ 50 size_t cur_start; /* Start position of cur_leaf */ 51 size_t cur_end; /* Ending position of cur_leaf */ 52 /* 0 if cur_leaf is invalid. */ 53 struct CORD_pe path[MAX_DEPTH + 1]; 54 /* path[path_len] is the leaf corresponding to cur_pos */ 55 /* path[0].pe_cord is the cord we point to. */ 56 # define FUNCTION_BUF_SZ 8 57 char function_buf[FUNCTION_BUF_SZ]; /* Space for next few chars */ 58 /* from function node. */ 59 } CORD_pos[1]; 60 61 /* Extract the cord from a position: */ 62 CORD_API CORD CORD_pos_to_cord(CORD_pos p); 63 64 /* Extract the current index from a position: */ 65 CORD_API size_t CORD_pos_to_index(CORD_pos p); 66 67 /* Fetch the character located at the given position: */ 68 CORD_API char CORD_pos_fetch(CORD_pos p); 69 70 /* Initialize the position to refer to the give cord and index. */ 71 /* Note that this is the most expensive function on positions: */ 72 CORD_API void CORD_set_pos(CORD_pos p, CORD x, size_t i); 73 74 /* Advance the position to the next character. */ 75 /* P must be initialized and valid. */ 76 /* Invalidates p if past end: */ 77 CORD_API void CORD_next(CORD_pos p); 78 79 /* Move the position to the preceding character. */ 80 /* P must be initialized and valid. */ 81 /* Invalidates p if past beginning: */ 82 CORD_API void CORD_prev(CORD_pos p); 83 84 /* Is the position valid, i.e. inside the cord? */ 85 CORD_API int CORD_pos_valid(CORD_pos p); 86 87 CORD_API char CORD__pos_fetch(CORD_pos); 88 CORD_API void CORD__next(CORD_pos); 89 CORD_API void CORD__prev(CORD_pos); 90 91 #define CORD_pos_fetch(p) \ 92 (((p)[0].cur_end != 0)? \ 93 (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \ 94 : CORD__pos_fetch(p)) 95 96 #define CORD_next(p) \ 97 (((p)[0].cur_pos + 1 < (p)[0].cur_end)? \ 98 (p)[0].cur_pos++ \ 99 : (CORD__next(p), 0)) 100 101 #define CORD_prev(p) \ 102 (((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start)? \ 103 (p)[0].cur_pos-- \ 104 : (CORD__prev(p), 0)) 105 106 #define CORD_pos_to_index(p) ((p)[0].cur_pos) 107 108 #define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord) 109 110 #define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID) 111 112 /* Some grubby stuff for performance-critical friends: */ 113 #define CORD_pos_chars_left(p) ((long)((p)[0].cur_end) - (long)((p)[0].cur_pos)) 114 /* Number of characters in cache. <= 0 ==> none */ 115 116 #define CORD_pos_advance(p,n) ((p)[0].cur_pos += (n) - 1, CORD_next(p)) 117 /* Advance position by n characters */ 118 /* 0 < n < CORD_pos_chars_left(p) */ 119 120 #define CORD_pos_cur_char_addr(p) \ 121 (p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start) 122 /* address of current character in cache. */ 123 124 #ifdef __cplusplus 125 } /* extern "C" */ 126 #endif 127 128 #endif 129