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