source: trunk/lang/tcl/src/RpEncodeTclInterface.cc @ 1042

Last change on this file since 1042 was 1042, checked in by mmc, 15 years ago

Fixed the Rappture::encoding::encode and decode operations to honor "--".
This is handy when the string may start with a dash, as in:

Rappture::encoding::encode -- -hi

Fixed the library.tcl code to guard against encode/decode problem by
using the "--" in front of strings obtained from the xml.

Cleaned up the tests for the Rappture::LibraryObj? class. Everything
works properly now, except for units. Some of the tests are failing
because the units code reports "length" instead of "area" (test finds
this problem). This should be fixed in the units code.

File size: 11.8 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::encoding
4 *
5 *  The encoding module for rappture used to zip and b64 encode data.
6 * ======================================================================
7 *  AUTHOR:  Derrick Kearney, Purdue University
8 *  Copyright (c) 2004-2007  Purdue Research Foundation
9 *
10 *  See the file "license.terms" for information on usage and
11 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 * ======================================================================
13 */
14#include <tcl.h>
15#include "RpEncode.h"
16
17extern "C" Tcl_AppInitProc RpEncoding_Init;
18
19static Tcl_ObjCmdProc RpTclEncodingIs;
20static Tcl_ObjCmdProc RpTclEncodingEncode;
21static Tcl_ObjCmdProc RpTclEncodingDecode;
22
23/**********************************************************************/
24// FUNCTION: RpEncoding_Init()
25/// Initializes the Rappture Encoding module and commands defined below
26/**
27 * Called in RapptureGUI_Init() to initialize the Rappture Units module.
28 * Initialized commands include:
29 * ::Rappture::encoding::is
30 * ::Rappture::encoding::encode
31 * ::Rappture::encoding::decode
32 */
33
34int
35RpEncoding_Init(Tcl_Interp *interp)
36{
37
38    Tcl_CreateObjCommand(interp, "::Rappture::encoding::is",
39        RpTclEncodingIs, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
40
41    Tcl_CreateObjCommand(interp, "::Rappture::encoding::encode",
42        RpTclEncodingEncode, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
43
44    Tcl_CreateObjCommand(interp, "::Rappture::encoding::decode",
45        RpTclEncodingDecode, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
46
47    return TCL_OK;
48}
49
50/**********************************************************************/
51// FUNCTION: RpTclEncodingIs()
52/// Rappture::encoding::is checks to see if given string is binary.
53/**
54 * Checks to see <string> is binary
55 * Full function call:
56 * ::Rappture::encoding::is binary <string>
57 *
58 */
59
60static int
61RpTclEncodingIs (ClientData cdata, Tcl_Interp *interp,
62    int objc, Tcl_Obj *const objv[])
63{
64    Tcl_ResetResult(interp);
65
66    // parse through command line options
67    if (objc != 3) {
68        Tcl_AppendResult(interp,
69            "wrong # args: should be \"",
70            Tcl_GetString(objv[0])," binary <string>\"",
71            (char*)NULL);
72        return TCL_ERROR;
73    }
74
75    const char *type = Tcl_GetString(objv[1]);
76
77    int bufLen;
78    const char *buf = (const char*) Tcl_GetByteArrayFromObj(objv[2],&bufLen);
79
80    if (strcmp(type,"binary") == 0) {
81        if (Rappture::encoding::isbinary(buf,bufLen) != 0) {
82            // non-ascii character found, return yes
83            Tcl_AppendResult(interp, "yes", (char*)NULL);
84        } else {
85            Tcl_AppendResult(interp, "no",(char*)NULL);
86        }
87        return TCL_OK;
88    }
89    Tcl_AppendResult(interp, "bad option \"", type,
90            "\": should be binary",
91            (char*)NULL);
92    return TCL_ERROR;
93}
94
95/**********************************************************************/
96// FUNCTION: RpTclEncodingEncode()
97/// Rappture::encoding::encode function in Tcl, encodes provided string
98/**
99 * Encode a string by compressing it with zlib and then base64 encoding it.
100 * If binary data is provided, the data is compressed and base64 encoded.
101 * RpTclEncodingIs is used to qualify binary data.
102 *
103 * If the -as option is not set, zlib compression and base64 encoding
104 * is performed by default
105 *
106 * Full function call:
107 * ::Rappture::encoding::encode ?-as z|b64|zb64? ?-no-header? <string>
108 */
109
110static int
111RpTclEncodingEncode (   ClientData cdata,
112                        Tcl_Interp *interp,
113                        int objc,
114                        Tcl_Obj *const objv[]  )
115{
116
117    const char* encodeType    = NULL; // name of the units provided by user
118    const char* option        = NULL;
119    const char* cmdName       = NULL;
120    Rappture::Buffer buf; // name of the units provided by user
121    Rappture::Outcome err;
122
123    int optionLen             = 0;
124    int typeLen               = 0;
125    int nextarg               = 0; // start parsing using the '2'th argument
126
127    int compress              = 1;
128    int base64                = 1;
129    int addHeader             = 1;
130    int flags                 = 0;
131
132    Tcl_Obj *result           = NULL;
133
134    Tcl_ResetResult(interp);
135
136    cmdName = Tcl_GetString(objv[nextarg++]);
137
138    // parse through command line options
139    if (objc < 1) {
140        Tcl_AppendResult(interp,
141                "wrong # args: should be \"", cmdName,
142                " ?-as z|b64|zb64? ?-no-header? ?--? <string>\"", (char*)NULL);
143        return TCL_ERROR;
144    }
145
146    while ((objc - nextarg) > 0) {
147        option = Tcl_GetStringFromObj(objv[nextarg], &optionLen);
148        if (*option == '-') {
149            if ( strncmp(option,"-as",optionLen) == 0 ) {
150                nextarg++;
151                typeLen = 0;
152                if (nextarg < objc) {
153                    encodeType = Tcl_GetStringFromObj(objv[nextarg],&typeLen);
154                    nextarg++;
155                }
156                if (        (typeLen == 1) &&
157                            (strncmp(encodeType,"z",typeLen) == 0) ) {
158                    compress = 1;
159                    base64 = 0;
160                }
161                else if (   (typeLen == 3) &&
162                            (strncmp(encodeType,"b64",typeLen) == 0) ) {
163                    compress = 0;
164                    base64 = 1;
165                }
166                else if (   (typeLen == 4) &&
167                            (strncmp(encodeType,"zb64",typeLen) == 0) ) {
168                    compress = 1;
169                    base64 = 1;
170                }
171                else {
172                    // user did not specify recognized wishes for this option,
173                    Tcl_AppendResult(interp, "bad value \"",(char*)NULL);
174                    if (encodeType != NULL) {
175                        Tcl_AppendResult(interp, encodeType,(char*)NULL);
176                    }
177                    Tcl_AppendResult(interp,
178                            "\": should be one of z, b64, zb64",
179                            (char*)NULL);
180                    return TCL_ERROR;
181                }
182            }
183            else if ( strncmp(option,"-no-header",optionLen) == 0 ) {
184                nextarg++;
185                addHeader = 0;
186            }
187            else if ( strcmp(option,"--") == 0 ) {
188                nextarg++;
189                break;
190            }
191            else {
192                Tcl_AppendResult(interp,
193                    "bad option \"", option,
194                    "\": should be -as, -no-header, --", (char*)NULL);
195                return TCL_ERROR;
196            }
197        }
198        else {
199            break;
200        }
201    }
202
203    if ((objc - nextarg) != 1) {
204        Tcl_AppendResult(interp,
205                "wrong # args: should be \"", cmdName,
206                " ?-as z|b64|zb64? ?-no-header? ?--? <string>\"", (char*)NULL);
207        return TCL_ERROR;
208    }
209
210    option = (const char*) Tcl_GetByteArrayFromObj(objv[nextarg++], &optionLen);
211    buf = Rappture::Buffer(option,optionLen);
212
213    if (compress == 1) {
214        flags = flags | RPENC_Z;
215    }
216    if (base64 == 1) {
217        flags = flags | RPENC_B64;
218    }
219    if (addHeader == 1) {
220        flags = flags | RPENC_HDR;
221    }
222
223    err &= Rappture::encoding::encode(buf,flags);
224
225    if (!err) {
226        result = Tcl_NewByteArrayObj(
227            (const unsigned char*)buf.bytes(), buf.size());
228        Tcl_SetObjResult(interp, result);
229    }
230    else {
231        result = Tcl_GetObjResult(interp);
232        Tcl_AppendStringsToObj( result, err.remark().c_str(),
233                                "\n", err.context().c_str(), NULL   );
234    }
235    return TCL_OK;
236}
237
238/**********************************************************************/
239// FUNCTION: RpTclEncodingDecode()
240/// Rappture::encoding::decode function in Tcl, decodes provided string
241/**
242 * Decode a string by uncompressing it with zlib and base64 decoding it.
243 * If binary data is provided, the data is base64 decoded and uncompressed.
244 * RpTclEncodingIs is used to qualify binary data.
245 *
246 * Full function call:
247 * ::Rappture::encoding::decode ?-as z|b64|zb64? <string>
248 */
249
250static int
251RpTclEncodingDecode (   ClientData cdata,
252                        Tcl_Interp *interp,
253                        int objc,
254                        Tcl_Obj *const objv[]  )
255{
256
257    const char* encodeType    = NULL; // name of the units provided by user
258    const char* option        = NULL;
259    const char* cmdName       = NULL;
260    Rappture::Buffer buf      = ""; // name of the units provided by user
261    Rappture::Outcome err;
262
263    int optionLen             = 0;
264    int typeLen               = 0;
265    int nextarg               = 0; // start parsing using the '2'th argument
266
267    int decompress            = 0;
268    int base64                = 0;
269    int flags                 = 0;
270
271    Tcl_Obj *result           = NULL;
272
273    Tcl_ResetResult(interp);
274
275    cmdName = Tcl_GetString(objv[nextarg++]);
276
277    // parse through command line options
278    if (objc < 1) {
279        Tcl_AppendResult(interp,
280                "wrong # args: should be \"", cmdName,
281                " ?-as z|b64|zb64? ?--? <string>\"", (char*)NULL);
282        return TCL_ERROR;
283    }
284
285    while ((objc - nextarg) > 0) {
286        option = Tcl_GetStringFromObj(objv[nextarg], &optionLen);
287        if (*option == '-') {
288            if ( strncmp(option,"-as",optionLen) == 0 ) {
289                nextarg++;
290                typeLen = 0;
291                if (nextarg < objc) {
292                    encodeType = Tcl_GetStringFromObj(objv[nextarg],&typeLen);
293                    nextarg++;
294                }
295                if (        (typeLen == 1) &&
296                            (strncmp(encodeType,"z",typeLen) == 0) ) {
297                    decompress = 1;
298                    base64 = 0;
299                }
300                else if (   (typeLen == 3) &&
301                            (strncmp(encodeType,"b64",typeLen) == 0) ) {
302                    decompress = 0;
303                    base64 = 1;
304                }
305                else if (   (typeLen == 4) &&
306                            (strncmp(encodeType,"zb64",typeLen) == 0) ) {
307                    decompress = 1;
308                    base64 = 1;
309                }
310                else {
311                    // user did not specify recognized wishes for this option,
312                    Tcl_AppendResult(interp, "bad value \"",(char*)NULL);
313                    if (encodeType != NULL) {
314                        Tcl_AppendResult(interp, encodeType,(char*)NULL);
315                    }
316                    Tcl_AppendResult(interp,
317                            "\": should be one of z, b64, zb64",
318                            (char*)NULL);
319                    return TCL_ERROR;
320                }
321            } else if ( strcmp(option,"--") == 0 ) {
322                nextarg++;
323                break;
324            } else {
325                Tcl_AppendResult(interp,
326                    "bad option \"", option,
327                    "\": should be -as, --", (char*)NULL);
328                return TCL_ERROR;
329            }
330        } else {
331            break;
332        }
333    }
334
335    if ((objc - nextarg) != 1) {
336        Tcl_AppendResult(interp,
337                "wrong # args: should be \"", cmdName,
338                " ?-as z|b64|zb64? ?--? <string>\"", (char*)NULL);
339        return TCL_ERROR;
340    }
341
342    option = (const char*) Tcl_GetByteArrayFromObj(objv[nextarg++], &optionLen);
343
344    buf = Rappture::Buffer(option,optionLen);
345
346    if (decompress == 1) {
347        flags = flags | RPENC_Z;
348    }
349    if (base64 == 1) {
350        flags = flags | RPENC_B64;
351    }
352
353    err &= Rappture::encoding::decode(buf,flags);
354
355    if (!err) {
356        result = Tcl_NewByteArrayObj(
357            (const unsigned char*)buf.bytes(), buf.size());
358        Tcl_SetObjResult(interp, result);
359    }
360    else {
361        result = Tcl_GetObjResult(interp);
362        Tcl_AppendStringsToObj( result, err.remark().c_str(),
363                                "\n", err.context().c_str(), NULL   );
364    }
365    return TCL_OK;
366}
Note: See TracBrowser for help on using the repository browser.