@@ -91,13 +91,14 @@ uint32_t read_uint32(byte *ptr) {
9191// Also returns the length of the varint
9292uint16_t read_vint16 (byte * ptr , int8_t * vlen ) {
9393 uint16_t ret = 0 ;
94- * vlen = 3 ; // read max 3 bytes
94+ int8_t len = 3 ; // read max 3 bytes
9595 do {
9696 ret <<= 7 ;
9797 ret += * ptr & 0x7F ;
98- (* vlen )-- ;
99- } while ((* ptr ++ & 0x80 ) == 0x80 && * vlen );
100- * vlen = 3 - * vlen ;
98+ len -- ;
99+ } while ((* ptr ++ & 0x80 ) == 0x80 && len );
100+ if (vlen )
101+ * vlen = 3 - len ;
101102 return ret ;
102103}
103104
@@ -106,16 +107,33 @@ uint16_t read_vint16(byte *ptr, int8_t *vlen) {
106107// Also returns the length of the varint
107108uint32_t read_vint32 (byte * ptr , int8_t * vlen ) {
108109 uint32_t ret = 0 ;
109- * vlen = 5 ; // read max 5 bytes
110+ int8_t len = 5 ; // read max 5 bytes
110111 do {
111112 ret <<= 7 ;
112113 ret += * ptr & 0x7F ;
113- (* vlen )-- ;
114- } while ((* ptr ++ & 0x80 ) == 0x80 && * vlen );
115- * vlen = 5 - * vlen ;
114+ len -- ;
115+ } while ((* ptr ++ & 0x80 ) == 0x80 && len );
116+ if (vlen )
117+ * vlen = 5 - len ;
116118 return ret ;
117119}
118120
121+ // Converts float to Sqlite's Big-endian double
122+ uint64_t float_to_double (const void * val ) {
123+ uint32_t bytes = * ((uint32_t * ) val );
124+ uint8_t exp8 = (bytes >> 23 ) & 0xFF ;
125+ uint16_t exp11 = exp8 ;
126+ if (exp11 != 0 ) {
127+ if (exp11 < 127 )
128+ exp11 = 1023 - (127 - exp11 );
129+ else
130+ exp11 = 1023 + (exp11 - 127 );
131+ }
132+ return ((uint64_t )(bytes >> 31 ) << 63 )
133+ | ((uint64_t )exp11 << 52 )
134+ | ((uint64_t )(bytes & 0x7FFFFF ) << (52 - 23 ) );
135+ }
136+
119137// Returns actual page size from given exponent
120138int32_t get_pagesize (byte page_size_exp ) {
121139 return (int32_t ) 1 << page_size_exp ;
@@ -315,9 +333,9 @@ int check_sums(byte *buf, int32_t page_size, int check_or_calc) {
315333 while (i < page_size )
316334 chk_sum += buf [i ++ ];
317335 if (check_or_calc )
318- buf [69 ] = page_chk ;
336+ buf [69 ] = chk_sum ;
319337 else {
320- if (buf [69 ] != page_chk )
338+ if (buf [69 ] != chk_sum )
321339 return ULS_RES_ERR ;
322340 }
323341 }
@@ -916,22 +934,60 @@ int uls_read_last_row(struct uls_read_context *rctx) {
916934// Reads the buffer part by part to avoid reading entire buffer into memory
917935// to support low memory systems (2kb ram)
918936// The underlying callback function hopefully optimizes repeated IO
919- int read_last_rowid (struct uls_read_context * rctx , uint32_t pos , int32_t page_size , uint32_t * out_rowid , uint16_t * out_rec_pos ) {
937+ int read_last_val (struct uls_read_context * rctx , uint32_t pos ,
938+ int32_t page_size , int col_idx , byte * * pval_at ,
939+ uint32_t * out_col_type , uint16_t * out_rec_pos , byte is_rowid ) {
920940 byte src_buf [12 ];
921941 int res = read_bytes_rctx (rctx , src_buf , pos * page_size , 12 );
922942 if (res )
923943 return res ;
924944 if (* src_buf != 13 )
925945 return ULS_RES_MALFORMED ;
926946 * out_rec_pos = read_uint16 (src_buf + 3 ) - 1 ;
927- res = read_bytes_rctx (rctx , src_buf , pos * page_size + read_uint16 (src_buf + 5 ), 12 );
947+ uint16_t last_pos = read_uint16 (src_buf + 5 );
948+ res = read_bytes_rctx (rctx , src_buf , pos * page_size + last_pos , 12 );
928949 if (res )
929950 return res ;
930951 int8_t vint_len ;
931- * out_rowid = read_vint32 (src_buf + 3 , & vint_len );
952+ uint32_t row_id = read_vint32 (src_buf + 3 , & vint_len );
953+ if (is_rowid )
954+ * out_col_type = row_id ;
955+ else {
956+ uint16_t rec_len = read_vint16 (src_buf , NULL ) + vint_len + LEN_OF_REC_LEN ;
957+ byte rec_buf [rec_len ];
958+ res = read_bytes_rctx (rctx , rec_buf , pos * page_size + last_pos , rec_len );
959+ if (res )
960+ return res ;
961+ uint16_t hdr_len ;
962+ byte * hdr_ptr = locate_column (rec_buf , col_idx , pval_at , & rec_len , & hdr_len );
963+ if (!hdr_ptr )
964+ return ULS_RES_NOT_FOUND ;
965+ * out_col_type = read_vint32 (hdr_ptr , & vint_len );
966+ }
932967 return ULS_RES_OK ;
933968}
934969
970+ byte * read_val_at (struct uls_read_context * rctx , uint32_t pos , int col_idx ,
971+ uint32_t * out_col_type , byte is_rowid ) {
972+ int8_t vint_len ;
973+ uint16_t rec_pos = read_uint16 (rctx -> buf + 8 + pos * 2 );
974+ uint32_t row_id = read_vint32 (rctx -> buf + rec_pos + LEN_OF_REC_LEN , & vint_len );
975+ if (is_rowid )
976+ * out_col_type = row_id ;
977+ else {
978+ uint16_t hdr_len ;
979+ uint16_t rec_len ;
980+ byte * data_ptr ;
981+ byte * hdr_ptr ;
982+ hdr_ptr = locate_column (rctx -> buf , col_idx , & data_ptr , & rec_len , & hdr_len );
983+ if (!hdr_ptr )
984+ return NULL ;
985+ * out_col_type = read_vint32 (hdr_ptr , & vint_len );
986+ return data_ptr ;
987+ }
988+ return NULL ;
989+ }
990+
935991// Returns the Row ID of the record at given position
936992uint32_t read_rowid_at (struct uls_read_context * rctx , uint32_t rec_pos ) {
937993 int8_t vint_len ;
@@ -999,22 +1055,6 @@ int uls_srch_row_by_id(struct uls_read_context *rctx, uint32_t rowid) {
9991055 return ULS_RES_NOT_FOUND ;
10001056}
10011057
1002- // Converts float to Sqlite's Big-endian double
1003- uint64_t float_to_double (const void * val ) {
1004- uint32_t bytes = * ((uint32_t * ) val );
1005- uint8_t exp8 = (bytes >> 23 ) & 0xFF ;
1006- uint16_t exp11 = exp8 ;
1007- if (exp11 != 0 ) {
1008- if (exp11 < 127 )
1009- exp11 = 1023 - (127 - exp11 );
1010- else
1011- exp11 = 1023 + (exp11 - 127 );
1012- }
1013- return ((uint64_t )(bytes >> 31 ) << 63 )
1014- | ((uint64_t )exp11 << 52 )
1015- | ((uint64_t )(bytes & 0x7FFFFF ) << (52 - 23 ) );
1016- }
1017-
10181058// compares two binary strings and returns k, -k or 0
10191059// 0 meaning the two are identical. If not, k is length that matches
10201060int compare_bin (const byte * v1 , byte len1 , const byte * v2 , byte len2 ) {
@@ -1036,7 +1076,7 @@ int compare_bin(const byte *v1, byte len1, const byte *v2, byte len2) {
10361076}
10371077
10381078// Compare values for binary search and return 1, -1 or 0
1039- int compare_vals (byte * val_at , uint32_t u32_at , int val_type , void * val , uint16_t len , byte is_rowid ) {
1079+ int compare_values (byte * val_at , uint32_t u32_at , int val_type , void * val , uint16_t len , byte is_rowid ) {
10401080 if (is_rowid )
10411081 return (u32_at > * ((uint32_t * ) val ) ? 1 : u32_at < * ((uint32_t * ) val ) ? -1 : 0 );
10421082 switch (val_type ) {
@@ -1075,15 +1115,17 @@ int compare_vals(byte *val_at, uint32_t u32_at, int val_type, void *val, uint16_
10751115 bytes64 = * ((uint64_t * ) val );
10761116 return (bytes64_at > bytes64 ? 1 : bytes64_at < bytes64 ? -1 : 0 );
10771117 case ULS_TYPE_BLOB :
1078- case ULS_TYPE_TEXT :
1118+ case ULS_TYPE_TEXT : {
10791119 uint32_t len_at = uls_derive_data_len (u32_at );
10801120 int res = compare_bin (val_at , len_at , val , len );
10811121 return (res > 0 ? 1 : (res < 0 ? -1 : 0 ));
1122+ }
10821123 }
1124+ return 1 ;
10831125}
10841126
10851127// See .h file for API description
1086- int uls_bin_srch_row_by_val (struct uls_read_context * rctx ,
1128+ int uls_bin_srch_row_by_val (struct uls_read_context * rctx , int col_idx ,
10871129 int val_type , void * val , uint16_t len , byte is_rowid ) {
10881130 int32_t page_size = get_pagesize (rctx -> page_size_exp );
10891131 if (rctx -> last_leaf_page == 0 )
@@ -1097,10 +1139,10 @@ int uls_bin_srch_row_by_val(struct uls_read_context *rctx,
10971139 uint16_t rec_pos ;
10981140 byte * val_at ;
10991141 uint32_t u32_at ;
1100- res = read_last_val (rctx , middle , page_size , & u32_at , is_rowid , & rec_pos );
1142+ res = read_last_val (rctx , middle , page_size , col_idx , & val_at , & u32_at , & rec_pos , is_rowid );
11011143 if (res )
11021144 return res ;
1103- int cmp = compare_vals (val_at , u32_at , val_type , val , len , is_rowid );
1145+ int cmp = compare_values (val_at , u32_at , val_type , val , len , is_rowid );
11041146 if (cmp == ULS_RES_TYPE_MISMATCH )
11051147 return cmp ;
11061148 if (cmp < 0 )
@@ -1125,10 +1167,10 @@ int uls_bin_srch_row_by_val(struct uls_read_context *rctx,
11251167 while (first < size ) {
11261168 middle = (first + size ) >> 1 ;
11271169 uint32_t u32_at ;
1128- byte * val_at = read_val_at (rctx , middle , & u32_at );
1129- if (res )
1130- return res ;
1131- int cmp = compare_vals (val_at , u32_at , val_type , val , len , is_rowid );
1170+ byte * val_at = read_val_at (rctx , middle , col_idx , & u32_at , is_rowid );
1171+ if (! val_at )
1172+ return ULS_RES_NOT_FOUND ;
1173+ int cmp = compare_values (val_at , u32_at , val_type , val , len , is_rowid );
11321174 if (cmp == ULS_RES_TYPE_MISMATCH )
11331175 return cmp ;
11341176 if (cmp < 0 )
0 commit comments