/ Check-in [94c4cdc5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:When converting from a BLOB value in the tointeger() and toreal() SQL functions, make sure that endianness of the machine does not matter.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | toTypeFuncs
Files: files | file ages | folders
SHA1: 94c4cdc50d2753c859e494d53cebd09edd2e5663
User & Date: mistachkin 2013-09-06 20:30:53
Context
2013-09-06
21:41
Add the ability to generate assembly listing files using the MSVC makefile. check-in: 6caa2cd1 user: mistachkin tags: toTypeFuncs
20:30
When converting from a BLOB value in the tointeger() and toreal() SQL functions, make sure that endianness of the machine does not matter. check-in: 94c4cdc5 user: mistachkin tags: toTypeFuncs
2013-09-04
00:58
Additional test cases for the tointeger() and toreal() SQL functions when converting from a BLOB. check-in: e1814452 user: mistachkin tags: toTypeFuncs
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/func.c.

   962    962         sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
   963    963         break;
   964    964       }
   965    965     }
   966    966   }
   967    967   
   968    968   /*
   969         -** tointeger(X):  If X is any value (integer, double, or string) that can
   970         -** be losslessly converted into an integer, then make the conversion and
          969  +** tointeger(X):  If X is any value (integer, double, blob, or string) that
          970  +** can be losslessly converted into an integer, then make the conversion and
   971    971   ** return the result.  Otherwise, return NULL.
   972    972   */
   973    973   static void tointegerFunc(
   974    974     sqlite3_context *context,
   975    975     int argc,
   976    976     sqlite3_value **argv
   977    977   ){
................................................................................
   992    992       }
   993    993       case SQLITE_BLOB: {
   994    994         const unsigned char *zBlob = sqlite3_value_blob(argv[0]);
   995    995         if( zBlob ){
   996    996           int nBlob = sqlite3_value_bytes(argv[0]);
   997    997           if( nBlob==sizeof(i64) ){
   998    998             i64 iVal;
   999         -          memcpy(&iVal, zBlob, sizeof(i64));
          999  +          if( SQLITE_BIGENDIAN ){
         1000  +            int i;
         1001  +            unsigned char *zBlobRev = contextMalloc(context, nBlob);
         1002  +            if( !zBlobRev ) break;
         1003  +            for(i=0; i<nBlob; i++) zBlobRev[i] = zBlob[nBlob-1-i];
         1004  +            memcpy(&iVal, zBlobRev, sizeof(i64));
         1005  +            sqlite3_free(zBlobRev);
         1006  +          }else{
         1007  +            memcpy(&iVal, zBlob, sizeof(i64));
         1008  +          }
  1000   1009             sqlite3_result_int64(context, iVal);
  1001   1010           }
  1002   1011         }
  1003   1012         break;
  1004   1013       }
  1005   1014       case SQLITE_TEXT: {
  1006   1015         const unsigned char *zStr = sqlite3_value_text(argv[0]);
................................................................................
  1019   1028         assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
  1020   1029         break;
  1021   1030       }
  1022   1031     }
  1023   1032   }
  1024   1033   
  1025   1034   /*
  1026         -** toreal(X):  If X can be losslessly converted into a real number, then
  1027         -** do so and return that real number.  Otherwise return NULL.
         1035  +** toreal(X): If X is any value (integer, double, blob, or string) that can
         1036  +** be losslessly converted into a real number, then do so and return that
         1037  +** real number.  Otherwise return NULL.
  1028   1038   */
  1029   1039   #if defined(_MSC_VER)
  1030   1040   #pragma optimize("", off)
  1031   1041   #endif
  1032   1042   static void torealFunc(
  1033   1043     sqlite3_context *context,
  1034   1044     int argc,
................................................................................
  1051   1061       }
  1052   1062       case SQLITE_BLOB: {
  1053   1063         const unsigned char *zBlob = sqlite3_value_blob(argv[0]);
  1054   1064         if( zBlob ){
  1055   1065           int nBlob = sqlite3_value_bytes(argv[0]);
  1056   1066           if( nBlob==sizeof(double) ){
  1057   1067             double rVal;
  1058         -          memcpy(&rVal, zBlob, sizeof(double));
         1068  +          if( SQLITE_LITTLEENDIAN ){
         1069  +            int i;
         1070  +            unsigned char *zBlobRev = contextMalloc(context, nBlob);
         1071  +            if( !zBlobRev ) break;
         1072  +            for(i=0; i<nBlob; i++) zBlobRev[i] = zBlob[nBlob-1-i];
         1073  +            memcpy(&rVal, zBlobRev, sizeof(double));
         1074  +            sqlite3_free(zBlobRev);
         1075  +          }else{
         1076  +            memcpy(&rVal, zBlob, sizeof(double));
         1077  +          }
  1059   1078             sqlite3_result_double(context, rVal);
  1060   1079           }
  1061   1080         }
  1062   1081         break;
  1063   1082       }
  1064   1083       case SQLITE_TEXT: {
  1065   1084         const unsigned char *zStr = sqlite3_value_text(argv[0]);

Changes to test/func4.test.

   663    663     ifcapable floatingpoint {
   664    664       do_execsql_test func4-6.1.$i.2 [subst {
   665    665         SELECT toreal(x'[string repeat 01 $i]');
   666    666       }] {{}}
   667    667     }
   668    668   }
   669    669   
   670         -proc swapHexBytes { value } {
   671         -  if {[string length $value] % 2 != 0} {
   672         -    error "value \"$value\" must have an even number of characters"
   673         -  }
   674         -  if {![string is xdigit -strict $value]} then {
   675         -    error "value \"$value\" must contain only hexadecimal digits"
   676         -  }
   677         -  join [lreverse [regexp -all -inline {.{2}} $value]] ""
   678         -}
   679         -
   680         -proc swapIntegerHexBytes { value } {
   681         -  if {![info exists ::tcl_platform(byteOrder)] || \
   682         -      $::tcl_platform(byteOrder) eq "littleEndian"} {
   683         -    return $value
   684         -  }
   685         -  return [swapHexBytes $value]
   686         -}
   687         -
   688         -proc swapDoubleHexBytes { value } {
   689         -  if {![info exists ::tcl_platform(byteOrder)] || \
   690         -      $::tcl_platform(byteOrder) ne "littleEndian"} {
   691         -    return $value
   692         -  }
   693         -  return [swapHexBytes $value]
   694         -}
   695         -
   696         -do_execsql_test func4-6.2.1 [subst {
   697         -  SELECT tointeger(x'[swapIntegerHexBytes 0102030405060708]');
   698         -}] {578437695752307201}
   699         -do_execsql_test func4-6.2.2 [subst {
   700         -  SELECT tointeger(x'[swapIntegerHexBytes 0807060504030201]');
   701         -}] {72623859790382856}
          670  +do_execsql_test func4-6.2.1 {
          671  +  SELECT tointeger(x'0102030405060708');
          672  +} {578437695752307201}
          673  +do_execsql_test func4-6.2.2 {
          674  +  SELECT tointeger(x'0807060504030201');
          675  +} {72623859790382856}
   702    676   
   703    677   ifcapable floatingpoint {
   704         -  do_execsql_test func4-6.3.1 [subst {
   705         -    SELECT toreal(x'[swapDoubleHexBytes ffefffffffffffff]');
   706         -  }] {-1.7976931348623157e+308}
   707         -  do_execsql_test func4-6.3.2 [subst {
   708         -    SELECT toreal(x'[swapDoubleHexBytes 8010000000000000]');
   709         -  }] {-2.2250738585072014e-308}
   710         -  do_execsql_test func4-6.3.3 [subst {
   711         -    SELECT toreal(x'[swapDoubleHexBytes c000000000000000]');
   712         -  }] {-2.0}
   713         -  do_execsql_test func4-6.3.4 [subst {
   714         -    SELECT toreal(x'[swapDoubleHexBytes bff0000000000000]');
   715         -  }] {-1.0}
   716         -  do_execsql_test func4-6.3.5 [subst {
   717         -    SELECT toreal(x'[swapDoubleHexBytes 8000000000000000]');
   718         -  }] {-0.0}
   719         -  do_execsql_test func4-6.3.6 [subst {
   720         -    SELECT toreal(x'[swapDoubleHexBytes 0000000000000000]');
   721         -  }] {0.0}
   722         -  do_execsql_test func4-6.3.7 [subst {
   723         -    SELECT toreal(x'[swapDoubleHexBytes 3ff0000000000000]');
   724         -  }] {1.0}
   725         -  do_execsql_test func4-6.3.8 [subst {
   726         -    SELECT toreal(x'[swapDoubleHexBytes 4000000000000000]');
   727         -  }] {2.0}
   728         -  do_execsql_test func4-6.3.9 [subst {
   729         -    SELECT toreal(x'[swapDoubleHexBytes 0010000000000000]');
   730         -  }] {2.2250738585072014e-308}
   731         -  do_execsql_test func4-6.3.10 [subst {
   732         -    SELECT toreal(x'[swapDoubleHexBytes 7fefffffffffffff]');
   733         -  }] {1.7976931348623157e+308}
   734         -  do_execsql_test func4-6.3.11 [subst {
   735         -    SELECT toreal(x'[swapDoubleHexBytes 8000000000000001]');
   736         -  }] {-5e-324}
   737         -  do_execsql_test func4-6.3.12 [subst {
   738         -    SELECT toreal(x'[swapDoubleHexBytes 800fffffffffffff]');
   739         -  }] {-2.225073858507201e-308}
   740         -  do_execsql_test func4-6.3.13 [subst {
   741         -    SELECT toreal(x'[swapDoubleHexBytes 0000000000000001]');
   742         -  }] {5e-324}
   743         -  do_execsql_test func4-6.3.14 [subst {
   744         -    SELECT toreal(x'[swapDoubleHexBytes 000fffffffffffff]');
   745         -  }] {2.225073858507201e-308}
   746         -  do_execsql_test func4-6.3.15 [subst {
   747         -    SELECT toreal(x'[swapDoubleHexBytes fff0000000000000]');
   748         -  }] {-Inf}
   749         -  do_execsql_test func4-6.3.16 [subst {
   750         -    SELECT toreal(x'[swapDoubleHexBytes 7ff0000000000000]');
   751         -  }] {Inf}
   752         -  do_execsql_test func4-6.3.17 [subst {
   753         -    SELECT toreal(x'[swapDoubleHexBytes fff8000000000000]');
   754         -  }] {{}}
   755         -  do_execsql_test func4-6.3.18 [subst {
   756         -    SELECT toreal(x'[swapDoubleHexBytes fff0000000000001]');
   757         -  }] {{}}
   758         -  do_execsql_test func4-6.3.19 [subst {
   759         -    SELECT toreal(x'[swapDoubleHexBytes fff7ffffffffffff]');
   760         -  }] {{}}
   761         -  do_execsql_test func4-6.3.20 [subst {
   762         -    SELECT toreal(x'[swapDoubleHexBytes 7ff0000000000001]');
   763         -  }] {{}}
   764         -  do_execsql_test func4-6.3.21 [subst {
   765         -    SELECT toreal(x'[swapDoubleHexBytes 7ff7ffffffffffff]');
   766         -  }] {{}}
   767         -  do_execsql_test func4-6.3.22 [subst {
   768         -    SELECT toreal(x'[swapDoubleHexBytes fff8000000000001]');
   769         -  }] {{}}
   770         -  do_execsql_test func4-6.3.23 [subst {
   771         -    SELECT toreal(x'[swapDoubleHexBytes ffffffffffffffff]');
   772         -  }] {{}}
   773         -  do_execsql_test func4-6.3.24 [subst {
   774         -    SELECT toreal(x'[swapDoubleHexBytes 7ff8000000000000]');
   775         -  }] {{}}
   776         -  do_execsql_test func4-6.3.25 [subst {
   777         -    SELECT toreal(x'[swapDoubleHexBytes 7fffffffffffffff]');
   778         -  }] {{}}
          678  +  do_execsql_test func4-6.3.1 {
          679  +    SELECT toreal(x'ffefffffffffffff');
          680  +  } {-1.7976931348623157e+308}
          681  +  do_execsql_test func4-6.3.2 {
          682  +    SELECT toreal(x'8010000000000000');
          683  +  } {-2.2250738585072014e-308}
          684  +  do_execsql_test func4-6.3.3 {
          685  +    SELECT toreal(x'c000000000000000');
          686  +  } {-2.0}
          687  +  do_execsql_test func4-6.3.4 {
          688  +    SELECT toreal(x'bff0000000000000');
          689  +  } {-1.0}
          690  +  do_execsql_test func4-6.3.5 {
          691  +    SELECT toreal(x'8000000000000000');
          692  +  } {-0.0}
          693  +  do_execsql_test func4-6.3.6 {
          694  +    SELECT toreal(x'0000000000000000');
          695  +  } {0.0}
          696  +  do_execsql_test func4-6.3.7 {
          697  +    SELECT toreal(x'3ff0000000000000');
          698  +  } {1.0}
          699  +  do_execsql_test func4-6.3.8 {
          700  +    SELECT toreal(x'4000000000000000');
          701  +  } {2.0}
          702  +  do_execsql_test func4-6.3.9 {
          703  +    SELECT toreal(x'0010000000000000');
          704  +  } {2.2250738585072014e-308}
          705  +  do_execsql_test func4-6.3.10 {
          706  +    SELECT toreal(x'7fefffffffffffff');
          707  +  } {1.7976931348623157e+308}
          708  +  do_execsql_test func4-6.3.11 {
          709  +    SELECT toreal(x'8000000000000001');
          710  +  } {-5e-324}
          711  +  do_execsql_test func4-6.3.12 {
          712  +    SELECT toreal(x'800fffffffffffff');
          713  +  } {-2.225073858507201e-308}
          714  +  do_execsql_test func4-6.3.13 {
          715  +    SELECT toreal(x'0000000000000001');
          716  +  } {5e-324}
          717  +  do_execsql_test func4-6.3.14 {
          718  +    SELECT toreal(x'000fffffffffffff');
          719  +  } {2.225073858507201e-308}
          720  +  do_execsql_test func4-6.3.15 {
          721  +    SELECT toreal(x'fff0000000000000');
          722  +  } {-Inf}
          723  +  do_execsql_test func4-6.3.16 {
          724  +    SELECT toreal(x'7ff0000000000000');
          725  +  } {Inf}
          726  +  do_execsql_test func4-6.3.17 {
          727  +    SELECT toreal(x'fff8000000000000');
          728  +  } {{}}
          729  +  do_execsql_test func4-6.3.18 {
          730  +    SELECT toreal(x'fff0000000000001');
          731  +  } {{}}
          732  +  do_execsql_test func4-6.3.19 {
          733  +    SELECT toreal(x'fff7ffffffffffff');
          734  +  } {{}}
          735  +  do_execsql_test func4-6.3.20 {
          736  +    SELECT toreal(x'7ff0000000000001');
          737  +  } {{}}
          738  +  do_execsql_test func4-6.3.21 {
          739  +    SELECT toreal(x'7ff7ffffffffffff');
          740  +  } {{}}
          741  +  do_execsql_test func4-6.3.22 {
          742  +    SELECT toreal(x'fff8000000000001');
          743  +  } {{}}
          744  +  do_execsql_test func4-6.3.23 {
          745  +    SELECT toreal(x'ffffffffffffffff');
          746  +  } {{}}
          747  +  do_execsql_test func4-6.3.24 {
          748  +    SELECT toreal(x'7ff8000000000000');
          749  +  } {{}}
          750  +  do_execsql_test func4-6.3.25 {
          751  +    SELECT toreal(x'7fffffffffffffff');
          752  +  } {{}}
   779    753   }
   780    754   
   781    755   set tcl_precision $saved_tcl_precision
   782    756   unset saved_tcl_precision
   783    757   finish_test