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