LexatomLoader_navigation.i (9019B)
1 /* -*- C++ -*- vim: set syntax=cpp: */ 2 #ifndef __QUEX_INCLUDE_GUARD__BUFFER__LEXATOMS__LEXATOM_LOADER_NAVIGATION_I 3 #define __QUEX_INCLUDE_GUARD__BUFFER__LEXATOMS__LEXATOM_LOADER_NAVIGATION_I 4 /* PURPOSE: LexatomLoader's seek: 5 * 6 * .--------------------------------------------------------------. 7 * | Setting the lexatom index of the next lexatom to be filled | 8 * | into the buffer. | 9 * '--------------------------------------------------------------' 10 * 11 * NOT TO CONFUSE with two other forms of seek: 12 * 13 * -- Buffer's seek sets the '_read_p' of the analyzer to a lexatom 14 * that is to be treated next. 15 * -- QUEX_NAME(ByteLoader)'s seek sets the position in the low level input 16 * stream. 17 * 18 * A LexatomLoader's seek has NO direct influence on the content or the pointers 19 * of the Buffer object that it fills. 20 * 21 * The difference between the QUEX_NAME(ByteLoader)'s seeking (stream seeking) and the 22 * LexatomLoader's seeking is that the QUEX_NAME(ByteLoader )understands the position 23 * independently of its meaning. The LexatomLoader already interprets the stream 24 * as 'lexatoms'. A QUEX_NAME(ByteLoader )sets the stream to a particular byte position. 25 * A LexatomLoader prepare the input of a lexatom. 26 * 27 * (C) Frank-Rene Schaefer */ 28 29 #include "definitions" 30 #include "bufferBuffer" 31 #include "MemoryManager" 32 #include "LexatomLoader" 33 #include "Buffer_debug" 34 35 QUEX_NAMESPACE_MAIN_OPEN 36 37 QUEX_INLINE QUEX_TYPE_STREAM_POSITION 38 QUEX_NAME(LexatomLoader_lexatom_index_tell)(QUEX_NAME(LexatomLoader)* me) 39 { 40 return me->lexatom_index_next_to_fill; 41 } 42 43 44 QUEX_INLINE bool 45 QUEX_NAME(LexatomLoader_lexatom_index_seek)(QUEX_NAME(LexatomLoader)* me, 46 const QUEX_TYPE_STREAM_POSITION CharacterIndex) 47 /* LexatomLoader's seek sets the input position for the next lexatom load in 48 * the stream. That is, it adapts: 49 * 50 * 'lexatom_index_next_to_fill = CharacterIndex' 51 * 52 * and the byte loader is brought into a position so that this will happen. 53 * 54 * RETURNS: true upon success, false else. */ 55 { 56 ptrdiff_t backup_stomach_byte_n; 57 QUEX_TYPE_STREAM_POSITION backup_byte_loader_position; 58 QUEX_TYPE_STREAM_POSITION backup_lexatom_index_next_to_fill; 59 QUEX_TYPE_STREAM_POSITION target_byte_pos; 60 61 if( me->lexatom_index_next_to_fill == CharacterIndex ) return true; 62 63 /* Converter reports '-1' => unable to determine the number of bytes in 64 * the stomach. 65 * => When backup position is to setup, start stepping from beginning. 66 * (This is currently only an issue with ICU; IConv behaves well) */ 67 backup_stomach_byte_n = me->stomach_byte_n(me); 68 backup_byte_loader_position = me->byte_loader->tell(me->byte_loader); 69 backup_lexatom_index_next_to_fill = me->lexatom_index_next_to_fill; 70 71 if( me->byte_n_per_lexatom != -1 ) { 72 /* LINEAR RELATION between lexatom index and stream position 73 * (It is not safe to assume that it can be computed) */ 74 target_byte_pos = CharacterIndex * me->byte_n_per_lexatom 75 + me->byte_loader->initial_position; 76 77 me->byte_loader->seek(me->byte_loader, target_byte_pos); 78 if( me->byte_loader->tell(me->byte_loader) != target_byte_pos ) { 79 me->byte_loader->seek(me->byte_loader, backup_byte_loader_position); 80 return false; 81 } 82 me->lexatom_index_next_to_fill = CharacterIndex; 83 me->stomach_clear(me); 84 return true; 85 } 86 87 /* STEPPING (WITHOUT COMPUTING) to the input position. */ 88 if( CharacterIndex < me->lexatom_index_next_to_fill ) { 89 /* Character index lies backward, so stepping needs to start from 90 * the initial position. */ 91 QUEX_NAME(LexatomLoader_lexatom_index_reset)(me); 92 } 93 94 /* step_forward_n_lexatoms() calls derived.load_lexatoms() 95 * which increments 'lexatom_index_next_to_fill'. */ 96 if( ! QUEX_NAME(LexatomLoader_lexatom_index_step_to)(me, (ptrdiff_t)CharacterIndex) ) { 97 QUEX_NAME(LexatomLoader_lexatom_index_reset_backup)(me, 98 backup_lexatom_index_next_to_fill, 99 backup_stomach_byte_n, 100 backup_byte_loader_position); 101 return false; 102 } 103 __quex_assert(me->lexatom_index_next_to_fill == CharacterIndex); 104 return true; 105 } 106 107 QUEX_INLINE void 108 QUEX_NAME(LexatomLoader_lexatom_index_reset)(QUEX_NAME(LexatomLoader)* me) 109 /* Set the lexatom index position to '0' and the byte loader to the initial 110 * position. The 'stomach' of derived buffer fillers is cleared, so that 111 * filling may start from the beginning. */ 112 { 113 if( me->byte_loader ) { 114 me->byte_loader->seek(me->byte_loader, me->byte_loader->initial_position); 115 if( me->byte_loader->tell(me->byte_loader) != me->byte_loader->initial_position ) { 116 QUEX_ERROR_EXIT("QUEX_NAME(ByteLoader )failed to seek to initial position.\n"); 117 } 118 } 119 me->lexatom_index_next_to_fill = 0; 120 me->stomach_clear(me); 121 } 122 123 QUEX_INLINE void 124 QUEX_NAME(LexatomLoader_lexatom_index_reset_backup)(QUEX_NAME(LexatomLoader)* me, 125 QUEX_TYPE_STREAM_POSITION Backup_lexatom_index_next_to_fill, 126 ptrdiff_t BackupStomachByteN, 127 QUEX_TYPE_STREAM_POSITION BackupByteLoaderPosition) 128 /* Reset a previous state of the LexatomLoader and its QUEX_NAME(ByteLoader). */ 129 { 130 QUEX_TYPE_STREAM_POSITION backup_byte_pos; 131 132 if( BackupStomachByteN == -1 ) { 133 /* Since it was not possible to determine the number of bytes in 134 * the converter's stomach, the backup position must be reached 135 * by starting from the begining. */ 136 QUEX_NAME(LexatomLoader_lexatom_index_reset)(me); 137 if( ! QUEX_NAME(LexatomLoader_lexatom_index_step_to)(me, (ptrdiff_t)Backup_lexatom_index_next_to_fill) ) { 138 QUEX_ERROR_EXIT("LexatomLoader failed to seek previously reached lexatom.\n"); 139 } 140 return; 141 } 142 143 backup_byte_pos = BackupByteLoaderPosition - BackupStomachByteN; 144 me->byte_loader->seek(me->byte_loader, backup_byte_pos); 145 me->stomach_clear(me); 146 me->lexatom_index_next_to_fill = Backup_lexatom_index_next_to_fill; 147 } 148 149 QUEX_INLINE bool 150 QUEX_NAME(LexatomLoader_lexatom_index_step_to)(QUEX_NAME(LexatomLoader)* me, 151 const QUEX_TYPE_STREAM_POSITION TargetCI) 152 /* From the given 'lexatom_index_next_to_fill' (i.e. the return value of 153 * 'input_lexatom_tell()') step forward to lexatom index 'TargetCI'. This 154 * function is used to reach a target input position in cases where computing 155 * is impossible. 156 * 157 * THIS FUNCTION DOES NOT BACKUP OR RE-INIT ANYTHING. 158 * => Must be done upon failure in the caller's function. 159 * 160 * RETURNS: true - success; false - else. */ 161 { 162 const QUEX_TYPE_STREAM_POSITION ChunkSize = QUEX_SETTING_BUFFER_FILLER_SEEK_TEMP_BUFFER_SIZE; 163 QUEX_TYPE_LEXATOM chunk[QUEX_SETTING_BUFFER_FILLER_SEEK_TEMP_BUFFER_SIZE]; 164 QUEX_TYPE_STREAM_POSITION remaining_n = TargetCI - me->lexatom_index_next_to_fill; 165 bool end_of_stream_f = false; 166 bool encoding_error_f = false; 167 size_t loaded_n; 168 169 __quex_assert(QUEX_SETTING_BUFFER_FILLER_SEEK_TEMP_BUFFER_SIZE >= 1); 170 171 for(; remaining_n > ChunkSize; remaining_n -= ChunkSize ) { 172 loaded_n = me->derived.load_lexatoms(me, &chunk[0], (size_t)ChunkSize, 173 &end_of_stream_f, &encoding_error_f); 174 me->lexatom_index_next_to_fill += (QUEX_TYPE_STREAM_POSITION)loaded_n; 175 if( ChunkSize > (QUEX_TYPE_STREAM_POSITION)loaded_n ) { 176 return false; 177 } 178 } 179 if( remaining_n ) { 180 loaded_n = me->derived.load_lexatoms(me, &chunk[0], (size_t)remaining_n, 181 &end_of_stream_f, &encoding_error_f); 182 me->lexatom_index_next_to_fill += (QUEX_TYPE_STREAM_POSITION)loaded_n; 183 if( remaining_n > (QUEX_TYPE_STREAM_POSITION)loaded_n ) { 184 return false; 185 } 186 } 187 188 __quex_assert(me->lexatom_index_next_to_fill == TargetCI); 189 return true; 190 } 191 192 193 QUEX_NAMESPACE_MAIN_CLOSE 194 195 #endif /* __QUEX_INCLUDE_GUARD__BUFFER__LEXATOMS__LEXATOM_LOADER_NAVIGATION_I */