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