ByteLoader.i (5989B)
1 /* vim: set ft=c: 2 * (C) Frank-Rene Schaefer */ 3 #ifndef __QUEX_INCLUDE_GUARD__BUFFER__BYTES__BYTE_LOADER_I 4 #define __QUEX_INCLUDE_GUARD__BUFFER__BYTES__BYTE_LOADER_I 5 6 QUEX_NAMESPACE_MAIN_OPEN 7 8 QUEX_INLINE QUEX_TYPE_STREAM_POSITION 9 QUEX_NAME(ByteLoader_tell)(QUEX_NAME(ByteLoader)* me); 10 11 QUEX_INLINE void 12 QUEX_NAME(ByteLoader_seek)(QUEX_NAME(ByteLoader)* me, QUEX_TYPE_STREAM_POSITION Position); 13 14 QUEX_INLINE size_t 15 QUEX_NAME(ByteLoader_load)(QUEX_NAME(ByteLoader)* me, void* begin_p, const size_t N, bool* end_of_stream_f); 16 17 QUEX_INLINE void 18 QUEX_NAME(ByteLoader_construct)(QUEX_NAME(ByteLoader)* me, 19 QUEX_TYPE_STREAM_POSITION (*tell)(QUEX_NAME(ByteLoader)* me), 20 void (*seek)(QUEX_NAME(ByteLoader)* me, QUEX_TYPE_STREAM_POSITION Pos), 21 size_t (*load)(QUEX_NAME(ByteLoader)*, void*, const size_t, bool*), 22 void (*delete_self)(QUEX_NAME(ByteLoader)*), 23 bool (*compare_handle)(const QUEX_NAME(ByteLoader)*, 24 const QUEX_NAME(ByteLoader)*)) 25 { 26 me->tell = QUEX_NAME(ByteLoader_tell); 27 me->seek = QUEX_NAME(ByteLoader_seek); 28 me->load = QUEX_NAME(ByteLoader_load); 29 me->derived.tell = tell; 30 me->derived.seek = seek; 31 me->derived.load = load; 32 me->delete_self = delete_self; 33 me->compare_handle = compare_handle; 34 me->on_nothing = (bool (*)(struct QUEX_NAME(ByteLoader_tag)*, size_t, size_t))0; 35 36 me->handle_ownership = E_Ownership_EXTERNAL; /* Default */ 37 me->ownership = E_Ownership_EXTERNAL; /* Default */ 38 39 me->initial_position = tell(me); 40 41 me->binary_mode_f = false; /* Default: 'false' is SAFE */ 42 } 43 44 QUEX_INLINE QUEX_TYPE_STREAM_POSITION 45 QUEX_NAME(ByteLoader_tell)(QUEX_NAME(ByteLoader)* me) 46 { 47 return me->derived.tell(me); 48 } 49 50 QUEX_INLINE void 51 QUEX_NAME(ByteLoader_seek_disable)(QUEX_NAME(ByteLoader)* me) 52 { 53 me->derived.seek = (void (*)(QUEX_NAME(ByteLoader)*, QUEX_TYPE_STREAM_POSITION))0; 54 } 55 56 QUEX_INLINE bool 57 QUEX_NAME(ByteLoader_seek_is_enabled)(QUEX_NAME(ByteLoader)* me) 58 { 59 return me->derived.seek ? true : false; 60 } 61 62 QUEX_INLINE void 63 QUEX_NAME(ByteLoader_seek)(QUEX_NAME(ByteLoader)* me, QUEX_TYPE_STREAM_POSITION Position) 64 { 65 if ( Position < me->initial_position ) return; 66 else if( ! me->derived.seek ) return; 67 me->derived.seek(me, Position); 68 } 69 70 QUEX_INLINE size_t 71 QUEX_NAME(ByteLoader_load)(QUEX_NAME(ByteLoader)* me, void* begin_p, const size_t N, bool* end_of_stream_f) 72 /* RETURNS: != 0, if something could be loaded 73 * == 0, if nothing could be loaded further. End of stream (EOS). 74 * 75 * Additionally, 'end_of_stream_f' may hint the end of the stream while still 76 * some bytes have been loaded. 77 * 78 * *end_of_stream_f == true => End of stream has been reached. 79 * *end_of_stream_f == false => No assumption if end of stream ore not. 80 * 81 * The first case is solely a hint to help the caller to act upon end of stream 82 * before actually reading zero bytes. It may spare a unnecessary load-cycle 83 * which ends up with no load at all. */ 84 { 85 size_t loaded_n; 86 size_t try_n = 0; 87 88 *end_of_stream_f = false; 89 90 if( ! N ) { 91 return 0; 92 } 93 94 do { 95 /* Try to load 'N' bytes. */ 96 loaded_n = me->derived.load(me, begin_p, N, end_of_stream_f); 97 if( loaded_n ) { 98 /* If at least some bytes could be loaded, return 'success'. */ 99 return loaded_n; 100 } 101 else if( ! me->on_nothing ) { 102 /* No plan for absence of data, return 'failure', EOS. */ 103 *end_of_stream_f = true; 104 return 0; 105 } 106 ++try_n; 107 108 } while( me->on_nothing(me, try_n, N) ); 109 110 /* If user's on nothing returns 'false' no further attemps to read. */ 111 *end_of_stream_f = true; 112 113 return 0; 114 } 115 116 QUEX_INLINE bool 117 QUEX_NAME(ByteLoader_is_equivalent)(const QUEX_NAME(ByteLoader)* A, 118 const QUEX_NAME(ByteLoader)* B) 119 /* RETURNS: true -- if A and B are equivalent. 120 * false -- else. */ 121 { 122 /* If two QUEX_NAME(ByteLoader )classes use the same 'load()' function, then they 123 * should not be different. For example, it does not make sense to have 124 * two loaders implementing stdandard libraries 'fread()' interface. 125 * 126 * Further, it is always safe to return 'false'. */ 127 if( A == NULL ) { 128 if( B != NULL ) return false; 129 else return true; 130 } 131 else if( B == NULL ) { 132 return false; 133 } 134 else if( A->load != B->load ) { 135 return false; 136 } 137 138 /* The 'compare_handle()' function can now safely cast the two pointers 139 * to its pointer type. */ 140 return A->compare_handle(A, B); 141 } 142 143 QUEX_INLINE void 144 QUEX_NAME(ByteLoader_delete)(QUEX_NAME(ByteLoader)** me) 145 { 146 if( ! *me ) return; 147 else if( (*me)->ownership != E_Ownership_LEXICAL_ANALYZER ) return; 148 else if( (*me)->delete_self ) (*me)->delete_self(*me); 149 (*me) = (QUEX_NAME(ByteLoader)*)0; 150 } 151 152 QUEX_NAMESPACE_MAIN_CLOSE 153 154 #include "ByteLoader_FILE.i" 155 #include "ByteLoader_stream.i" 156 #ifdef QUEX_OPTION_POSIX 157 # include <quex/code_base/buffer/bytes/ByteLoader_POSIX.i> /* (tm) */ 158 #endif 159 #if 0 160 # include <quex/code_base/buffer/bytes/ByteLoader_FreeRTOS.i> /* (tm) */ 161 # include <quex/code_base/buffer/bytes/ByteLoader_PalmOS.i> /* (tm) */ 162 #endif 163 164 #endif /* __QUEX_INCLUDE_GUARD__BUFFER__BYTES__BYTE_LOADER_I */