persistentstorage/sqlite3api/TEST/SRC/test_hexio.c
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 /*
       
     2 ** 2007 April 6
       
     3 **
       
     4 ** Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
       
     5 **
       
     6 ** The author disclaims copyright to this source code.  In place of
       
     7 ** a legal notice, here is a blessing:
       
     8 **
       
     9 **    May you do good and not evil.
       
    10 **    May you find forgiveness for yourself and forgive others.
       
    11 **    May you share freely, never taking more than you give.
       
    12 **
       
    13 *************************************************************************
       
    14 ** Code for testing all sorts of SQLite interfaces.  This code
       
    15 ** implements TCL commands for reading and writing the binary
       
    16 ** database files and displaying the content of those files as
       
    17 ** hexadecimal.  We could, in theory, use the built-in "binary"
       
    18 ** command of TCL to do a lot of this, but there are some issues
       
    19 ** with historical versions of the "binary" command.  So it seems
       
    20 ** easier and safer to build our own mechanism.
       
    21 **
       
    22 ** $Id: test_hexio.c,v 1.7 2008/05/12 16:17:42 drh Exp $
       
    23 */
       
    24 #include "sqliteInt.h"
       
    25 #include "tcl.h"
       
    26 #include <stdlib.h>
       
    27 #include <string.h>
       
    28 #include <assert.h>
       
    29 #include <unistd.h>
       
    30 #include <sys/param.h>
       
    31 
       
    32 extern char* FullFilePath(char* aPath, const char* aFileName);
       
    33 
       
    34 /* Symbian OS - often TCL scripts attempt to open a file just using the file name without path.
       
    35    This is not working on the hardware. The function bellow will contstruct the full file name. */
       
    36 extern char* GetFullFilePath(char* aPath, const char* aFileName)
       
    37 	{
       
    38 	return FullFilePath(aPath, aFileName);
       
    39 	}
       
    40 
       
    41 /*
       
    42 ** Convert binary to hex.  The input zBuf[] contains N bytes of
       
    43 ** binary data.  zBuf[] is 2*n+1 bytes long.  Overwrite zBuf[]
       
    44 ** with a hexadecimal representation of its original binary input.
       
    45 */
       
    46 void sqlite3TestBinToHex(unsigned char *zBuf, int N){
       
    47   const unsigned char zHex[] = "0123456789ABCDEF";
       
    48   int i, j;
       
    49   unsigned char c;
       
    50   i = N*2;
       
    51   zBuf[i--] = 0;
       
    52   for(j=N-1; j>=0; j--){
       
    53     c = zBuf[j];
       
    54     zBuf[i--] = zHex[c&0xf];
       
    55     zBuf[i--] = zHex[c>>4];
       
    56   }
       
    57   assert( i==-1 );
       
    58 }
       
    59 
       
    60 /*
       
    61 ** Convert hex to binary.  The input zIn[] contains N bytes of
       
    62 ** hexadecimal.  Convert this into binary and write aOut[] with
       
    63 ** the binary data.  Spaces in the original input are ignored.
       
    64 ** Return the number of bytes of binary rendered.
       
    65 */
       
    66 int sqlite3TestHexToBin(const unsigned char *zIn, int N, unsigned char *aOut){
       
    67   const unsigned char aMap[] = {
       
    68      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    69      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    70      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    71      1, 2, 3, 4, 5, 6, 7, 8,  9,10, 0, 0, 0, 0, 0, 0,
       
    72      0,11,12,13,14,15,16, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    73      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    74      0,11,12,13,14,15,16, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    75      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    76      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    77      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    78      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    79      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    80      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    81      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    82      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    83      0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
       
    84   };
       
    85   int i, j;
       
    86   int hi=1;
       
    87   unsigned char c;
       
    88 
       
    89   for(i=j=0; i<N; i++){
       
    90     c = aMap[zIn[i]];
       
    91     if( c==0 ) continue;
       
    92     if( hi ){
       
    93       aOut[j] = (c-1)<<4;
       
    94       hi = 0;
       
    95     }else{
       
    96       aOut[j++] |= c-1;
       
    97       hi = 1;
       
    98     }
       
    99   }
       
   100   return j;
       
   101 }
       
   102 
       
   103 
       
   104 /*
       
   105 ** Usage:   hexio_read  FILENAME  OFFSET  AMT
       
   106 **
       
   107 ** Read AMT bytes from file FILENAME beginning at OFFSET from the
       
   108 ** beginning of the file.  Convert that information to hexadecimal
       
   109 ** and return the resulting HEX string.
       
   110 */
       
   111 static int hexio_read(
       
   112   void * clientData,
       
   113   Tcl_Interp *interp,
       
   114   int objc,
       
   115   Tcl_Obj *CONST objv[]
       
   116 ){
       
   117   int offset;
       
   118   int amt, got;
       
   119   const char *zFile;
       
   120   unsigned char *zBuf;
       
   121   FILE *in;
       
   122   char fnamebuf[MAXPATHLEN + 1];
       
   123 
       
   124   if( objc!=4 ){
       
   125     Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET AMT");
       
   126     return TCL_ERROR;
       
   127   }
       
   128   if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
       
   129   if( Tcl_GetIntFromObj(interp, objv[3], &amt) ) return TCL_ERROR;
       
   130   zFile = Tcl_GetString(objv[1]);
       
   131   zBuf = sqlite3_malloc( amt*2+1 );
       
   132   if( zBuf==0 ){
       
   133     return TCL_ERROR;
       
   134   }
       
   135   if(GetFullFilePath(fnamebuf, zFile) == 0)
       
   136     return TCL_ERROR;
       
   137   in = fopen(fnamebuf, "rb");
       
   138   if( in==0 ){
       
   139     in = fopen(fnamebuf, "r");
       
   140   }
       
   141   if( in==0 ){
       
   142     Tcl_AppendResult(interp, "cannot open input file ", fnamebuf, 0);
       
   143     return TCL_ERROR;
       
   144   }
       
   145   fseek(in, offset, SEEK_SET);
       
   146   got = fread(zBuf, 1, amt, in);
       
   147   fclose(in);
       
   148   if( got<0 ){
       
   149     got = 0;
       
   150   }
       
   151   sqlite3TestBinToHex(zBuf, got);
       
   152   Tcl_AppendResult(interp, zBuf, 0);
       
   153   sqlite3_free(zBuf);
       
   154   return TCL_OK;
       
   155 }
       
   156 
       
   157 
       
   158 /*
       
   159 ** Usage:   hexio_write  FILENAME  OFFSET  DATA
       
   160 **
       
   161 ** Write DATA into file FILENAME beginning at OFFSET from the
       
   162 ** beginning of the file.  DATA is expressed in hexadecimal.
       
   163 */
       
   164 static int hexio_write(
       
   165   void * clientData,
       
   166   Tcl_Interp *interp,
       
   167   int objc,
       
   168   Tcl_Obj *CONST objv[]
       
   169 ){
       
   170   int offset;
       
   171   int nIn, nOut, written;
       
   172   const char *zFile;
       
   173   const unsigned char *zIn;
       
   174   unsigned char *aOut;
       
   175   FILE *out;
       
   176   char fnamebuf[MAXPATHLEN + 1];
       
   177 
       
   178   if( objc!=4 ){
       
   179     Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET HEXDATA");
       
   180     return TCL_ERROR;
       
   181   }
       
   182   if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
       
   183   zFile = Tcl_GetString(objv[1]);
       
   184   zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn);
       
   185   aOut = sqlite3_malloc( nIn/2 );
       
   186   if( aOut==0 ){
       
   187     return TCL_ERROR;
       
   188   }
       
   189   nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
       
   190   if(GetFullFilePath(fnamebuf, zFile) == 0)
       
   191     return TCL_ERROR;
       
   192   out = fopen(fnamebuf, "r+b");
       
   193   if( out==0 ){
       
   194     out = fopen(fnamebuf, "r+");
       
   195   }
       
   196   if( out==0 ){
       
   197     Tcl_AppendResult(interp, "cannot open output file ", fnamebuf, 0);
       
   198     return TCL_ERROR;
       
   199   }
       
   200   fseek(out, offset, SEEK_SET);
       
   201   written = fwrite(aOut, 1, nOut, out);
       
   202   sqlite3_free(aOut);
       
   203   fclose(out);
       
   204   Tcl_SetObjResult(interp, Tcl_NewIntObj(written));
       
   205   return TCL_OK;
       
   206 }
       
   207 
       
   208 /*
       
   209 ** USAGE:   hexio_get_int   HEXDATA
       
   210 **
       
   211 ** Interpret the HEXDATA argument as a big-endian integer.  Return
       
   212 ** the value of that integer.  HEXDATA can contain between 2 and 8
       
   213 ** hexadecimal digits.
       
   214 */
       
   215 static int hexio_get_int(
       
   216   void * clientData,
       
   217   Tcl_Interp *interp,
       
   218   int objc,
       
   219   Tcl_Obj *CONST objv[]
       
   220 ){
       
   221   int val;
       
   222   int nIn, nOut;
       
   223   const unsigned char *zIn;
       
   224   unsigned char *aOut;
       
   225   unsigned char aNum[4];
       
   226 
       
   227   if( objc!=2 ){
       
   228     Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA");
       
   229     return TCL_ERROR;
       
   230   }
       
   231   zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
       
   232   aOut = sqlite3_malloc( nIn/2 );
       
   233   if( aOut==0 ){
       
   234     return TCL_ERROR;
       
   235   }
       
   236   nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
       
   237   if( nOut>=4 ){
       
   238     memcpy(aNum, aOut, 4);
       
   239   }else{
       
   240     memset(aNum, 0, sizeof(aNum));
       
   241     memcpy(&aNum[4-nOut], aOut, nOut);
       
   242   }
       
   243   sqlite3_free(aOut);
       
   244   val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
       
   245   Tcl_SetObjResult(interp, Tcl_NewIntObj(val));
       
   246   return TCL_OK;
       
   247 }
       
   248 
       
   249 
       
   250 /*
       
   251 ** USAGE:   hexio_render_int16   INTEGER
       
   252 **
       
   253 ** Render INTEGER has a 16-bit big-endian integer in hexadecimal.
       
   254 */
       
   255 static int hexio_render_int16(
       
   256   void * clientData,
       
   257   Tcl_Interp *interp,
       
   258   int objc,
       
   259   Tcl_Obj *CONST objv[]
       
   260 ){
       
   261   int val;
       
   262   unsigned char aNum[10];
       
   263 
       
   264   if( objc!=2 ){
       
   265     Tcl_WrongNumArgs(interp, 1, objv, "INTEGER");
       
   266     return TCL_ERROR;
       
   267   }
       
   268   if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR;
       
   269   aNum[0] = val>>8;
       
   270   aNum[1] = val;
       
   271   sqlite3TestBinToHex(aNum, 2);
       
   272   Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 4));
       
   273   return TCL_OK;
       
   274 }
       
   275 
       
   276 
       
   277 /*
       
   278 ** USAGE:   hexio_render_int32   INTEGER
       
   279 **
       
   280 ** Render INTEGER has a 32-bit big-endian integer in hexadecimal.
       
   281 */
       
   282 static int hexio_render_int32(
       
   283   void * clientData,
       
   284   Tcl_Interp *interp,
       
   285   int objc,
       
   286   Tcl_Obj *CONST objv[]
       
   287 ){
       
   288   int val;
       
   289   unsigned char aNum[10];
       
   290 
       
   291   if( objc!=2 ){
       
   292     Tcl_WrongNumArgs(interp, 1, objv, "INTEGER");
       
   293     return TCL_ERROR;
       
   294   }
       
   295   if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR;
       
   296   aNum[0] = val>>24;
       
   297   aNum[1] = val>>16;
       
   298   aNum[2] = val>>8;
       
   299   aNum[3] = val;
       
   300   sqlite3TestBinToHex(aNum, 4);
       
   301   Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 8));
       
   302   return TCL_OK;
       
   303 }
       
   304 
       
   305 /*
       
   306 ** USAGE:  utf8_to_utf8  HEX
       
   307 **
       
   308 ** The argument is a UTF8 string represented in hexadecimal.
       
   309 ** The UTF8 might not be well-formed.  Run this string through
       
   310 ** sqlite3Utf8to8() convert it back to hex and return the result.
       
   311 */
       
   312 static int utf8_to_utf8(
       
   313   void * clientData,
       
   314   Tcl_Interp *interp,
       
   315   int objc,
       
   316   Tcl_Obj *CONST objv[]
       
   317 ){
       
   318 #ifdef SQLITE_DEBUG
       
   319   int n;
       
   320   int nOut;
       
   321   const unsigned char *zOrig;
       
   322   unsigned char *z;
       
   323   if( objc!=2 ){
       
   324     Tcl_WrongNumArgs(interp, 1, objv, "HEX");
       
   325     return TCL_ERROR;
       
   326   }
       
   327   zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
       
   328   z = sqlite3_malloc( n+3 );
       
   329   n = sqlite3TestHexToBin(zOrig, n, z);
       
   330   z[n] = 0;
       
   331   nOut = sqlite3Utf8To8(z);
       
   332   sqlite3TestBinToHex(z,nOut);
       
   333   Tcl_AppendResult(interp, (char*)z, 0);
       
   334   sqlite3_free(z);
       
   335 #endif
       
   336   return TCL_OK;
       
   337 }
       
   338 
       
   339 
       
   340 /*
       
   341 ** Register commands with the TCL interpreter.
       
   342 */
       
   343 int Sqlitetest_hexio_Init(Tcl_Interp *interp){
       
   344   static struct {
       
   345      char *zName;
       
   346      Tcl_ObjCmdProc *xProc;
       
   347   } aObjCmd[] = {
       
   348      { "hexio_read",                   hexio_read            },
       
   349      { "hexio_write",                  hexio_write           },
       
   350      { "hexio_get_int",                hexio_get_int         },
       
   351      { "hexio_render_int16",           hexio_render_int16    },
       
   352      { "hexio_render_int32",           hexio_render_int32    },
       
   353      { "utf8_to_utf8",                 utf8_to_utf8          },
       
   354   };
       
   355   int i;
       
   356   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
       
   357     Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
       
   358   }
       
   359   return TCL_OK;
       
   360 }