sheepy

build system (sheepy) and package manager (spm) for C
git clone https://spartatek.se/git/sheepy.git
Log | Files | Refs | README | LICENSE

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 */