xref: /sqlite-3.40.0/src/test5.c (revision df014893)
1 /*
2 ** 2001 September 15
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 the utf.c module in SQLite.  This code
13 ** is not included in the SQLite library.  It is used for automated
14 ** testing of the SQLite library. Specifically, the code in this file
15 ** is used for testing the SQLite routines for converting between
16 ** the various supported unicode encodings.
17 **
18 ** $Id: test5.c,v 1.7 2004/06/02 00:41:10 drh Exp $
19 */
20 #include "sqliteInt.h"
21 #include "os.h"         /* to get SQLITE_BIGENDIAN */
22 #include "tcl.h"
23 #include <stdlib.h>
24 #include <string.h>
25 
26 /*
27 ** Return the number of bytes up to and including the first pair of
28 ** 0x00 bytes in *pStr.
29 */
30 static int utf16_length(const unsigned char *pZ){
31   const unsigned char *pC1 = pZ;
32   const unsigned char *pC2 = pZ+1;
33   while( *pC1 || *pC2 ){
34     pC1 += 2;
35     pC2 += 2;
36   }
37   return (pC1-pZ)+2;
38 }
39 
40 /*
41 ** tclcmd:   sqlite_utf8to16le  STRING
42 ** title:    Convert STRING from utf-8 to utf-16le
43 **
44 ** Return the utf-16le encoded string
45 */
46 static int sqlite_utf8to16le(
47   void * clientData,
48   Tcl_Interp *interp,
49   int objc,
50   Tcl_Obj *CONST objv[]
51 ){
52   unsigned char *out;
53   unsigned char *in;
54   Tcl_Obj *res;
55 
56   if( objc!=2 ){
57     Tcl_AppendResult(interp, "wrong # args: should be \"",
58         Tcl_GetStringFromObj(objv[0], 0), "<utf-8 encoded-string>", 0);
59     return TCL_ERROR;
60   }
61 
62   in = Tcl_GetString(objv[1]);
63   out = (unsigned char *)sqlite3utf8to16le(in, -1);
64   res = Tcl_NewByteArrayObj(out, utf16_length(out));
65   sqliteFree(out);
66 
67   Tcl_SetObjResult(interp, res);
68 
69   return TCL_OK;
70 }
71 
72 /*
73 ** tclcmd:   sqlite_utf8to16be  STRING
74 ** title:    Convert STRING from utf-8 to utf-16be
75 **
76 ** Return the utf-16be encoded string
77 */
78 static int sqlite_utf8to16be(
79   void * clientData,
80   Tcl_Interp *interp,
81   int objc,
82   Tcl_Obj *CONST objv[]
83 ){
84   unsigned char *out;
85   unsigned char *in;
86   Tcl_Obj *res;
87 
88   if( objc!=2 ){
89     Tcl_AppendResult(interp, "wrong # args: should be \"",
90         Tcl_GetStringFromObj(objv[0], 0), "<utf-8 encoded-string>", 0);
91     return TCL_ERROR;
92   }
93 
94   in = Tcl_GetByteArrayFromObj(objv[1], 0);
95   in = Tcl_GetString(objv[1]);
96   out = (unsigned char *)sqlite3utf8to16be(in, -1);
97   res = Tcl_NewByteArrayObj(out, utf16_length(out));
98   sqliteFree(out);
99 
100   Tcl_SetObjResult(interp, res);
101 
102   return TCL_OK;
103 }
104 
105 /*
106 ** tclcmd:   sqlite_utf16to16le  STRING
107 ** title:    Convert STRING from utf-16 in native byte order to utf-16le
108 **
109 ** Return the utf-16le encoded string.  If the input string contains
110 ** a byte-order mark, then the byte order mark should override the
111 ** native byte order.
112 */
113 static int sqlite_utf16to16le(
114   void * clientData,
115   Tcl_Interp *interp,
116   int objc,
117   Tcl_Obj *CONST objv[]
118 ){
119   unsigned char *out;
120   unsigned char *in;
121   int in_len;
122   Tcl_Obj *res;
123 
124   if( objc!=2 ){
125     Tcl_AppendResult(interp, "wrong # args: should be \"",
126         Tcl_GetStringFromObj(objv[0], 0), "<utf-16 encoded-string>", 0);
127     return TCL_ERROR;
128   }
129 
130   in = Tcl_GetByteArrayFromObj(objv[1], &in_len);
131   out = (unsigned char *)sqliteMalloc(in_len);
132   memcpy(out, in, in_len);
133 
134   sqlite3utf16to16le(out, -1);
135   res = Tcl_NewByteArrayObj(out, utf16_length(out));
136   sqliteFree(out);
137 
138   Tcl_SetObjResult(interp, res);
139 
140   return TCL_OK;
141 }
142 
143 /*
144 ** tclcmd:   sqlite_utf16to16be  STRING
145 ** title:    Convert STRING from utf-16 in native byte order to utf-16be
146 **
147 ** Return the utf-16be encoded string.  If the input string contains
148 ** a byte-order mark, then the byte order mark should override the
149 ** native byte order.
150 */
151 static int sqlite_utf16to16be(
152   void * clientData,
153   Tcl_Interp *interp,
154   int objc,
155   Tcl_Obj *CONST objv[]
156 ){
157   unsigned char *out;
158   unsigned char *in;
159   int in_len;
160   Tcl_Obj *res;
161 
162   if( objc!=2 ){
163     Tcl_AppendResult(interp, "wrong # args: should be \"",
164         Tcl_GetStringFromObj(objv[0], 0), "<utf-16 encoded-string>", 0);
165     return TCL_ERROR;
166   }
167 
168   in = Tcl_GetByteArrayFromObj(objv[1], &in_len);
169   out = (unsigned char *)sqliteMalloc(in_len);
170   memcpy(out, in, in_len);
171 
172   sqlite3utf16to16be(out, -1);
173   res = Tcl_NewByteArrayObj(out, utf16_length(out));
174   sqliteFree(out);
175 
176   Tcl_SetObjResult(interp, res);
177 
178   return TCL_OK;
179 }
180 
181 /*
182 ** tclcmd:   sqlite_utf16to8  STRING
183 ** title:    Convert STRING from utf-16 in native byte order to utf-8
184 **
185 ** Return the utf-8 encoded string.  If the input string contains
186 ** a byte-order mark, then the byte order mark should override the
187 ** native byte order.
188 */
189 static int sqlite_utf16to8(
190   void * clientData,
191   Tcl_Interp *interp,
192   int objc,
193   Tcl_Obj *CONST objv[]
194 ){
195   unsigned char *out;
196   unsigned char *in;
197   Tcl_Obj *res;
198 
199   if( objc!=2 ){
200     Tcl_AppendResult(interp, "wrong # args: should be \"",
201         Tcl_GetStringFromObj(objv[0], 0), " <utf-16 encoded-string>", 0);
202     return TCL_ERROR;
203   }
204 
205   in = Tcl_GetByteArrayFromObj(objv[1], 0);
206   out = sqlite3utf16to8(in, -1, SQLITE_BIGENDIAN);
207   res = Tcl_NewByteArrayObj(out, strlen(out)+1);
208   sqliteFree(out);
209 
210   Tcl_SetObjResult(interp, res);
211 
212   return TCL_OK;
213 }
214 
215 /*
216 ** The first argument is a TCL UTF-8 string. Return the byte array
217 ** object with the encoded representation of the string, including
218 ** the NULL terminator.
219 */
220 static int binarize(
221   void * clientData,
222   Tcl_Interp *interp,
223   int objc,
224   Tcl_Obj *CONST objv[]
225 ){
226   int len;
227   char *bytes;
228   Tcl_Obj *pRet;
229   assert(objc==2);
230 
231   bytes = Tcl_GetStringFromObj(objv[1], &len);
232   pRet = Tcl_NewByteArrayObj(bytes, len+1);
233   Tcl_SetObjResult(interp, pRet);
234   return TCL_OK;
235 }
236 
237 
238 /*
239 ** Register commands with the TCL interpreter.
240 */
241 int Sqlitetest5_Init(Tcl_Interp *interp){
242   static struct {
243     char *zName;
244     Tcl_ObjCmdProc *xProc;
245   } aCmd[] = {
246     { "sqlite_utf16to8",         (Tcl_ObjCmdProc*)sqlite_utf16to8    },
247     { "sqlite_utf8to16le",       (Tcl_ObjCmdProc*)sqlite_utf8to16le  },
248     { "sqlite_utf8to16be",       (Tcl_ObjCmdProc*)sqlite_utf8to16be  },
249     { "sqlite_utf16to16le",      (Tcl_ObjCmdProc*)sqlite_utf16to16le },
250     { "sqlite_utf16to16be",      (Tcl_ObjCmdProc*)sqlite_utf16to16be },
251     { "binarize",                (Tcl_ObjCmdProc*)binarize }
252   };
253   int i;
254   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
255     Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
256   }
257 
258   return TCL_OK;
259 }
260