@@ -622,18 +622,7 @@ int uls_set_col_val(struct uls_write_context *wctx,
622622 } else
623623 if (type == ULS_TYPE_REAL && len == 4 ) {
624624 // Assumes float is represented in IEEE-754 format
625- uint32_t bytes = * ((uint32_t * ) val );
626- uint8_t exp8 = (bytes >> 23 ) & 0xFF ;
627- uint16_t exp11 = exp8 ;
628- if (exp11 != 0 ) {
629- if (exp11 < 127 )
630- exp11 = 1023 - (127 - exp11 );
631- else
632- exp11 = 1023 + (exp11 - 127 );
633- }
634- uint64_t bytes64 = ((uint64_t )(bytes >> 31 ) << 63 )
635- | ((uint64_t )exp11 << 52 )
636- | ((uint64_t )(bytes & 0x7FFFFF ) << (52 - 23 ) );
625+ uint64_t bytes64 = float_to_double (val );
637626 write_uint64 (data_ptr , bytes64 );
638627 } else
639628 if (type == ULS_TYPE_REAL && len == 8 ) {
@@ -1010,20 +999,92 @@ int uls_srch_row_by_id(struct uls_read_context *rctx, uint32_t rowid) {
1010999 return ULS_RES_NOT_FOUND ;
10111000}
10121001
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+
1018+ // compares two binary strings and returns k, -k or 0
1019+ // 0 meaning the two are identical. If not, k is length that matches
1020+ int compare_bin (const byte * v1 , byte len1 , const byte * v2 , byte len2 ) {
1021+ int k = 0 ;
1022+ int lim = (len2 < len1 ? len2 : len1 );
1023+ while (k < lim ) {
1024+ byte c1 = v1 [k ];
1025+ byte c2 = v2 [k ];
1026+ k ++ ;
1027+ if (c1 < c2 )
1028+ return - k ;
1029+ else if (c1 > c2 )
1030+ return k ;
1031+ }
1032+ if (len1 == len2 )
1033+ return 0 ;
1034+ k ++ ;
1035+ return (len1 < len2 ? - k : k );
1036+ }
1037+
1038+ // Compare values for binary search and return 1, -1 or 0
10131039int compare_vals (byte * val_at , uint32_t u32_at , int val_type , void * val , uint16_t len , byte is_rowid ) {
10141040 if (is_rowid )
10151041 return (u32_at > * ((uint32_t * ) val ) ? 1 : u32_at < * ((uint32_t * ) val ) ? -1 : 0 );
10161042 switch (val_type ) {
10171043 case ULS_TYPE_INT :
1018-
1044+ if (u32_at != len )
1045+ return ULS_RES_TYPE_MISMATCH ;
1046+ if (len == 4 ) {
1047+ int32_t iat = * ((int32_t * ) val_at );
1048+ int32_t ival = * ((int32_t * ) val );
1049+ return (iat > ival ? 1 : iat < ival ? -1 : 0 );
1050+ }
1051+ if (len == 2 ) {
1052+ int16_t iat = * ((int16_t * ) val_at );
1053+ int16_t ival = * ((int16_t * ) val );
1054+ return (iat > ival ? 1 : iat < ival ? -1 : 0 );
1055+ }
1056+ if (len == 6 ) {
1057+ int64_t iat = * ((int64_t * ) val_at );
1058+ int64_t ival = * ((int64_t * ) val );
1059+ return (iat > ival ? 1 : iat < ival ? -1 : 0 );
1060+ }
1061+ if (len == 1 ) {
1062+ int8_t iat = * ((int8_t * ) val_at );
1063+ int8_t ival = * ((int8_t * ) val );
1064+ return (iat > ival ? 1 : iat < ival ? -1 : 0 );
1065+ }
1066+ return ULS_RES_TYPE_MISMATCH ;
10191067 case ULS_TYPE_REAL :
1020- case ULS_TYPE_TEXT :
1068+ if ((len != 4 && len != 8 ) || u32_at != 8 )
1069+ return ULS_RES_TYPE_MISMATCH ;
1070+ uint64_t bytes64 , bytes64_at ;
1071+ bytes64 = * ((uint64_t * ) val_at );
1072+ if (len == 4 )
1073+ bytes64 = float_to_double (val );
1074+ else
1075+ bytes64 = * ((uint64_t * ) val );
1076+ return (bytes64_at > bytes64 ? 1 : bytes64_at < bytes64 ? -1 : 0 );
10211077 case ULS_TYPE_BLOB :
1078+ case ULS_TYPE_TEXT :
1079+ uint32_t len_at = uls_derive_data_len (u32_at );
1080+ int res = compare_bin (val_at , len_at , val , len );
1081+ return (res > 0 ? 1 : (res < 0 ? -1 : 0 ));
10221082 }
10231083}
10241084
10251085// See .h file for API description
1026- int uls_bin_srch_row_by_val (struct uls_read_context * rctx , int val_type , void * val , uint16_t len , byte is_rowid ) {
1086+ int uls_bin_srch_row_by_val (struct uls_read_context * rctx ,
1087+ int val_type , void * val , uint16_t len , byte is_rowid ) {
10271088 int32_t page_size = get_pagesize (rctx -> page_size_exp );
10281089 if (rctx -> last_leaf_page == 0 )
10291090 return ULS_RES_NOT_FINALIZED ;
@@ -1040,6 +1101,8 @@ int uls_bin_srch_row_by_val(struct uls_read_context *rctx, int val_type, void *v
10401101 if (res )
10411102 return res ;
10421103 int cmp = compare_vals (val_at , u32_at , val_type , val , len , is_rowid );
1104+ if (cmp == ULS_RES_TYPE_MISMATCH )
1105+ return cmp ;
10431106 if (cmp < 0 )
10441107 first = middle + 1 ;
10451108 else if (cmp > 0 )
@@ -1066,6 +1129,8 @@ int uls_bin_srch_row_by_val(struct uls_read_context *rctx, int val_type, void *v
10661129 if (res )
10671130 return res ;
10681131 int cmp = compare_vals (val_at , u32_at , val_type , val , len , is_rowid );
1132+ if (cmp == ULS_RES_TYPE_MISMATCH )
1133+ return cmp ;
10691134 if (cmp < 0 )
10701135 first = middle + 1 ;
10711136 else if (cmp > 0 )
0 commit comments