1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/*
* tclBinary.c --
*
* This file contains the implementation of the "binary" Tcl built-in
* command and the Tcl binary data object.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
* Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclBinary.c,v 1.13.4.16 2007/09/07 03:15:08 dgp Exp $
*/
#include "tclInt.h"
#include "tommath.h"
#include <math.h>
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/*
* tclBinary.c --
*
* This file contains the implementation of the "binary" Tcl built-in
* command and the Tcl binary data object.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
* Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclBinary.c,v 1.13.4.17 2007/11/12 20:40:40 dgp Exp $
*/
#include "tclInt.h"
#include "tommath.h"
#include <math.h>
|
| ︙ | | | ︙ | |
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
|
Tcl_GetByteArrayFromObj(
Tcl_Obj *objPtr, /* The ByteArray object. */
int *lengthPtr) /* If non-NULL, filled with length of the
* array of bytes in the ByteArray object. */
{
ByteArray *baPtr;
SetByteArrayFromAny(NULL, objPtr);
baPtr = GET_BYTEARRAY(objPtr);
if (lengthPtr != NULL) {
*lengthPtr = baPtr->used;
}
return (unsigned char *) baPtr->bytes;
}
|
>
|
>
|
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
|
Tcl_GetByteArrayFromObj(
Tcl_Obj *objPtr, /* The ByteArray object. */
int *lengthPtr) /* If non-NULL, filled with length of the
* array of bytes in the ByteArray object. */
{
ByteArray *baPtr;
if (objPtr->typePtr != &tclByteArrayType) {
SetByteArrayFromAny(NULL, objPtr);
}
baPtr = GET_BYTEARRAY(objPtr);
if (lengthPtr != NULL) {
*lengthPtr = baPtr->used;
}
return (unsigned char *) baPtr->bytes;
}
|
| ︙ | | | ︙ | |
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
|
int length;
char *src, *srcEnd;
unsigned char *dst;
ByteArray *byteArrayPtr;
Tcl_UniChar ch;
if (objPtr->typePtr != &tclByteArrayType) {
src = Tcl_GetStringFromObj(objPtr, &length);
srcEnd = src + length;
byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
src += Tcl_UtfToUniChar(src, &ch);
*dst++ = (unsigned char) ch;
}
|
|
|
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
|
int length;
char *src, *srcEnd;
unsigned char *dst;
ByteArray *byteArrayPtr;
Tcl_UniChar ch;
if (objPtr->typePtr != &tclByteArrayType) {
src = TclGetStringFromObj(objPtr, &length);
srcEnd = src + length;
byteArrayPtr = (ByteArray *) ckalloc(BYTEARRAY_SIZE(length));
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
src += Tcl_UtfToUniChar(src, &ch);
*dst++ = (unsigned char) ch;
}
|
| ︙ | | | ︙ | |
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
|
/*
* To avoid copying the data, we format the string in two passes. The
* first pass computes the size of the output buffer. The second pass
* places the formatted data into the buffer.
*/
format = Tcl_GetString(objv[2]);
arg = 3;
offset = 0;
length = 0;
while (*format != '\0') {
str = format;
flags = 0;
if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
|
|
|
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
|
/*
* To avoid copying the data, we format the string in two passes. The
* first pass computes the size of the output buffer. The second pass
* places the formatted data into the buffer.
*/
format = TclGetString(objv[2]);
arg = 3;
offset = 0;
length = 0;
while (*format != '\0') {
str = format;
flags = 0;
if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
|
| ︙ | | | ︙ | |
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
|
if (count == BINARY_NOCOUNT) {
arg++;
count = 1;
} else {
int listc;
Tcl_Obj **listv;
if (Tcl_ListObjGetElements(interp, objv[arg++], &listc,
&listv) != TCL_OK) {
return TCL_ERROR;
}
if (count == BINARY_ALL) {
count = listc;
} else if (count > listc) {
Tcl_AppendResult(interp,
"number of elements in list does not match count",
NULL);
return TCL_ERROR;
|
>
|
>
>
|
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
|
if (count == BINARY_NOCOUNT) {
arg++;
count = 1;
} else {
int listc;
Tcl_Obj **listv;
/* The macro evals its args more than once: avoid arg++ */
if (TclListObjGetElements(interp, objv[arg], &listc,
&listv) != TCL_OK) {
return TCL_ERROR;
}
arg++;
if (count == BINARY_ALL) {
count = listc;
} else if (count > listc) {
Tcl_AppendResult(interp,
"number of elements in list does not match count",
NULL);
return TCL_ERROR;
|
| ︙ | | | ︙ | |
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
|
/*
* Pack the data into the result object. Note that we can skip the
* error checking during this pass, since we have already parsed the
* string once.
*/
arg = 3;
format = Tcl_GetString(objv[2]);
cursor = buffer;
maxPos = cursor;
while (*format != 0) {
flags = 0;
if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
break;
}
|
|
|
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
|
/*
* Pack the data into the result object. Note that we can skip the
* error checking during this pass, since we have already parsed the
* string once.
*/
arg = 3;
format = TclGetString(objv[2]);
cursor = buffer;
maxPos = cursor;
while (*format != 0) {
flags = 0;
if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
break;
}
|
| ︙ | | | ︙ | |
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
|
cursor += count;
break;
}
case 'b':
case 'B': {
unsigned char *last;
str = Tcl_GetStringFromObj(objv[arg++], &length);
if (count == BINARY_ALL) {
count = length;
} else if (count == BINARY_NOCOUNT) {
count = 1;
}
last = cursor + ((count + 7) / 8);
if (count > length) {
|
|
>
|
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
|
cursor += count;
break;
}
case 'b':
case 'B': {
unsigned char *last;
str = TclGetStringFromObj(objv[arg], &length);
arg++;
if (count == BINARY_ALL) {
count = length;
} else if (count == BINARY_NOCOUNT) {
count = 1;
}
last = cursor + ((count + 7) / 8);
if (count > length) {
|
| ︙ | | | ︙ | |
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
|
break;
}
case 'h':
case 'H': {
unsigned char *last;
int c;
str = Tcl_GetStringFromObj(objv[arg++], &length);
if (count == BINARY_ALL) {
count = length;
} else if (count == BINARY_NOCOUNT) {
count = 1;
}
last = cursor + ((count + 1) / 2);
if (count > length) {
|
|
>
|
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
|
break;
}
case 'h':
case 'H': {
unsigned char *last;
int c;
str = TclGetStringFromObj(objv[arg], &length);
arg++;
if (count == BINARY_ALL) {
count = length;
} else if (count == BINARY_NOCOUNT) {
count = 1;
}
last = cursor + ((count + 1) / 2);
if (count > length) {
|
| ︙ | | | ︙ | |
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
|
* array.
*/
listv = (Tcl_Obj**)(objv + arg);
listc = 1;
count = 1;
} else {
Tcl_ListObjGetElements(interp, objv[arg], &listc, &listv);
if (count == BINARY_ALL) {
count = listc;
}
}
arg++;
for (i = 0; i < count; i++) {
if (FormatNumber(interp, cmd, listv[i], &cursor)!=TCL_OK) {
|
|
|
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
|
* array.
*/
listv = (Tcl_Obj**)(objv + arg);
listc = 1;
count = 1;
} else {
TclListObjGetElements(interp, objv[arg], &listc, &listv);
if (count == BINARY_ALL) {
count = listc;
}
}
arg++;
for (i = 0; i < count; i++) {
if (FormatNumber(interp, cmd, listv[i], &cursor)!=TCL_OK) {
|
| ︙ | | | ︙ | |
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
|
Tcl_WrongNumArgs(interp, 2, objv,
"value formatString ?varName varName ...?");
return TCL_ERROR;
}
numberCachePtr = &numberCacheHash;
Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);
buffer = Tcl_GetByteArrayFromObj(objv[2], &length);
format = Tcl_GetString(objv[3]);
cursor = buffer;
arg = 4;
offset = 0;
while (*format != '\0') {
str = format;
flags = 0;
if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
|
|
|
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
|
Tcl_WrongNumArgs(interp, 2, objv,
"value formatString ?varName varName ...?");
return TCL_ERROR;
}
numberCachePtr = &numberCacheHash;
Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS);
buffer = Tcl_GetByteArrayFromObj(objv[2], &length);
format = TclGetString(objv[3]);
cursor = buffer;
arg = 4;
offset = 0;
while (*format != '\0') {
str = format;
flags = 0;
if (!GetFormatSpec(&format, &cmd, &count, &flags)) {
|
| ︙ | | | ︙ | |
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
|
if (count > (length - offset) * 8) {
goto done;
}
}
src = buffer + offset;
valuePtr = Tcl_NewObj();
Tcl_SetObjLength(valuePtr, count);
dest = Tcl_GetString(valuePtr);
if (cmd == 'b') {
for (i = 0; i < count; i++) {
if (i % 8) {
value >>= 1;
} else {
value = *src++;
|
|
|
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
|
if (count > (length - offset) * 8) {
goto done;
}
}
src = buffer + offset;
valuePtr = Tcl_NewObj();
Tcl_SetObjLength(valuePtr, count);
dest = TclGetString(valuePtr);
if (cmd == 'b') {
for (i = 0; i < count; i++) {
if (i % 8) {
value >>= 1;
} else {
value = *src++;
|
| ︙ | | | ︙ | |
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
|
if (count > (length - offset)*2) {
goto done;
}
}
src = buffer + offset;
valuePtr = Tcl_NewObj();
Tcl_SetObjLength(valuePtr, count);
dest = Tcl_GetString(valuePtr);
if (cmd == 'h') {
for (i = 0; i < count; i++) {
if (i % 2) {
value >>= 4;
} else {
value = *src++;
|
|
|
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
|
if (count > (length - offset)*2) {
goto done;
}
}
src = buffer + offset;
valuePtr = Tcl_NewObj();
Tcl_SetObjLength(valuePtr, count);
dest = TclGetString(valuePtr);
if (cmd == 'h') {
for (i = 0; i < count; i++) {
if (i % 2) {
value >>= 4;
} else {
value = *src++;
|
| ︙ | | | ︙ | |
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
|
/*
* 32-bit integer values.
*/
case 'i':
case 'I':
case 'n':
if (Tcl_GetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
if (NeedReversing(type)) {
*(*cursorPtr)++ = (unsigned char) value;
*(*cursorPtr)++ = (unsigned char) (value >> 8);
*(*cursorPtr)++ = (unsigned char) (value >> 16);
*(*cursorPtr)++ = (unsigned char) (value >> 24);
|
|
|
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
|
/*
* 32-bit integer values.
*/
case 'i':
case 'I':
case 'n':
if (TclGetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
if (NeedReversing(type)) {
*(*cursorPtr)++ = (unsigned char) value;
*(*cursorPtr)++ = (unsigned char) (value >> 8);
*(*cursorPtr)++ = (unsigned char) (value >> 16);
*(*cursorPtr)++ = (unsigned char) (value >> 24);
|
| ︙ | | | ︙ | |
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
|
/*
* 16-bit integer values.
*/
case 's':
case 'S':
case 't':
if (Tcl_GetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
if (NeedReversing(type)) {
*(*cursorPtr)++ = (unsigned char) value;
*(*cursorPtr)++ = (unsigned char) (value >> 8);
} else {
*(*cursorPtr)++ = (unsigned char) (value >> 8);
*(*cursorPtr)++ = (unsigned char) value;
}
return TCL_OK;
/*
* 8-bit integer values.
*/
case 'c':
if (Tcl_GetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
*(*cursorPtr)++ = (unsigned char) value;
return TCL_OK;
default:
Tcl_Panic("unexpected fallthrough");
|
|
|
|
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
|
/*
* 16-bit integer values.
*/
case 's':
case 'S':
case 't':
if (TclGetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
if (NeedReversing(type)) {
*(*cursorPtr)++ = (unsigned char) value;
*(*cursorPtr)++ = (unsigned char) (value >> 8);
} else {
*(*cursorPtr)++ = (unsigned char) (value >> 8);
*(*cursorPtr)++ = (unsigned char) value;
}
return TCL_OK;
/*
* 8-bit integer values.
*/
case 'c':
if (TclGetLongFromObj(interp, src, &value) != TCL_OK) {
return TCL_ERROR;
}
*(*cursorPtr)++ = (unsigned char) value;
return TCL_OK;
default:
Tcl_Panic("unexpected fallthrough");
|
| ︙ | | | ︙ | |