os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclBinary.c
First public contribution.
4 * This file contains the implementation of the "binary" Tcl built-in
5 * command and the Tcl binary data object.
7 * Copyright (c) 1997 by Sun Microsystems, Inc.
8 * Copyright (c) 1998-1999 by Scriptics Corporation.
9 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * RCS: @(#) $Id: tclBinary.c,v 1.13.2.4 2005/10/23 22:01:29 msofer Exp $
22 * The following constants are used by GetFormatSpec to indicate various
23 * special conditions in the parsing of a format specifier.
26 #define BINARY_ALL -1 /* Use all elements in the argument. */
27 #define BINARY_NOCOUNT -2 /* No count was specified in format. */
30 * The following defines the maximum number of different (integer)
31 * numbers placed in the object cache by 'binary scan' before it bails
32 * out and switches back to Plan A (creating a new object for each
33 * value.) Theoretically, it would be possible to keep the cache
34 * about for the values that are already in it, but that makes the
35 * code slower in practise when overflow happens, and makes little
36 * odds the rest of the time (as measured on my machine.) It is also
37 * slower (on the sample I tried at least) to grow the cache to hold
38 * all items we might want to put in it; presumably the extra cost of
39 * managing the memory for the enlarged table outweighs the benefit
40 * from allocating fewer objects. This is probably because as the
41 * number of objects increases, the likelihood of reuse of any
42 * particular one drops, and there is very little gain from larger
43 * maximum cache sizes (the value below is chosen to allow caching to
44 * work in full with conversion of bytes.) - DKF
47 #define BINARY_SCAN_MAX_CACHE 260
50 * Prototypes for local procedures defined in this file:
53 static void DupByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
55 static int FormatNumber _ANSI_ARGS_((Tcl_Interp *interp, int type,
56 Tcl_Obj *src, unsigned char **cursorPtr));
57 static void CopyNumber _ANSI_ARGS_((CONST VOID *from, VOID *to,
58 unsigned int length));
59 static void FreeByteArrayInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
60 static int GetFormatSpec _ANSI_ARGS_((char **formatPtr,
61 char *cmdPtr, int *countPtr));
62 static Tcl_Obj * ScanNumber _ANSI_ARGS_((unsigned char *buffer,
63 int type, Tcl_HashTable **numberCachePtr));
64 static int SetByteArrayFromAny _ANSI_ARGS_((Tcl_Interp *interp,
66 static void UpdateStringOfByteArray _ANSI_ARGS_((Tcl_Obj *listPtr));
67 static void DeleteScanNumberCache _ANSI_ARGS_((
68 Tcl_HashTable *numberCachePtr));
71 * The following object type represents an array of bytes. An array of
72 * bytes is not equivalent to an internationalized string. Conceptually, a
73 * string is an array of 16-bit quantities organized as a sequence of properly
74 * formed UTF-8 characters, while a ByteArray is an array of 8-bit quantities.
75 * Accessor functions are provided to convert a ByteArray to a String or a
76 * String to a ByteArray. Two or more consecutive bytes in an array of bytes
77 * may look like a single UTF-8 character if the array is casually treated as
78 * a string. But obtaining the String from a ByteArray is guaranteed to
79 * produced properly formed UTF-8 sequences so that there is a one-to-one
80 * map between bytes and characters.
82 * Converting a ByteArray to a String proceeds by casting each byte in the
83 * array to a 16-bit quantity, treating that number as a Unicode character,
84 * and storing the UTF-8 version of that Unicode character in the String.
85 * For ByteArrays consisting entirely of values 1..127, the corresponding
86 * String representation is the same as the ByteArray representation.
88 * Converting a String to a ByteArray proceeds by getting the Unicode
89 * representation of each character in the String, casting it to a
90 * byte by truncating the upper 8 bits, and then storing the byte in the
91 * ByteArray. Converting from ByteArray to String and back to ByteArray
92 * is not lossy, but converting an arbitrary String to a ByteArray may be.
95 Tcl_ObjType tclByteArrayType = {
97 FreeByteArrayInternalRep,
98 DupByteArrayInternalRep,
99 UpdateStringOfByteArray,
104 * The following structure is the internal rep for a ByteArray object.
105 * Keeps track of how much memory has been used and how much has been
106 * allocated for the byte array to enable growing and shrinking of the
107 * ByteArray object with fewer mallocs.
110 typedef struct ByteArray {
111 int used; /* The number of bytes used in the byte
113 int allocated; /* The amount of space actually allocated
115 unsigned char bytes[4]; /* The array of bytes. The actual size of
116 * this field depends on the 'allocated' field
120 #define BYTEARRAY_SIZE(len) \
121 ((unsigned) (sizeof(ByteArray) - 4 + (len)))
122 #define GET_BYTEARRAY(objPtr) \
123 ((ByteArray *) (objPtr)->internalRep.otherValuePtr)
124 #define SET_BYTEARRAY(objPtr, baPtr) \
125 (objPtr)->internalRep.otherValuePtr = (VOID *) (baPtr)
129 *---------------------------------------------------------------------------
131 * Tcl_NewByteArrayObj --
133 * This procedure is creates a new ByteArray object and initializes
134 * it from the given array of bytes.
137 * The newly create object is returned. This object will have no
138 * initial string representation. The returned object has a ref count
142 * Memory allocated for new object and copy of byte array argument.
144 *---------------------------------------------------------------------------
148 #undef Tcl_NewByteArrayObj
152 Tcl_NewByteArrayObj(bytes, length)
153 CONST unsigned char *bytes; /* The array of bytes used to initialize
155 int length; /* Length of the array of bytes, which must
158 return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0);
161 #else /* if not TCL_MEM_DEBUG */
164 Tcl_NewByteArrayObj(bytes, length)
165 CONST unsigned char *bytes; /* The array of bytes used to initialize
167 int length; /* Length of the array of bytes, which must
173 Tcl_SetByteArrayObj(objPtr, bytes, length);
176 #endif /* TCL_MEM_DEBUG */
179 *---------------------------------------------------------------------------
181 * Tcl_DbNewByteArrayObj --
183 * This procedure is normally called when debugging: i.e., when
184 * TCL_MEM_DEBUG is defined. It is the same as the Tcl_NewByteArrayObj
185 * above except that it calls Tcl_DbCkalloc directly with the file name
186 * and line number from its caller. This simplifies debugging since then
187 * the [memory active] command will report the correct file name and line
188 * number when reporting objects that haven't been freed.
190 * When TCL_MEM_DEBUG is not defined, this procedure just returns the
191 * result of calling Tcl_NewByteArrayObj.
194 * The newly create object is returned. This object will have no
195 * initial string representation. The returned object has a ref count
199 * Memory allocated for new object and copy of byte array argument.
201 *---------------------------------------------------------------------------
207 Tcl_DbNewByteArrayObj(bytes, length, file, line)
208 CONST unsigned char *bytes; /* The array of bytes used to initialize
210 int length; /* Length of the array of bytes, which must
212 CONST char *file; /* The name of the source file calling this
213 * procedure; used for debugging. */
214 int line; /* Line number in the source file; used
219 TclDbNewObj(objPtr, file, line);
220 Tcl_SetByteArrayObj(objPtr, bytes, length);
224 #else /* if not TCL_MEM_DEBUG */
227 Tcl_DbNewByteArrayObj(bytes, length, file, line)
228 CONST unsigned char *bytes; /* The array of bytes used to initialize
230 int length; /* Length of the array of bytes, which must
232 CONST char *file; /* The name of the source file calling this
233 * procedure; used for debugging. */
234 int line; /* Line number in the source file; used
237 return Tcl_NewByteArrayObj(bytes, length);
239 #endif /* TCL_MEM_DEBUG */
242 *---------------------------------------------------------------------------
244 * Tcl_SetByteArrayObj --
246 * Modify an object to be a ByteArray object and to have the specified
247 * array of bytes as its value.
253 * The object's old string rep and internal rep is freed.
254 * Memory allocated for copy of byte array argument.
256 *----------------------------------------------------------------------
260 Tcl_SetByteArrayObj(objPtr, bytes, length)
261 Tcl_Obj *objPtr; /* Object to initialize as a ByteArray. */
262 CONST unsigned char *bytes; /* The array of bytes to use as the new
264 int length; /* Length of the array of bytes, which must
267 Tcl_ObjType *typePtr;
268 ByteArray *byteArrayPtr;
270 if (Tcl_IsShared(objPtr)) {
271 panic("Tcl_SetByteArrayObj called with shared object");
273 typePtr = objPtr->typePtr;
274 if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
275 (*typePtr->freeIntRepProc)(objPtr);
277 Tcl_InvalidateStringRep(objPtr);
279 byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
280 byteArrayPtr->used = length;
281 byteArrayPtr->allocated = length;
282 memcpy((VOID *) byteArrayPtr->bytes, (VOID *) bytes, (size_t) length);
284 objPtr->typePtr = &tclByteArrayType;
285 SET_BYTEARRAY(objPtr, byteArrayPtr);
289 *----------------------------------------------------------------------
291 * Tcl_GetByteArrayFromObj --
293 * Attempt to get the array of bytes from the Tcl object. If the
294 * object is not already a ByteArray object, an attempt will be
295 * made to convert it to one.
298 * Pointer to array of bytes representing the ByteArray object.
301 * Frees old internal rep. Allocates memory for new internal rep.
303 *----------------------------------------------------------------------
306 EXPORT_C unsigned char *
307 Tcl_GetByteArrayFromObj(objPtr, lengthPtr)
308 Tcl_Obj *objPtr; /* The ByteArray object. */
309 int *lengthPtr; /* If non-NULL, filled with length of the
310 * array of bytes in the ByteArray object. */
314 SetByteArrayFromAny(NULL, objPtr);
315 baPtr = GET_BYTEARRAY(objPtr);
317 if (lengthPtr != NULL) {
318 *lengthPtr = baPtr->used;
320 return (unsigned char *) baPtr->bytes;
324 *----------------------------------------------------------------------
326 * Tcl_SetByteArrayLength --
328 * This procedure changes the length of the byte array for this
329 * object. Once the caller has set the length of the array, it
330 * is acceptable to directly modify the bytes in the array up until
331 * Tcl_GetStringFromObj() has been called on this object.
334 * The new byte array of the specified length.
337 * Allocates enough memory for an array of bytes of the requested
338 * size. When growing the array, the old array is copied to the
339 * new array; new bytes are undefined. When shrinking, the
340 * old array is truncated to the specified length.
342 *---------------------------------------------------------------------------
345 EXPORT_C unsigned char *
346 Tcl_SetByteArrayLength(objPtr, length)
347 Tcl_Obj *objPtr; /* The ByteArray object. */
348 int length; /* New length for internal byte array. */
350 ByteArray *byteArrayPtr, *newByteArrayPtr;
352 if (Tcl_IsShared(objPtr)) {
353 panic("Tcl_SetObjLength called with shared object");
355 if (objPtr->typePtr != &tclByteArrayType) {
356 SetByteArrayFromAny(NULL, objPtr);
359 byteArrayPtr = GET_BYTEARRAY(objPtr);
360 if (length > byteArrayPtr->allocated) {
361 newByteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
362 newByteArrayPtr->used = length;
363 newByteArrayPtr->allocated = length;
364 memcpy((VOID *) newByteArrayPtr->bytes,
365 (VOID *) byteArrayPtr->bytes, (size_t) byteArrayPtr->used);
366 ckfree((char *) byteArrayPtr);
367 byteArrayPtr = newByteArrayPtr;
368 SET_BYTEARRAY(objPtr, byteArrayPtr);
370 Tcl_InvalidateStringRep(objPtr);
371 byteArrayPtr->used = length;
372 return byteArrayPtr->bytes;
376 *---------------------------------------------------------------------------
378 * SetByteArrayFromAny --
380 * Generate the ByteArray internal rep from the string rep.
383 * The return value is always TCL_OK.
386 * A ByteArray object is stored as the internal rep of objPtr.
388 *---------------------------------------------------------------------------
392 SetByteArrayFromAny(interp, objPtr)
393 Tcl_Interp *interp; /* Not used. */
394 Tcl_Obj *objPtr; /* The object to convert to type ByteArray. */
396 Tcl_ObjType *typePtr;
400 ByteArray *byteArrayPtr;
403 typePtr = objPtr->typePtr;
404 if (typePtr != &tclByteArrayType) {
405 src = Tcl_GetStringFromObj(objPtr, &length);
406 srcEnd = src + length;
408 byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
409 for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
410 src += Tcl_UtfToUniChar(src, &ch);
411 *dst++ = (unsigned char) ch;
414 byteArrayPtr->used = dst - byteArrayPtr->bytes;
415 byteArrayPtr->allocated = length;
417 if ((typePtr != NULL) && (typePtr->freeIntRepProc) != NULL) {
418 (*typePtr->freeIntRepProc)(objPtr);
420 objPtr->typePtr = &tclByteArrayType;
421 SET_BYTEARRAY(objPtr, byteArrayPtr);
427 *----------------------------------------------------------------------
429 * FreeByteArrayInternalRep --
431 * Deallocate the storage associated with a ByteArray data object's
432 * internal representation.
440 *----------------------------------------------------------------------
444 FreeByteArrayInternalRep(objPtr)
445 Tcl_Obj *objPtr; /* Object with internal rep to free. */
447 ckfree((char *) GET_BYTEARRAY(objPtr));
451 *---------------------------------------------------------------------------
453 * DupByteArrayInternalRep --
455 * Initialize the internal representation of a ByteArray Tcl_Obj
456 * to a copy of the internal representation of an existing ByteArray
465 *---------------------------------------------------------------------------
469 DupByteArrayInternalRep(srcPtr, copyPtr)
470 Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
471 Tcl_Obj *copyPtr; /* Object with internal rep to set. */
474 ByteArray *srcArrayPtr, *copyArrayPtr;
476 srcArrayPtr = GET_BYTEARRAY(srcPtr);
477 length = srcArrayPtr->used;
479 copyArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
480 copyArrayPtr->used = length;
481 copyArrayPtr->allocated = length;
482 memcpy((VOID *) copyArrayPtr->bytes, (VOID *) srcArrayPtr->bytes,
484 SET_BYTEARRAY(copyPtr, copyArrayPtr);
486 copyPtr->typePtr = &tclByteArrayType;
490 *---------------------------------------------------------------------------
492 * UpdateStringOfByteArray --
494 * Update the string representation for a ByteArray data object.
495 * Note: This procedure does not invalidate an existing old string rep
496 * so storage will be lost if this has not already been done.
502 * The object's string is set to a valid string that results from
503 * the ByteArray-to-string conversion.
505 * The object becomes a string object -- the internal rep is
506 * discarded and the typePtr becomes NULL.
508 *---------------------------------------------------------------------------
512 UpdateStringOfByteArray(objPtr)
513 Tcl_Obj *objPtr; /* ByteArray object whose string rep to
519 ByteArray *byteArrayPtr;
521 byteArrayPtr = GET_BYTEARRAY(objPtr);
522 src = byteArrayPtr->bytes;
523 length = byteArrayPtr->used;
526 * How much space will string rep need?
530 for (i = 0; i < length; i++) {
531 if ((src[i] == 0) || (src[i] > 127)) {
536 dst = (char *) ckalloc((unsigned) (size + 1));
538 objPtr->length = size;
540 if (size == length) {
541 memcpy((VOID *) dst, (VOID *) src, (size_t) size);
544 for (i = 0; i < length; i++) {
545 dst += Tcl_UniCharToUtf(src[i], dst);
552 *----------------------------------------------------------------------
554 * Tcl_BinaryObjCmd --
556 * This procedure implements the "binary" Tcl command.
559 * A standard Tcl result.
562 * See the user documentation.
564 *----------------------------------------------------------------------
568 Tcl_BinaryObjCmd(dummy, interp, objc, objv)
569 ClientData dummy; /* Not used. */
570 Tcl_Interp *interp; /* Current interpreter. */
571 int objc; /* Number of arguments. */
572 Tcl_Obj *CONST objv[]; /* Argument objects. */
574 int arg; /* Index of next argument to consume. */
575 int value = 0; /* Current integer value to be packed.
576 * Initialized to avoid compiler warning. */
577 char cmd; /* Current format character. */
578 int count; /* Count associated with current format
580 char *format; /* Pointer to current position in format
582 Tcl_Obj *resultPtr; /* Object holding result buffer. */
583 unsigned char *buffer; /* Start of result buffer. */
584 unsigned char *cursor; /* Current position within result buffer. */
585 unsigned char *maxPos; /* Greatest position within result buffer that
586 * cursor has visited.*/
587 char *errorString, *errorValue, *str;
588 int offset, size, length, index;
589 static CONST char *options[] = {
590 "format", "scan", NULL
593 BINARY_FORMAT, BINARY_SCAN
597 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
601 if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
606 switch ((enum options) index) {
607 case BINARY_FORMAT: {
609 Tcl_WrongNumArgs(interp, 2, objv, "formatString ?arg arg ...?");
614 * To avoid copying the data, we format the string in two passes.
615 * The first pass computes the size of the output buffer. The
616 * second pass places the formatted data into the buffer.
619 format = Tcl_GetString(objv[2]);
623 while (*format != '\0') {
625 if (!GetFormatSpec(&format, &cmd, &count)) {
636 * For string-type specifiers, the count corresponds
637 * to the number of bytes in a single argument.
643 if (count == BINARY_ALL) {
644 Tcl_GetByteArrayFromObj(objv[arg], &count);
645 } else if (count == BINARY_NOCOUNT) {
649 if (cmd == 'a' || cmd == 'A') {
651 } else if (cmd == 'b' || cmd == 'B') {
652 offset += (count + 7) / 8;
654 offset += (count + 1) / 2;
678 size = sizeof(float);
682 size = sizeof(double);
690 * For number-type specifiers, the count corresponds
691 * to the number of elements in the list stored in
692 * a single argument. If no count is specified, then
693 * the argument is taken as a single non-list value.
696 if (count == BINARY_NOCOUNT) {
702 if (Tcl_ListObjGetElements(interp, objv[arg++],
703 &listc, &listv) != TCL_OK) {
706 if (count == BINARY_ALL) {
708 } else if (count > listc) {
709 Tcl_AppendResult(interp,
710 "number of elements in list does not match count",
715 offset += count*size;
719 if (count == BINARY_ALL) {
720 Tcl_AppendResult(interp,
721 "cannot use \"*\" in format string with \"x\"",
724 } else if (count == BINARY_NOCOUNT) {
731 if (count == BINARY_NOCOUNT) {
734 if ((count > offset) || (count == BINARY_ALL)) {
737 if (offset > length) {
744 if (offset > length) {
747 if (count == BINARY_ALL) {
749 } else if (count == BINARY_NOCOUNT) {
762 if (offset > length) {
770 * Prepare the result object by preallocating the caclulated
771 * number of bytes and filling with nulls.
774 resultPtr = Tcl_GetObjResult(interp);
775 buffer = Tcl_SetByteArrayLength(resultPtr, length);
776 memset((VOID *) buffer, 0, (size_t) length);
779 * Pack the data into the result object. Note that we can skip
780 * the error checking during this pass, since we have already
781 * parsed the string once.
785 format = Tcl_GetString(objv[2]);
788 while (*format != 0) {
789 if (!GetFormatSpec(&format, &cmd, &count)) {
792 if ((count == 0) && (cmd != '@')) {
799 char pad = (char) (cmd == 'a' ? '\0' : ' ');
800 unsigned char *bytes;
802 bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length);
804 if (count == BINARY_ALL) {
806 } else if (count == BINARY_NOCOUNT) {
809 if (length >= count) {
810 memcpy((VOID *) cursor, (VOID *) bytes,
813 memcpy((VOID *) cursor, (VOID *) bytes,
815 memset((VOID *) (cursor + length), pad,
816 (size_t) (count - length));
825 str = Tcl_GetStringFromObj(objv[arg++], &length);
826 if (count == BINARY_ALL) {
828 } else if (count == BINARY_NOCOUNT) {
831 last = cursor + ((count + 7) / 8);
832 if (count > length) {
836 errorString = "binary";
838 for (offset = 0; offset < count; offset++) {
840 if (str[offset] == '1') {
842 } else if (str[offset] != '0') {
846 if (((offset + 1) % 8) == 0) {
847 *cursor++ = (unsigned char) value;
852 for (offset = 0; offset < count; offset++) {
854 if (str[offset] == '1') {
856 } else if (str[offset] != '0') {
860 if (!((offset + 1) % 8)) {
861 *cursor++ = (unsigned char) value;
866 if ((offset % 8) != 0) {
868 value <<= 8 - (offset % 8);
870 value >>= 8 - (offset % 8);
872 *cursor++ = (unsigned char) value;
874 while (cursor < last) {
884 str = Tcl_GetStringFromObj(objv[arg++], &length);
885 if (count == BINARY_ALL) {
887 } else if (count == BINARY_NOCOUNT) {
890 last = cursor + ((count + 1) / 2);
891 if (count > length) {
895 errorString = "hexadecimal";
897 for (offset = 0; offset < count; offset++) {
899 if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */
903 c = str[offset] - '0';
905 c += ('0' - 'A') + 10;
912 *cursor++ = (char) value;
917 for (offset = 0; offset < count; offset++) {
920 if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */
924 c = str[offset] - '0';
926 c += ('0' - 'A') + 10;
931 value |= ((c << 4) & 0xf0);
933 *cursor++ = (unsigned char)(value & 0xff);
944 *cursor++ = (unsigned char) value;
947 while (cursor < last) {
964 if (count == BINARY_NOCOUNT) {
966 * Note that we are casting away the const-ness of
967 * objv, but this is safe since we aren't going to
971 listv = (Tcl_Obj**)(objv + arg);
975 Tcl_ListObjGetElements(interp, objv[arg],
977 if (count == BINARY_ALL) {
982 for (i = 0; i < count; i++) {
983 if (FormatNumber(interp, cmd, listv[i], &cursor)
991 if (count == BINARY_NOCOUNT) {
994 memset(cursor, 0, (size_t) count);
999 if (cursor > maxPos) {
1002 if (count == BINARY_NOCOUNT) {
1005 if ((count == BINARY_ALL)
1006 || (count > (cursor - buffer))) {
1014 if (cursor > maxPos) {
1017 if (count == BINARY_ALL) {
1020 cursor = buffer + count;
1030 Tcl_Obj *valuePtr, *elementPtr;
1031 Tcl_HashTable numberCacheHash;
1032 Tcl_HashTable *numberCachePtr;
1035 Tcl_WrongNumArgs(interp, 2, objv,
1036 "value formatString ?varName varName ...?");
1039 numberCachePtr = &numberCacheHash;
1040 Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);
1041 buffer = Tcl_GetByteArrayFromObj(objv[2], &length);
1042 format = Tcl_GetString(objv[3]);
1046 while (*format != '\0') {
1048 if (!GetFormatSpec(&format, &cmd, &count)) {
1057 DeleteScanNumberCache(numberCachePtr);
1060 if (count == BINARY_ALL) {
1061 count = length - offset;
1063 if (count == BINARY_NOCOUNT) {
1066 if (count > (length - offset)) {
1071 src = buffer + offset;
1075 * Trim trailing nulls and spaces, if necessary.
1080 if (src[size-1] != '\0' && src[size-1] != ' ') {
1086 valuePtr = Tcl_NewByteArrayObj(src, size);
1087 Tcl_IncrRefCount(valuePtr);
1088 resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
1089 NULL, valuePtr, TCL_LEAVE_ERR_MSG);
1090 Tcl_DecrRefCount(valuePtr);
1092 if (resultPtr == NULL) {
1093 DeleteScanNumberCache(numberCachePtr);
1105 DeleteScanNumberCache(numberCachePtr);
1108 if (count == BINARY_ALL) {
1109 count = (length - offset) * 8;
1111 if (count == BINARY_NOCOUNT) {
1114 if (count > (length - offset) * 8) {
1118 src = buffer + offset;
1119 valuePtr = Tcl_NewObj();
1120 Tcl_SetObjLength(valuePtr, count);
1121 dest = Tcl_GetString(valuePtr);
1124 for (i = 0; i < count; i++) {
1130 *dest++ = (char) ((value & 1) ? '1' : '0');
1133 for (i = 0; i < count; i++) {
1139 *dest++ = (char) ((value & 0x80) ? '1' : '0');
1143 Tcl_IncrRefCount(valuePtr);
1144 resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
1145 NULL, valuePtr, TCL_LEAVE_ERR_MSG);
1146 Tcl_DecrRefCount(valuePtr);
1148 if (resultPtr == NULL) {
1149 DeleteScanNumberCache(numberCachePtr);
1152 offset += (count + 7 ) / 8;
1160 static char hexdigit[] = "0123456789abcdef";
1163 DeleteScanNumberCache(numberCachePtr);
1166 if (count == BINARY_ALL) {
1167 count = (length - offset)*2;
1169 if (count == BINARY_NOCOUNT) {
1172 if (count > (length - offset)*2) {
1176 src = buffer + offset;
1177 valuePtr = Tcl_NewObj();
1178 Tcl_SetObjLength(valuePtr, count);
1179 dest = Tcl_GetString(valuePtr);
1182 for (i = 0; i < count; i++) {
1188 *dest++ = hexdigit[value & 0xf];
1191 for (i = 0; i < count; i++) {
1197 *dest++ = hexdigit[(value >> 4) & 0xf];
1201 Tcl_IncrRefCount(valuePtr);
1202 resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
1203 NULL, valuePtr, TCL_LEAVE_ERR_MSG);
1204 Tcl_DecrRefCount(valuePtr);
1206 if (resultPtr == NULL) {
1207 DeleteScanNumberCache(numberCachePtr);
1210 offset += (count + 1) / 2;
1233 size = sizeof(float);
1239 size = sizeof(double);
1244 DeleteScanNumberCache(numberCachePtr);
1247 if (count == BINARY_NOCOUNT) {
1248 if ((length - offset) < size) {
1251 valuePtr = ScanNumber(buffer+offset, cmd,
1255 if (count == BINARY_ALL) {
1256 count = (length - offset) / size;
1258 if ((length - offset) < (count * size)) {
1261 valuePtr = Tcl_NewObj();
1262 src = buffer+offset;
1263 for (i = 0; i < count; i++) {
1264 elementPtr = ScanNumber(src, cmd,
1267 Tcl_ListObjAppendElement(NULL, valuePtr,
1270 offset += count*size;
1273 Tcl_IncrRefCount(valuePtr);
1274 resultPtr = Tcl_ObjSetVar2(interp, objv[arg],
1275 NULL, valuePtr, TCL_LEAVE_ERR_MSG);
1276 Tcl_DecrRefCount(valuePtr);
1278 if (resultPtr == NULL) {
1279 DeleteScanNumberCache(numberCachePtr);
1285 if (count == BINARY_NOCOUNT) {
1288 if ((count == BINARY_ALL)
1289 || (count > (length - offset))) {
1297 if (count == BINARY_NOCOUNT) {
1300 if ((count == BINARY_ALL) || (count > offset)) {
1308 if (count == BINARY_NOCOUNT) {
1309 DeleteScanNumberCache(numberCachePtr);
1312 if ((count == BINARY_ALL) || (count > length)) {
1320 DeleteScanNumberCache(numberCachePtr);
1328 * Set the result to the last position of the cursor.
1332 Tcl_ResetResult(interp);
1333 Tcl_SetLongObj(Tcl_GetObjResult(interp), arg - 4);
1334 DeleteScanNumberCache(numberCachePtr);
1341 Tcl_ResetResult(interp);
1342 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "expected ", errorString,
1343 " string but got \"", errorValue, "\" instead", NULL);
1347 errorString = "missing count for \"@\" field specifier";
1351 errorString = "not enough arguments for all format specifiers";
1357 char buf[TCL_UTF_MAX + 1];
1359 Tcl_UtfToUniChar(errorString, &ch);
1360 buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
1361 Tcl_AppendResult(interp, "bad field specifier \"", buf, "\"", NULL);
1366 Tcl_AppendResult(interp, errorString, NULL);
1371 *----------------------------------------------------------------------
1375 * This function parses the format strings used in the binary
1376 * format and scan commands.
1379 * Moves the formatPtr to the start of the next command. Returns
1380 * the current command character and count in cmdPtr and countPtr.
1381 * The count is set to BINARY_ALL if the count character was '*'
1382 * or BINARY_NOCOUNT if no count was specified. Returns 1 on
1383 * success, or 0 if the string did not have a format specifier.
1388 *----------------------------------------------------------------------
1392 GetFormatSpec(formatPtr, cmdPtr, countPtr)
1393 char **formatPtr; /* Pointer to format string. */
1394 char *cmdPtr; /* Pointer to location of command char. */
1395 int *countPtr; /* Pointer to repeat count value. */
1398 * Skip any leading blanks.
1401 while (**formatPtr == ' ') {
1406 * The string was empty, except for whitespace, so fail.
1409 if (!(**formatPtr)) {
1414 * Extract the command character and any trailing digits or '*'.
1417 *cmdPtr = **formatPtr;
1419 if (**formatPtr == '*') {
1421 (*countPtr) = BINARY_ALL;
1422 } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
1423 (*countPtr) = strtoul(*formatPtr, formatPtr, 10);
1425 (*countPtr) = BINARY_NOCOUNT;
1431 *----------------------------------------------------------------------
1435 * This routine is called by Tcl_BinaryObjCmd to format a number
1436 * into a location pointed at by cursor.
1439 * A standard Tcl result.
1442 * Moves the cursor to the next location to be written into.
1444 *----------------------------------------------------------------------
1448 FormatNumber(interp, type, src, cursorPtr)
1449 Tcl_Interp *interp; /* Current interpreter, used to report
1451 int type; /* Type of number to format. */
1452 Tcl_Obj *src; /* Number to format. */
1453 unsigned char **cursorPtr; /* Pointer to index into destination buffer. */
1463 * For floating point types, we need to copy the data using
1464 * memcpy to avoid alignment issues.
1467 if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
1472 * Can't just memcpy() here. [Bug 1116542]
1475 CopyNumber(&dvalue, *cursorPtr, sizeof(double));
1476 *cursorPtr += sizeof(double);
1481 * Because some compilers will generate floating point exceptions
1482 * on an overflow cast (e.g. Borland), we restrict the values
1483 * to the valid range for float.
1486 if (fabs(dvalue) > (double)FLT_MAX) {
1487 fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
1489 fvalue = (float) dvalue;
1491 memcpy((VOID *) *cursorPtr, (VOID *) &fvalue, sizeof(float));
1492 *cursorPtr += sizeof(float);
1497 * Next cases separate from other integer cases because we
1498 * need a different API to get a wide.
1502 if (Tcl_GetWideIntFromObj(interp, src, &wvalue) != TCL_OK) {
1506 *(*cursorPtr)++ = (unsigned char) wvalue;
1507 *(*cursorPtr)++ = (unsigned char) (wvalue >> 8);
1508 *(*cursorPtr)++ = (unsigned char) (wvalue >> 16);
1509 *(*cursorPtr)++ = (unsigned char) (wvalue >> 24);
1510 *(*cursorPtr)++ = (unsigned char) (wvalue >> 32);
1511 *(*cursorPtr)++ = (unsigned char) (wvalue >> 40);
1512 *(*cursorPtr)++ = (unsigned char) (wvalue >> 48);
1513 *(*cursorPtr)++ = (unsigned char) (wvalue >> 56);
1515 *(*cursorPtr)++ = (unsigned char) (wvalue >> 56);
1516 *(*cursorPtr)++ = (unsigned char) (wvalue >> 48);
1517 *(*cursorPtr)++ = (unsigned char) (wvalue >> 40);
1518 *(*cursorPtr)++ = (unsigned char) (wvalue >> 32);
1519 *(*cursorPtr)++ = (unsigned char) (wvalue >> 24);
1520 *(*cursorPtr)++ = (unsigned char) (wvalue >> 16);
1521 *(*cursorPtr)++ = (unsigned char) (wvalue >> 8);
1522 *(*cursorPtr)++ = (unsigned char) wvalue;
1526 if (Tcl_GetLongFromObj(interp, src, &value) != TCL_OK) {
1530 *(*cursorPtr)++ = (unsigned char) value;
1531 } else if (type == 's') {
1532 *(*cursorPtr)++ = (unsigned char) value;
1533 *(*cursorPtr)++ = (unsigned char) (value >> 8);
1534 } else if (type == 'S') {
1535 *(*cursorPtr)++ = (unsigned char) (value >> 8);
1536 *(*cursorPtr)++ = (unsigned char) value;
1537 } else if (type == 'i') {
1538 *(*cursorPtr)++ = (unsigned char) value;
1539 *(*cursorPtr)++ = (unsigned char) (value >> 8);
1540 *(*cursorPtr)++ = (unsigned char) (value >> 16);
1541 *(*cursorPtr)++ = (unsigned char) (value >> 24);
1542 } else if (type == 'I') {
1543 *(*cursorPtr)++ = (unsigned char) (value >> 24);
1544 *(*cursorPtr)++ = (unsigned char) (value >> 16);
1545 *(*cursorPtr)++ = (unsigned char) (value >> 8);
1546 *(*cursorPtr)++ = (unsigned char) value;
1552 /* Ugly workaround for old and broken compiler! */
1554 CopyNumber(from, to, length)
1557 unsigned int length;
1559 memcpy(to, from, length);
1563 *----------------------------------------------------------------------
1567 * This routine is called by Tcl_BinaryObjCmd to scan a number
1571 * Returns a newly created object containing the scanned number.
1572 * This object has a ref count of zero.
1575 * Might reuse an object in the number cache, place a new object
1576 * in the cache, or delete the cache and set the reference to
1577 * it (itself passed in by reference) to NULL.
1579 *----------------------------------------------------------------------
1583 ScanNumber(buffer, type, numberCachePtrPtr)
1584 unsigned char *buffer; /* Buffer to scan number from. */
1585 int type; /* Format character from "binary scan" */
1586 Tcl_HashTable **numberCachePtrPtr;
1587 /* Place to look for cache of scanned
1588 * value objects, or NULL if too many
1589 * different numbers have been scanned. */
1592 Tcl_WideUInt uwvalue;
1595 * We cannot rely on the compiler to properly sign extend integer values
1596 * when we cast from smaller values to larger values because we don't know
1597 * the exact size of the integer types. So, we have to handle sign
1598 * extension explicitly by checking the high bit and padding with 1's as
1605 * Characters need special handling. We want to produce a
1606 * signed result, but on some platforms (such as AIX) chars
1607 * are unsigned. To deal with this, check for a value that
1608 * should be negative but isn't.
1615 goto returnNumericObject;
1618 value = (long) (buffer[0] + (buffer[1] << 8));
1621 value = (long) (buffer[1] + (buffer[0] << 8));
1623 if (value & 0x8000) {
1626 goto returnNumericObject;
1629 value = (long) (buffer[0]
1632 + (buffer[3] << 24));
1635 value = (long) (buffer[3]
1638 + (buffer[0] << 24));
1641 * Check to see if the value was sign extended properly on
1642 * systems where an int is more than 32-bits.
1645 if ((value & (((unsigned int)1)<<31)) && (value > 0)) {
1646 value -= (((unsigned int)1)<<31);
1647 value -= (((unsigned int)1)<<31);
1649 returnNumericObject:
1650 if (*numberCachePtrPtr == NULL) {
1651 return Tcl_NewLongObj(value);
1653 register Tcl_HashTable *tablePtr = *numberCachePtrPtr;
1654 register Tcl_HashEntry *hPtr;
1657 hPtr = Tcl_CreateHashEntry(tablePtr, (char *)value, &isNew);
1659 return (Tcl_Obj *) Tcl_GetHashValue(hPtr);
1661 if (tablePtr->numEntries > BINARY_SCAN_MAX_CACHE) {
1663 * We've overflowed the cache! Someone's parsing
1664 * a LOT of varied binary data in a single call!
1665 * Bail out by switching back to the old behaviour
1666 * for the rest of the scan.
1668 * Note that anyone just using the 'c' conversion
1669 * (for bytes) cannot trigger this.
1671 DeleteScanNumberCache(tablePtr);
1672 *numberCachePtrPtr = NULL;
1673 return Tcl_NewLongObj(value);
1675 register Tcl_Obj *objPtr = Tcl_NewLongObj(value);
1677 Tcl_IncrRefCount(objPtr);
1678 Tcl_SetHashValue(hPtr, (ClientData) objPtr);
1684 * Do not cache wide values; they are already too large to
1688 uwvalue = ((Tcl_WideUInt) buffer[0])
1689 | (((Tcl_WideUInt) buffer[1]) << 8)
1690 | (((Tcl_WideUInt) buffer[2]) << 16)
1691 | (((Tcl_WideUInt) buffer[3]) << 24)
1692 | (((Tcl_WideUInt) buffer[4]) << 32)
1693 | (((Tcl_WideUInt) buffer[5]) << 40)
1694 | (((Tcl_WideUInt) buffer[6]) << 48)
1695 | (((Tcl_WideUInt) buffer[7]) << 56);
1696 return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue);
1698 uwvalue = ((Tcl_WideUInt) buffer[7])
1699 | (((Tcl_WideUInt) buffer[6]) << 8)
1700 | (((Tcl_WideUInt) buffer[5]) << 16)
1701 | (((Tcl_WideUInt) buffer[4]) << 24)
1702 | (((Tcl_WideUInt) buffer[3]) << 32)
1703 | (((Tcl_WideUInt) buffer[2]) << 40)
1704 | (((Tcl_WideUInt) buffer[1]) << 48)
1705 | (((Tcl_WideUInt) buffer[0]) << 56);
1706 return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue);
1709 * Do not cache double values; they are already too large
1710 * to use as keys and the values stored are utterly
1715 memcpy((VOID *) &fvalue, (VOID *) buffer, sizeof(float));
1716 return Tcl_NewDoubleObj(fvalue);
1720 memcpy((VOID *) &dvalue, (VOID *) buffer, sizeof(double));
1721 return Tcl_NewDoubleObj(dvalue);
1728 *----------------------------------------------------------------------
1730 * DeleteScanNumberCache --
1732 * Deletes the hash table acting as a scan number cache.
1738 * Decrements the reference counts of the objects in the cache.
1740 *----------------------------------------------------------------------
1744 DeleteScanNumberCache(numberCachePtr)
1745 Tcl_HashTable *numberCachePtr; /* Pointer to the hash table, or
1746 * NULL (when the cache has already
1747 * been deleted due to overflow.) */
1749 Tcl_HashEntry *hEntry;
1750 Tcl_HashSearch search;
1752 if (numberCachePtr == NULL) {
1756 hEntry = Tcl_FirstHashEntry(numberCachePtr, &search);
1757 while (hEntry != NULL) {
1758 register Tcl_Obj *value = (Tcl_Obj *) Tcl_GetHashValue(hEntry);
1760 if (value != NULL) {
1761 Tcl_DecrRefCount(value);
1763 hEntry = Tcl_NextHashEntry(&search);
1765 Tcl_DeleteHashTable(numberCachePtr);