wasCSharpSQLite – Rev
?pathlinks?
using System.Diagnostics;
using System.IO;
using System.Text;
namespace Community.CsharpSqlite
{
#if TCLSH
using tcl.lang;
using Tcl_Interp = tcl.lang.Interp;
using Tcl_Obj = tcl.lang.TclObject;
public partial class Sqlite3
{
/*
** 2007 April 6
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces. This code
** implements TCL commands for reading and writing the binary
** database files and displaying the content of those files as
** hexadecimal. We could, _in theory, use the built-_in "binary"
** command of TCL to do a lot of this, but there are some issues
** with historical versions of the "binary" command. So it seems
** easier and safer to build our own mechanism.
*************************************************************************
** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
** C#-SQLite is an independent reimplementation of the SQLite software library
**
** SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e
**
*************************************************************************
*/
//#include "sqliteInt.h"
//#include "tcl.h"
//#include <stdlib.h>
//#include <string.h>
//#include <assert.h>
/*
** Convert binary to hex. The input zBuf[] contains N bytes of
** binary data. zBuf[] is 2*n+1 bytes long. Overwrite zBuf[]
** with a hexadecimal representation of its original binary input.
*/
static void sqlite3TestBinToHex( byte[] zBuf, int N )
{
StringBuilder zHex = new StringBuilder( "0123456789ABCDEF" );
int i, j;
byte c;
i = N * 2;
zBuf[i--] = 0;
for ( j = N - 1; j >= 0; j-- )
{
c = zBuf[j];
zBuf[i--] = (byte)zHex[c & 0xf];
zBuf[i--] = (byte)zHex[c >> 4];
}
Debug.Assert( i == -1 );
}
/*
** Convert hex to binary. The input zIn[] contains N bytes of
** hexadecimal. Convert this into binary and write aOut[] with
** the binary data. Spaces _in the original input are ignored.
** Return the number of bytes of binary rendered.
*/
static int sqlite3TestHexToBin( string zIn, int N, byte[] aOut )
{
int[] aMap = new int[] {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0, 0, 0, 0, 0, 0,
0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
int i, j;
int hi = 1;
int c;
for ( i = j = 0; i < N; i++ )
{
c = aMap[zIn[i]];
if ( c == 0 )
continue;
if ( hi != 0 )
{
aOut[j] = (byte)( ( c - 1 ) << 4 );
hi = 0;
}
else
{
aOut[j++] |= (byte)( c - 1 );
hi = 1;
}
}
return j;
}
/*
** Usage: hexio_read FILENAME OFFSET AMT
**
** Read AMT bytes from file FILENAME beginning at OFFSET from the
** beginning of the file. Convert that information to hexadecimal
** and return the resulting HEX string.
*/
static int hexio_read(
object clientdata,
Tcl_Interp interp,
int objc,
Tcl_Obj[] objv
)
{
int offset = 0;
int amt = 0, got;
string zFile;
byte[] zBuf;
FileStream _in;
if ( objc != 4 )
{
TCL.Tcl_WrongNumArgs( interp, 1, objv, "FILENAME OFFSET AMT" );
return TCL.TCL_ERROR;
}
if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out offset ) )
return TCL.TCL_ERROR;
if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[3], out amt ) )
return TCL.TCL_ERROR;
zFile = TCL.Tcl_GetString( objv[1] );
zBuf = new byte[amt * 2 + 1];// sqlite3Malloc( amt * 2 + 1 );
if ( zBuf == null )
{
return TCL.TCL_ERROR;
}
_in = new FileStream( zFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite );
//if( _in==null){
// _in = fopen(zFile, "r");
//}
if ( _in == null )
{
TCL.Tcl_AppendResult( interp, "cannot open input file ", zFile );
return TCL.TCL_ERROR;
}
_in.Seek( offset, SeekOrigin.Begin ); //fseek(_in, offset, SEEK_SET);
got = _in.Read( zBuf, 0, amt ); // got = fread( zBuf, 1, amt, _in );
_in.Flush();
_in.Close();// fclose( _in );
if ( got < 0 )
{
got = 0;
}
sqlite3TestBinToHex( zBuf, got );
TCL.Tcl_AppendResult( interp, System.Text.Encoding.UTF8.GetString( zBuf, 0, zBuf.Length ).Substring( 0, got * 2 ) );
zBuf = null;// sqlite3DbFree( db, ref zBuf );
return TCL.TCL_OK;
}
/*
** Usage: hexio_write FILENAME OFFSET DATA
**
** Write DATA into file FILENAME beginning at OFFSET from the
** beginning of the file. DATA is expressed _in hexadecimal.
*/
static int hexio_write(
object clientdata,
Tcl_Interp interp,
int objc,
Tcl_Obj[] objv
)
{
int offset = 0;
int nIn = 0, nOut, written;
string zFile;
string zIn;
byte[] aOut;
FileStream _out;
if ( objc != 4 )
{
TCL.Tcl_WrongNumArgs( interp, 1, objv, "FILENAME OFFSET HEXDATA" );
return TCL.TCL_ERROR;
}
if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], out offset ) )
return TCL.TCL_ERROR;
zFile = TCL.Tcl_GetString( objv[1] );
zIn = TCL.Tcl_GetStringFromObj( objv[3], out nIn );
aOut = new byte[nIn / 2 + 1];//sqlite3Malloc( nIn/2 );
if ( aOut == null )
{
return TCL.TCL_ERROR;
}
nOut = sqlite3TestHexToBin( zIn, nIn, aOut );
_out = new FileStream( zFile, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite );// fopen( zFile, "r+b" );
//if( _out==0 ){
// _out = fopen(zFile, "r+");
//}
if ( _out == null )
{
TCL.Tcl_AppendResult( interp, "cannot open output file ", zFile );
return TCL.TCL_ERROR;
}
_out.Seek( offset, SeekOrigin.Begin );// fseek( _out, offset, SEEK_SET );
written = (int)_out.Position;
_out.Write( aOut, 0, nOut );// written = fwrite( aOut, 1, nOut, _out );
written = (int)_out.Position - written;
aOut = null;// sqlite3DbFree( db, ref aOut );
_out.Flush();
_out.Close();// fclose( _out );
TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( written ) );
return TCL.TCL_OK;
}
/*
** USAGE: hexio_get_int HEXDATA
**
** Interpret the HEXDATA argument as a big-endian integer. Return
** the value of that integer. HEXDATA can contain between 2 and 8
** hexadecimal digits.
*/
static int hexio_get_int(
object clientdata,
Tcl_Interp interp,
int objc,
Tcl_Obj[] objv
)
{
int val;
int nIn = 0, nOut;
string zIn;
byte[] aOut;
byte[] aNum = new byte[4];
if ( objc != 2 )
{
TCL.Tcl_WrongNumArgs( interp, 1, objv, "HEXDATA" );
return TCL.TCL_ERROR;
}
zIn = TCL.Tcl_GetStringFromObj( objv[1], out nIn );
aOut = new byte[nIn / 2];// sqlite3Malloc( nIn / 2 );
if ( aOut == null )
{
return TCL.TCL_ERROR;
}
nOut = sqlite3TestHexToBin( zIn, nIn, aOut );
if ( nOut >= 4 )
{
aNum[0] = aOut[0]; // memcpy( aNum, aOut, 4 );
aNum[1] = aOut[1];
aNum[2] = aOut[2];
aNum[3] = aOut[3];
}
else
{
//memset(aNum, 0, sizeof(aNum));
//memcpy(&aNum[4-nOut], aOut, nOut);
aNum[4 - nOut] = aOut[0];
if ( nOut > 1 )
aNum[4 - nOut + 1] = aOut[1];
if ( nOut > 2 )
aNum[4 - nOut + 2] = aOut[2];
if ( nOut > 3 )
aNum[4 - nOut + 3] = aOut[3];
}
aOut = null;// sqlite3DbFree( db, ref aOut );
val = ( aNum[0] << 24 ) | ( aNum[1] << 16 ) | ( aNum[2] << 8 ) | aNum[3];
TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( val ) );
return TCL.TCL_OK;
}
/*
** USAGE: hexio_render_int16 INTEGER
**
** Render INTEGER has a 16-bit big-endian integer _in hexadecimal.
*/
static int hexio_render_int16(
object clientdata,
Tcl_Interp interp,
int objc,
Tcl_Obj[] objv
)
{
int val = 0;
byte[] aNum = new byte[10];
if ( objc != 2 )
{
TCL.Tcl_WrongNumArgs( interp, 1, objv, "INTEGER" );
return TCL.TCL_ERROR;
}
if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out val ) )
return TCL.TCL_ERROR;
aNum[0] = (byte)( val >> 8 );
aNum[1] = (byte)val;
sqlite3TestBinToHex( aNum, 2 );
TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewStringObj( aNum, 4 ) );
return TCL.TCL_OK;
}
/*
** USAGE: hexio_render_int32 INTEGER
**
** Render INTEGER has a 32-bit big-endian integer _in hexadecimal.
*/
static int hexio_render_int32(
object clientdata,
Tcl_Interp interp,
int objc,
Tcl_Obj[] objv
)
{
int val = 0;
byte[] aNum = new byte[10];
if ( objc != 2 )
{
TCL.Tcl_WrongNumArgs( interp, 1, objv, "INTEGER" );
return TCL.TCL_ERROR;
}
if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out val ) )
return TCL.TCL_ERROR;
aNum[0] = (byte)( val >> 24 );
aNum[1] = (byte)( val >> 16 );
aNum[2] = (byte)( val >> 8 );
aNum[3] = (byte)val;
sqlite3TestBinToHex( aNum, 4 );
TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewStringObj( aNum, 8 ) );
return TCL.TCL_OK;
}
/*
** USAGE: utf8_to_utf8 HEX
**
** The argument is a UTF8 string represented _in hexadecimal.
** The UTF8 might not be well-formed. Run this string through
** sqlite3Utf8to8() convert it back to hex and return the result.
*/
static int utf8_to_utf8(
object clientdata,
Tcl_Interp interp,
int objc,
Tcl_Obj[] objv
){
#if SQLITE_DEBUG
int n = 0;
int nOut;
string zOrig;
byte[] z;
if( objc!=2 ){
TCL.Tcl_WrongNumArgs(interp, 1, objv, "HEX");
return TCL.TCL_ERROR;
}
zOrig = TCL.Tcl_GetStringFromObj(objv[1], out n);
z = new byte[2 * n + 1];//sqlite3Malloc( n + 3 );
nOut = sqlite3TestHexToBin( zOrig, n, z );
//z[n] = 0;
nOut = sqlite3Utf8To8(z);
sqlite3TestBinToHex( z, zOrig.Length );
TCL.Tcl_AppendResult(interp, Encoding.ASCII.GetString(z,0,n));
//sqlite3_free( z );
return TCL.TCL_OK;
#else
Tcl_AppendResult(interp,
"[utf8_to_utf8] unavailable - SQLITE_DEBUG not defined", 0
);
return TCL.TCL_ERROR;
#endif
}
//static int getFts3Varint(string p, sqlite_int64 *v){
// const unsigned char *q = (const unsigned char ) p;
// sqlite_uint64 x = 0, y = 1;
// while( (*q & 0x80) == 0x80 ){
// x += y * (*q++ & 0x7f);
// y <<= 7;
// }
// x += y * (*q++);
// *v = (sqlite_int64) x;
// return (int) (q - (unsigned char )p);
//}
///*
//** USAGE: read_fts3varint BLOB VARNAME
//**
//** Read a varint from the start of BLOB. Set variable VARNAME to contain
//** the interpreted value. Return the number of bytes of BLOB consumed.
//*/
//static int read_fts3varint(
// void * clientData,
// Tcl_Interp interp,
// int objc,
// Tcl_Obj[] objv
//){
// int nBlob;
// unsigned string zBlob;
// sqlite3_int64 iVal;
// int nVal;
// if( objc!=3 ){
// Tcl_WrongNumArgs(interp, 1, objv, "BLOB VARNAME");
// return TCL.TCL_ERROR;
// }
// zBlob = TCL.Tcl_GetByteArrayFromObj(objv[1], &nBlob);
// nVal = getFts3Varint((char)zBlob, (sqlite3_int64 )(&iVal));
// Tcl_ObjSetVar2(interp, objv[2], 0, TCL.TCL_NewWideIntObj(iVal), 0);
// Tcl_SetObjResult(interp, TCL.TCL_NewIntObj(nVal));
// return TCL.TCL_OK;
//}
/*
** Register commands with the TCL interpreter.
*/
static public int Sqlitetest_hexio_Init( Tcl_Interp interp )
{
//static struct {
// string zName;
// Tcl_ObjCmdProc *xProc;
//}
_aObjCmd[] aObjCmd = new _aObjCmd[] {
new _aObjCmd( "hexio_read", hexio_read ),
new _aObjCmd( "hexio_write", hexio_write ),
new _aObjCmd( "hexio_get_int", hexio_get_int ),
new _aObjCmd( "hexio_render_int16", hexio_render_int16 ),
new _aObjCmd( "hexio_render_int32", hexio_render_int32 ),
new _aObjCmd( "utf8_to_utf8", utf8_to_utf8 ),
// { "read_fts3varint", read_fts3varint },
};
int i;
for ( i = 0; i < aObjCmd.Length; i++ )
{
TCL.Tcl_CreateObjCommand( interp, aObjCmd[i].zName, aObjCmd[i].xProc, null, null );
}
return TCL.TCL_OK;
}
}
#endif
}