Buffer_navigation.i (7961B)
1 /* vim: set ft=c: 2 * 3 * PURPOSE: Buffer's seek: 4 * 5 * .---------------------------------------------------------------. 6 * | Setting the '_read_p' to a specific position in the stream. | 7 * '---------------------------------------------------------------' 8 * 9 * This is the type of 'seek' used in the user interface's seek functions. 10 * 11 * NOT TO CONFUSE with two other forms of seek: 12 * 13 * -- LexatomLoader's seek sets the input position of the next 14 * lexatom to be loaded into the buffer. 15 * -- QUEX_NAME(ByteLoader)'s seek sets the position in the low level input 16 * stream. 17 * 18 * A 'seek' always implies that the following happens: 19 * 20 * _lexeme_start_p = _read_p 21 * 22 * The two stored lexatoms will be assigned after seeking as 23 * 24 * _lexatom_at_lexeme_start = _read_p[0] 25 * _lexatom_before_lexeme_start = _read_p[-1] 26 * 27 * If the read pointer stands at the beginning of the file, then 28 * 29 * _lexatom_before_lexeme_start = newline 30 * 31 * It is crucial to understand the difference between 'stream seeking' and 32 * 'buffer seeking'. Stream seeking determines the next position in the input 33 * stream from where content is loaded into the buffer. Buffer seeking sets 34 * the input pointer '_read_p' to a particular position. The position-1 where 35 * it points contains the next lexatom to be read during analysis. 36 * 37 * (C) Frank-Rene Schaefer */ 38 #ifndef __QUEX_INCLUDE_GUARD__BUFFER__BUFFER_NAVIGATION_I 39 #define __QUEX_INCLUDE_GUARD__BUFFER__BUFFER_NAVIGATION_I 40 41 QUEX_NAMESPACE_MAIN_OPEN 42 43 QUEX_INLINE bool 44 QUEX_NAME(Buffer_finish_seek_based_on_read_p)(QUEX_NAME(Buffer)* me); 45 46 QUEX_INLINE QUEX_TYPE_STREAM_POSITION 47 QUEX_NAME(Buffer_input_lexatom_index_begin)(QUEX_NAME(Buffer)* me) 48 /* Determine lexatom index of first lexatom in the buffer. */ 49 { 50 __quex_assert(me->input.lexatom_index_begin >= 0); 51 return me->input.lexatom_index_begin; 52 } 53 54 QUEX_INLINE bool 55 QUEX_NAME(Buffer_seek_forward)(QUEX_NAME(Buffer)* me, const ptrdiff_t CharacterN) 56 /* Move '_read_p' forwards by 'CharacterN'. This may involve reload in 57 * forward direction. 58 * 59 * Seeking error => Buffer is completely left as is. In particular no change 60 * to '_read_p' or '_lexeme_start_p'. 61 * 62 * RETURNS: True -- if positioning was successful, 63 * False -- else. */ 64 { 65 QUEX_TYPE_LEXATOM* BeginP = &me->_memory._front[1]; 66 QUEX_TYPE_STREAM_POSITION CharacterIndexAtReadP = me->input.lexatom_index_begin 67 + (me->_read_p - BeginP); 68 QUEX_TYPE_STREAM_POSITION target = CharacterIndexAtReadP + CharacterN; 69 QUEX_TYPE_STREAM_POSITION new_lexatom_index_begin; 70 71 if( ! CharacterN ) { 72 return true; 73 } 74 else if( target < QUEX_NAME(Buffer_input_lexatom_index_end)(me) ) { 75 me->_read_p += CharacterN; 76 /* => &me->_read_p[-1] inside buffer. */ 77 } 78 else if( me->input.lexatom_index_end_of_stream != -1 79 && target > me->input.lexatom_index_end_of_stream ) { 80 return false; 81 } 82 else { 83 /* Character index at read_p = lexatom index at begin + offset */ 84 new_lexatom_index_begin = QUEX_MAX(0, target - QUEX_SETTING_BUFFER_MIN_FALLBACK_N); 85 if( ! QUEX_NAME(Buffer_move_and_load_forward)(me, new_lexatom_index_begin, target) ) { 86 QUEX_BUFFER_ASSERT_CONSISTENCY(me); 87 return false; 88 } 89 90 me->_read_p = &BeginP[target - new_lexatom_index_begin]; 91 } 92 me->_lexeme_start_p = me->_read_p; 93 94 return QUEX_NAME(Buffer_finish_seek_based_on_read_p)(me); 95 } 96 97 QUEX_INLINE bool 98 QUEX_NAME(Buffer_seek_backward)(QUEX_NAME(Buffer)* me, 99 const ptrdiff_t CharacterN) 100 /* Move '_read_p' backwards by 'CharacterN'. This may involve reload in 101 * backward direction. 102 * 103 * Seeking error => Buffer is completely left as is. In particular no change 104 * to '_read_p' or '_lexeme_start_p'. 105 * 106 * RETURNS: True -- if positioning was successful, 107 * False -- else. */ 108 { 109 QUEX_TYPE_LEXATOM* BeginP = &me->_memory._front[1]; 110 QUEX_TYPE_STREAM_POSITION CharacterIndexAtReadP = me->input.lexatom_index_begin 111 + (me->_read_p - BeginP); 112 QUEX_TYPE_STREAM_POSITION target = CharacterIndexAtReadP - CharacterN; 113 const ptrdiff_t ContentSize = (ptrdiff_t)QUEX_NAME(Buffer_content_size)(me); 114 QUEX_TYPE_STREAM_POSITION new_lexatom_index_begin; 115 ptrdiff_t offset; 116 117 if( ! CharacterN ) { 118 return true; 119 } 120 else if( target > me->input.lexatom_index_begin ) { 121 /* => &me->_read_p[-1] inside buffer. */ 122 me->_read_p -= CharacterN; 123 } 124 else { 125 /* offset = desired distance from begin to 'read_p'. */ 126 offset = (ptrdiff_t)QUEX_MIN((QUEX_TYPE_STREAM_POSITION)(ContentSize >> 1), target); 127 new_lexatom_index_begin = target - offset; 128 129 if( ! QUEX_NAME(Buffer_move_and_load_backward)(me, new_lexatom_index_begin) ) { 130 /* QUEX_ERROR_EXIT() initiated inside above function. */ 131 return false; 132 } 133 me->_read_p = &BeginP[offset]; 134 } 135 136 return QUEX_NAME(Buffer_finish_seek_based_on_read_p)(me); 137 } 138 139 QUEX_INLINE QUEX_TYPE_STREAM_POSITION 140 QUEX_NAME(Buffer_tell)(QUEX_NAME(Buffer)* me) 141 /* RETURNS: lexatom index which corresponds to the position of the input 142 * pointer. */ 143 { 144 const QUEX_TYPE_STREAM_POSITION DeltaToBufferBegin = me->_read_p - &me->_memory._front[1]; 145 QUEX_BUFFER_ASSERT_CONSISTENCY(me); 146 147 return DeltaToBufferBegin + QUEX_NAME(Buffer_input_lexatom_index_begin)(me); 148 } 149 150 QUEX_INLINE void 151 QUEX_NAME(Buffer_seek)(QUEX_NAME(Buffer)* me, const QUEX_TYPE_STREAM_POSITION CharacterIndex) 152 /* Set the _read_p according to a lexatom index of the input. It is the 153 * inverse of 'tell()'. */ 154 { 155 const QUEX_TYPE_STREAM_POSITION CurrentCharacterIndex = QUEX_NAME(Buffer_tell)(me); 156 157 if( CharacterIndex > CurrentCharacterIndex ) { 158 QUEX_NAME(Buffer_seek_forward)(me, (ptrdiff_t)(CharacterIndex - CurrentCharacterIndex)); 159 } 160 else if( CharacterIndex < CurrentCharacterIndex ) { 161 QUEX_NAME(Buffer_seek_backward)(me,(ptrdiff_t)(CurrentCharacterIndex - CharacterIndex)); 162 } 163 } 164 165 QUEX_INLINE bool 166 QUEX_NAME(Buffer_finish_seek_based_on_read_p)(QUEX_NAME(Buffer)* me) 167 { 168 QUEX_TYPE_LEXATOM* BeginP = &me->_memory._front[1]; 169 bool verdict_f = true; 170 171 if( me->_read_p >= me->input.end_p ) { 172 me->_read_p = me->input.end_p; 173 verdict_f = false; 174 } 175 else if( me->_read_p < BeginP ) { 176 me->_read_p = BeginP; 177 verdict_f = false; 178 } 179 180 me->_lexeme_start_p = me->_read_p; 181 me->_lexatom_at_lexeme_start = me->_read_p[0]; 182 # ifdef __QUEX_OPTION_SUPPORT_BEGIN_OF_LINE_PRE_CONDITION 183 /* Seek was towards 'target - 1' 184 * => Now, there must be at least one lexatom before '_read_p'. 185 * Or if not, then the target was on the lower limit 0 and the '_read_p' 186 * stands on the buffer's content front. */ 187 me->_lexatom_before_lexeme_start = me->_read_p > BeginP ? me->_read_p[-1] 188 : QUEX_SETTING_CHARACTER_NEWLINE_IN_ENGINE_CODEC; 189 # endif 190 QUEX_BUFFER_ASSERT_CONSISTENCY(me); 191 return verdict_f; 192 } 193 194 QUEX_NAMESPACE_MAIN_CLOSE 195 #endif /* __QUEX_INCLUDE_GUARD__BUFFER__BUFFER_NAVIGATION_I */