Line data Source code
1 : #include "fd_pb_tokenize.h" 2 : #include "fd_pb_wire.h" 3 : 4 : static fd_pb_inbuf_t * 5 : read_varint( fd_pb_inbuf_t * buf, 6 0 : ulong * out ) { 7 0 : ulong sz = (ulong)( buf->end - buf->cur ); 8 0 : ulong var = 0UL; 9 0 : int shift = 0; 10 0 : for( ulong i=0UL;; i++ ) { 11 0 : if( FD_UNLIKELY( i>=10 || i>=sz ) ) return NULL; 12 : /* FIXME check if one bits are shifted out of bounds */ 13 0 : var |= (ulong)( buf->cur[i] & 0x7f ) << shift; 14 0 : shift += 7; 15 0 : if( !( buf->cur[i] & 0x80 ) ) { 16 0 : buf->cur += i+1; 17 0 : *out = var; 18 0 : return buf; 19 0 : } 20 0 : } 21 0 : } 22 : 23 : static fd_pb_tlv_t * 24 : fd_pb_read_tlv_slow( fd_pb_inbuf_t * buf, 25 0 : fd_pb_tlv_t * tlv ) { 26 0 : fd_pb_inbuf_t buf2 = *buf; 27 0 : ulong tag; 28 0 : if( FD_UNLIKELY( !read_varint( &buf2, &tag ) ) ) return NULL; 29 0 : if( FD_UNLIKELY( tag>UINT_MAX ) ) return NULL; 30 0 : uint wire_type = fd_pb_tag_wire_type( (uint)tag ); 31 0 : uint field_id = fd_pb_tag_field_id ( (uint)tag ); 32 0 : ulong val; 33 0 : switch( wire_type ) { 34 0 : case FD_PB_WIRE_TYPE_VARINT: 35 0 : case FD_PB_WIRE_TYPE_LEN: 36 0 : if( FD_UNLIKELY( !read_varint( &buf2, &val ) ) ) return NULL; 37 0 : break; 38 0 : case FD_PB_WIRE_TYPE_I64: 39 0 : if( FD_UNLIKELY( (ulong)( buf2.end - buf2.cur )<8UL ) ) return NULL; 40 0 : val = FD_LOAD( ulong, buf2.cur ); 41 0 : buf2.cur += 8UL; 42 0 : break; 43 0 : case FD_PB_WIRE_TYPE_I32: 44 0 : if( FD_UNLIKELY( (ulong)( buf2.end - buf2.cur )<4UL ) ) return NULL; 45 0 : val = (ulong)FD_LOAD( uint, buf2.cur ); 46 0 : buf2.cur += 4UL; 47 0 : break; 48 0 : default: 49 0 : return NULL; 50 0 : } 51 0 : *tlv = (fd_pb_tlv_t) { 52 0 : .wire_type = wire_type, 53 0 : .field_id = field_id, 54 0 : .varint = val 55 0 : }; 56 0 : *buf = buf2; 57 0 : return tlv; 58 0 : } 59 : 60 : fd_pb_tlv_t * 61 : fd_pb_read_tlv( fd_pb_inbuf_t * buf, 62 0 : fd_pb_tlv_t * tlv ) { 63 : /* FIXME plenty of optimization opportunities here */ 64 0 : return fd_pb_read_tlv_slow( buf, tlv ); 65 0 : }