Accumulator.i (7066B)
1 /* -*- C++ -*- vim:set syntax=cpp: 2 * 3 * (C) 2005-2009 Frank-Rene Schaefer 4 * 5 * __QUEX_INCLUDE_GUARD__ANALYZER__ACCUMULATOR may be undefined in case 6 * that multiple lexical analyzers are used. Then, the name of the 7 * QUEX_NAME(Accumulator) must be different. */ 8 #ifndef __QUEX_INCLUDE_GUARD__ANALYZER__ACCUMULATOR_I 9 #define __QUEX_INCLUDE_GUARD__ANALYZER__ACCUMULATOR_I 10 11 #include "definitions" 12 #include "Accumulator" 13 #include "MemoryManager" 14 #include "TokenPolicy" 15 16 QUEX_NAMESPACE_MAIN_OPEN 17 18 QUEX_INLINE void 19 QUEX_NAME(Accumulator_construct)(QUEX_NAME(Accumulator)* me, 20 QUEX_TYPE_ANALYZER* lexer) 21 { 22 me->the_lexer = lexer; 23 QUEX_NAME(Accumulator_init_memory)(me); 24 __QUEX_IF_COUNT_LINES(me->_begin_line = 0); 25 __QUEX_IF_COUNT_COLUMNS(me->_begin_column = 0); 26 } 27 28 29 QUEX_INLINE void 30 QUEX_NAME(Accumulator_destruct)(QUEX_NAME(Accumulator)* me) 31 { 32 if( me->text.begin ) { 33 QUEXED(MemoryManager_free)((void*)me->text.begin, 34 E_MemoryObjectType_TEXT); 35 } 36 me->the_lexer = 0x0; 37 me->text.begin = 0x0; 38 me->text.end = 0x0; 39 me->text.memory_end = 0x0; 40 } 41 42 QUEX_INLINE void 43 QUEX_NAME(Accumulator_init_memory)(QUEX_NAME(Accumulator)* me) 44 { 45 if( QUEX_SETTING_ACCUMULATOR_INITIAL_SIZE == 0 ) { 46 me->text.begin = 0x0; 47 } 48 else { 49 me->text.begin = \ 50 (QUEX_TYPE_LEXATOM*) 51 QUEXED(MemoryManager_allocate)( 52 QUEX_SETTING_ACCUMULATOR_INITIAL_SIZE * sizeof(QUEX_TYPE_LEXATOM), 53 E_MemoryObjectType_TEXT); 54 if( ! me->text.begin ) { 55 QUEX_ERROR_EXIT("Quex engine: out of memory--cannot allocate Accumulator."); 56 } 57 } 58 me->text.end = me->text.begin; 59 me->text.memory_end = me->text.begin + QUEX_SETTING_ACCUMULATOR_INITIAL_SIZE; 60 } 61 62 QUEX_INLINE bool 63 QUEX_NAME(Accumulator_extend)(QUEX_NAME(Accumulator)* me, size_t MinAddSize) 64 { 65 const size_t OldContentSize = (size_t)(me->text.end - me->text.begin); 66 const size_t Size = (size_t)(me->text.memory_end - me->text.begin); 67 const size_t AddSize = (size_t)((float)Size * (float)QUEX_SETTING_ACCUMULATOR_GRANULARITY_FACTOR); 68 const size_t NewSize = Size + (AddSize < MinAddSize ? MinAddSize : AddSize); 69 70 QUEX_TYPE_LEXATOM* chunk = \ 71 (QUEX_TYPE_LEXATOM*) 72 QUEXED(MemoryManager_allocate)(NewSize*sizeof(QUEX_TYPE_LEXATOM), 73 E_MemoryObjectType_TEXT); 74 75 if( chunk == 0x0 ) return false; 76 77 __quex_assert(me->text.end >= me->text.begin); 78 __quex_assert(me->text.memory_end >= me->text.begin); 79 80 __QUEX_STD_memcpy(chunk, me->text.begin, sizeof(QUEX_TYPE_LEXATOM) * Size); 81 82 QUEXED(MemoryManager_free)((void*)me->text.begin, E_MemoryObjectType_TEXT); 83 84 me->text.begin = chunk; 85 me->text.end = chunk + OldContentSize; 86 me->text.memory_end = chunk + NewSize; 87 return true; 88 } 89 90 QUEX_INLINE void 91 QUEX_NAME(Accumulator_clear)(QUEX_NAME(Accumulator)* me) 92 { 93 /* If no text is to be flushed, return undone */ 94 if( me->text.begin == me->text.end ) return; 95 me->text.end = me->text.begin; 96 } 97 98 QUEX_INLINE void 99 QUEX_NAME(Accumulator_add)(QUEX_NAME(Accumulator)* me, 100 const QUEX_TYPE_LEXATOM* Begin, const QUEX_TYPE_LEXATOM* End) 101 { 102 const size_t L = (size_t)(End - Begin); 103 __quex_assert(End > Begin); 104 105 /* If it is the first string to be appended, the store the location */ 106 # ifdef __QUEX_OPTION_COUNTER 107 if( me->text.begin == me->text.end ) { 108 __QUEX_IF_COUNT_COLUMNS(me->_begin_column = me->the_lexer->counter._column_number_at_begin); 109 __QUEX_IF_COUNT_LINES(me->_begin_line = me->the_lexer->counter._line_number_at_begin); 110 } 111 # endif 112 113 /* Ensure, that there is one more cell between end and .memory_end to store 114 * the terminating zero for flushing or printing. */ 115 if( me->text.memory_end <= me->text.end + L ) { 116 /* L + 1 we need space for the string + the terminating zero */ 117 if( QUEX_NAME(Accumulator_extend)(me, L + 1) == false ) { 118 QUEX_ERROR_EXIT("Quex Engine: Out of Memory. Accumulator could not be further extended.\n"); 119 } 120 } 121 122 __QUEX_STD_memcpy(me->text.end, Begin, L * sizeof(QUEX_TYPE_LEXATOM)); 123 me->text.end += L; 124 } 125 126 127 QUEX_INLINE void 128 QUEX_NAME(Accumulator_add_character)(QUEX_NAME(Accumulator)* me, 129 const QUEX_TYPE_LEXATOM Character) 130 { 131 /* If it is the first string to be appended, the store the location */ 132 # ifdef __QUEX_OPTION_COUNTER 133 if( me->text.begin == me->text.end ) { 134 __QUEX_IF_COUNT_COLUMNS(me->_begin_column = me->the_lexer->counter._column_number_at_begin); 135 __QUEX_IF_COUNT_LINES(me->_begin_line = me->the_lexer->counter._line_number_at_begin); 136 } 137 # endif 138 139 /* Ensure, that there is one more cell between end and .memory_end to store 140 * the terminating zero for flushing or printing. */ 141 if( me->text.memory_end <= me->text.end + 1 ) { 142 /* 1 + 1 we need space for the character + the terminating zero */ 143 if( QUEX_NAME(Accumulator_extend)(me, 2) == false ) { 144 QUEX_ERROR_EXIT("Quex Engine: Out of Memory. Accumulator could not be further extended.\n"); 145 } 146 } 147 148 *(me->text.end) = Character; 149 ++(me->text.end); 150 } 151 152 #if 0 153 QUEX_INLINE void 154 QUEX_NAME(Accumulator_flush)(QUEX_NAME(Accumulator)* me, 155 const QUEX_TYPE_TOKEN_ID TokenID) 156 { 157 /* All functions must ensure that there is one cell left to store the terminating zero. */ 158 __quex_assert(me->text.end < me->text.memory_end); 159 160 161 /* If no text is to be flushed, return undone */ 162 if( me->text.begin == me->text.end ) return; 163 164 *(me->text.end) = (QUEX_TYPE_LEXATOM)0; /* see above '__quex_assert()' */ 165 166 # define self (*me->the_lexer) 167 self_token_set_id(TokenID); 168 if( QUEX_NAME_TOKEN(take_text)(__QUEX_CURRENT_TOKEN_P, 169 me->the_lexer, 170 me->text.begin, 171 me->text.end) == false ) { 172 /* The called function does not need the memory chunk, we reuse it. */ 173 QUEX_NAME(Accumulator_clear)(me); 174 } else { 175 /* The called function wants to use the memory, so we get some new. */ 176 QUEX_NAME(Accumulator_init_memory)(me); 177 } 178 QUEX_TOKEN_POLICY_PREPARE_NEXT(); 179 # undef self 180 } 181 #endif 182 183 QUEX_INLINE void 184 QUEX_NAME(Accumulator_print_this)(QUEX_NAME(Accumulator)* me) 185 { 186 /* All functions must ensure that there is one cell left to store the terminating zero. */ 187 __quex_assert(me->text.end < me->text.memory_end); 188 189 *(me->text.end) = (QUEX_TYPE_LEXATOM)0; /* see above '__quex_assert()' */ 190 191 __QUEX_STD_printf(" Accumulator = '%s'\n", (const char*)me->text.begin); 192 } 193 194 QUEX_NAMESPACE_MAIN_CLOSE 195 196 #endif /* __QUEX_INCLUDE_GUARD__ANALYZER__ACCUMULATOR_I */