Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_capture_fd_solcap_reader_h 2 : #define HEADER_fd_src_flamenco_capture_fd_solcap_reader_h 3 : 4 : #include "fd_solcap.pb.h" 5 : #include "fd_solcap_proto.h" 6 : 7 : #if FD_HAS_HOSTED 8 : 9 : /* fd_solcap_chunk_iter_t helps with iterating through the chunks of a 10 : solcap file */ 11 : 12 : struct fd_solcap_chunk_iter { 13 : void * stream; 14 : fd_solcap_chunk_t chunk; 15 : int err; 16 : ulong chunk_off; /* Absolute file offset of current chunk */ 17 : ulong chunk_end; /* Absolute file offset of next chunk */ 18 : }; 19 : typedef struct fd_solcap_chunk_iter fd_solcap_chunk_iter_t; 20 : 21 : FD_PROTOTYPES_BEGIN 22 : 23 : /* fd_solcap_chunk_iter_new initializes the given iter. stream is a 24 : file handle (FILE * or platform equivalent). The stream cursor must 25 : point to the first chunk (not the file header). To read the first 26 : and subsequent chunks, use fd_solcap_chunk_iter_next. It is U.B. to 27 : call any other reader methods than "next" after "new". */ 28 : 29 : fd_solcap_chunk_iter_t * 30 : fd_solcap_chunk_iter_new( fd_solcap_chunk_iter_t * iter, 31 : void * stream ); 32 : 33 : /* fd_solcap_chunk_iter_next reads the next chunk header. Safe to call 34 : even if stream cursor was modified by user. On success, returns the 35 : file offset pointing to the first byte of the chunk. The cursor of 36 : iter->stream is undefined, so user should use fseek() with SEEK_SET 37 : to find data of interest. Typically use as follows: 38 : 39 : long chunk_goff = fd_solcap_chunk_iter_next( iter ); 40 : if( FD_UNLIKELY( chunk_goff<0L ) ) { ... } 41 : fseek( iter->stream, chunk_goff + my_offset, SEEK_SET ); 42 : 43 : On failure, returns -1L. Reasons for failure are end-of-file, I/O 44 : error, or parse error. errno-like code can be read via 45 : fd_solcap_chunk_iter_err, which returns 0 on end-of-file. Reasons 46 : for error (other than EOF) are written to warning log. */ 47 : 48 : long 49 : fd_solcap_chunk_iter_next( fd_solcap_chunk_iter_t * iter ); 50 : 51 : /* fd_solcap_chunk_iter_err returns errno of last failure. Returns 0 52 : if last failure was EOF, and non-zero otherwise. Return value is 53 : undefined if no failure occurred yet. */ 54 : 55 : static inline int 56 0 : fd_solcap_chunk_iter_err( fd_solcap_chunk_iter_t const * iter ) { 57 0 : return iter->err; 58 0 : } 59 : 60 : /* fd_solcap_chunk_iter_done returns 0 if there might be more chunks. 61 : Returns 1 if end-of-file was reached or read failure was encountered 62 : at last chunk. */ 63 : 64 : int 65 : fd_solcap_chunk_iter_done( fd_solcap_chunk_iter_t const * iter ); 66 : 67 : /* fd_solcap_chunk_iter_item returns pointer to last successful chunk 68 : header read (using fd_solcap_chunk_iter_next()). Lifetime of pointer 69 : is until next call to "next" or until lifetime of iter ends. If no 70 : successful call to fd_solcap_chunk_iter_next was made yet, "chunk" 71 : field of return value is zero. */ 72 : 73 : static inline fd_solcap_chunk_t const * 74 0 : fd_solcap_chunk_iter_item( fd_solcap_chunk_iter_t const * iter ) { 75 0 : return &iter->chunk; 76 0 : } 77 : 78 : /* fd_solcap_chunk_iter_find iterates through chunks until a chunk with 79 : the given magic is found. Returns absolute file offset of chunk if 80 : chunk was found, and -1L if chunk was not found. */ 81 : 82 : static inline long 83 : fd_solcap_chunk_iter_find( fd_solcap_chunk_iter_t * iter, 84 0 : ulong magic ) { 85 0 : for(;;) { 86 0 : long chunk_gaddr = fd_solcap_chunk_iter_next( iter ); 87 0 : if( FD_UNLIKELY( chunk_gaddr<0L ) ) 88 0 : return -1L; 89 0 : if( FD_UNLIKELY( fd_solcap_chunk_iter_done( iter ) ) ) 90 0 : return -1L; 91 0 : if( fd_solcap_chunk_iter_item( iter )->magic == magic ) 92 0 : return chunk_gaddr; 93 0 : } 94 0 : } 95 : 96 : /* fd_solcap_read_bank_preimage reads and parses the bank preimage 97 : metadata blob. chunk_goff is the file offset of the chunk containing 98 : the bank preimage. hdr points to a copy of the corresponding chunk 99 : header. */ 100 : 101 : int 102 : fd_solcap_read_bank_preimage( void * stream, 103 : ulong chunk_goff, 104 : fd_solcap_BankPreimage * preimage, 105 : fd_solcap_chunk_t const * hdr ); 106 : 107 : /* fd_solcap_find_account_table reads an account table meta and seeks 108 : the given (FILE *) like stream to the first account table row. 109 : acc_tbl_goff is the file offset of the chunk containing the account 110 : table. On success, writes the account meta to *meta and returns 0. 111 : On failure, returns errno-like error code. */ 112 : 113 : int 114 : fd_solcap_find_account_table( void * _file, 115 : fd_solcap_AccountTableMeta * meta, 116 : ulong acc_tbl_goff ); 117 : 118 : /* fd_solcap_includes_account_data returns 1 if a capture account chunk 119 : includes account data, and 0 otherwise. Reasons for missing account 120 : data are that capture program deliberately excluded them, or that 121 : account data size is zero. */ 122 : 123 : static inline int 124 0 : fd_solcap_includes_account_data( fd_solcap_AccountMeta const * meta ) { 125 0 : return (!!meta->data_coff) & (!!meta->data_sz); 126 0 : } 127 : 128 : /* fd_solcap_find_account reads an account meta. If opt_data_off, sets 129 : *opt_data_off to the file offset to account data. If account data 130 : size is zero or the capture does not include account data, 131 : *opt_data_off is undefined. (Use fd_solcap_includes_account_data to 132 : check). Returns 0 on success or errno-like on failure. */ 133 : 134 : int 135 : fd_solcap_find_account( void * _file, 136 : fd_solcap_AccountMeta * meta, 137 : ulong * opt_data_off, 138 : fd_solcap_account_tbl_t const * rec, 139 : ulong acc_tbl_goff ); 140 : 141 : 142 : FD_PROTOTYPES_END 143 : 144 : #endif /* FD_HAS_HOSTED */ 145 : 146 : #endif /* HEADER_fd_src_flamenco_capture_fd_solcap_reader_h */ 147 :