wasCSharpSQLite – Blame information for rev 4

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 * BinaryCmd.java --
3 *
4 * Implements the built-in "binary" Tcl command.
5 *
6 * Copyright (c) 1999 Christian Krone.
7 * Copyright (c) 1997 by Sun Microsystems, Inc.
8 *
9 * See the file "license.terms" for information on usage and
10 * redistribution of this file, and for a DISCLAIMER OF ALL
11 * WARRANTIES.
12 *
13 * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
14 *
15 * RCS @(#) $Id: BinaryCmd.java,v 1.2 2002/05/07 06:58:06 mdejong Exp $
16 *
17 */
18 using System;
19 using System.Text;
20 using System.IO;
21 namespace tcl.lang
22 {
23  
24 /*
25 * This class implements the built-in "binary" command in Tcl.
26 */
27  
28 class BinaryCmd : Command
29 {
30  
31 private static readonly string[] validCmds = new string[] { "format", "scan" };
32 private const string HEXDIGITS = "0123456789abcdef";
33  
34 private const int CMD_FORMAT = 0;
35 private const int CMD_SCAN = 1;
36  
37 // The following constants are used by GetFormatSpec to indicate various
38 // special conditions in the parsing of a format specifier.
39  
40 // Use all elements in the argument.
41 private const int BINARY_ALL = -1;
42 // No count was specified in format.
43 private const int BINARY_NOCOUNT = -2;
44 // End of format was found.
45 private const char FORMAT_END = ' ';
46  
47 public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
48 {
49 int arg; // Index of next argument to consume.
50 char[] format = null; // User specified format string.
51 char cmd; // Current format character.
52 int cursor; // Current position within result buffer.
53 int maxPos; // Greatest position within result buffer that
54 // cursor has visited.
55 int value = 0; // Current integer value to be packed.
56 // Initialized to avoid compiler warning.
57 int offset, size = 0, length;//, index;
58  
59 if ( argv.Length < 2 )
60 {
61 throw new TclNumArgsException( interp, 1, argv, "option ?arg arg ...?" );
62 }
63 int cmdIndex = TclIndex.get( interp, argv[1], validCmds, "option", 0 );
64  
65 switch ( cmdIndex )
66 {
67  
68 case CMD_FORMAT:
69 {
70 if ( argv.Length < 3 )
71 {
72 throw new TclNumArgsException( interp, 2, argv, "formatString ?arg arg ...?" );
73 }
74  
75 // To avoid copying the data, we format the string in two passes.
76 // The first pass computes the size of the output buffer. The
77 // second pass places the formatted data into the buffer.
78  
79 format = argv[2].ToString().ToCharArray();
80 arg = 3;
81 length = 0;
82 offset = 0;
83 System.Int32 parsePos = 0;
84  
85 while ( ( cmd = GetFormatSpec( format, ref parsePos ) ) != FORMAT_END )
86 {
87 int count = GetFormatCount( format, ref parsePos );
88  
89 switch ( cmd )
90 {
91  
92 case 'a':
93 case 'A':
94 case 'b':
95 case 'B':
96 case 'h':
97 case 'H':
98 {
99 // For string-type specifiers, the count corresponds
100 // to the number of bytes in a single argument.
101  
102 if ( arg >= argv.Length )
103 {
104 missingArg( interp );
105 }
106 if ( count == BINARY_ALL )
107 {
108 count = TclByteArray.getLength( interp, argv[arg] );
109 }
110 else if ( count == BINARY_NOCOUNT )
111 {
112 count = 1;
113 }
114 arg++;
115 switch ( cmd )
116 {
117  
118 case 'a':
119 case 'A':
120 offset += count;
121 break;
122  
123 case 'b':
124 case 'B':
125 offset += ( count + 7 ) / 8;
126 break;
127  
128 case 'h':
129 case 'H':
130 offset += ( count + 1 ) / 2;
131 break;
132 }
133 break;
134 }
135  
136 case 'c':
137 case 's':
138 case 'S':
139 case 'i':
140 case 'I':
141 case 'f':
142 case 'd':
143 {
144 if ( arg >= argv.Length )
145 {
146 missingArg( interp );
147 }
148 switch ( cmd )
149 {
150  
151 case 'c':
152 size = 1;
153 break;
154  
155 case 's':
156 case 'S':
157 size = 2;
158 break;
159  
160 case 'i':
161 case 'I':
162 size = 4;
163 break;
164  
165 case 'f':
166 size = 4;
167 break;
168  
169 case 'd':
170 size = 8;
171 break;
172 }
173  
174 // For number-type specifiers, the count corresponds
175 // to the number of elements in the list stored in
176 // a single argument. If no count is specified, then
177 // the argument is taken as a single non-list value.
178  
179 if ( count == BINARY_NOCOUNT )
180 {
181 arg++;
182 count = 1;
183 }
184 else
185 {
186 int listc = TclList.getLength( interp, argv[arg++] );
187 if ( count == BINARY_ALL )
188 {
189 count = listc;
190 }
191 else if ( count > listc )
192 {
193 throw new TclException( interp, "number of elements in list" + " does not match count" );
194 }
195 }
196 offset += count * size;
197 break;
198 }
199  
200 case 'x':
201 {
202 if ( count == BINARY_ALL )
203 {
204 throw new TclException( interp, "cannot use \"*\"" + " in format string with \"x\"" );
205 }
206 if ( count == BINARY_NOCOUNT )
207 {
208 count = 1;
209 }
210 offset += count;
211 break;
212 }
213  
214 case 'X':
215 {
216 if ( count == BINARY_NOCOUNT )
217 {
218 count = 1;
219 }
220 if ( ( count > offset ) || ( count == BINARY_ALL ) )
221 {
222 count = offset;
223 }
224 if ( offset > length )
225 {
226 length = offset;
227 }
228 offset -= count;
229 break;
230 }
231  
232 case '@':
233 {
234 if ( offset > length )
235 {
236 length = offset;
237 }
238 if ( count == BINARY_ALL )
239 {
240 offset = length;
241 }
242 else if ( count == BINARY_NOCOUNT )
243 {
244 alephWithoutCount( interp );
245 }
246 else
247 {
248 offset = count;
249 }
250 break;
251 }
252  
253 default:
254 {
255 badField( interp, cmd );
256 }
257 break;
258  
259 }
260 }
261 if ( offset > length )
262 {
263 length = offset;
264 }
265 if ( length == 0 )
266 {
267 return TCL.CompletionCode.RETURN;
268 }
269  
270 // Prepare the result object by preallocating the calculated
271 // number of bytes and filling with nulls.
272  
273 TclObject resultObj = TclByteArray.newInstance();
274 byte[] resultBytes = TclByteArray.setLength( interp, resultObj, length );
275 interp.setResult( resultObj );
276  
277 // Pack the data into the result object. Note that we can skip
278 // the error checking during this pass, since we have already
279 // parsed the string once.
280  
281 arg = 3;
282 cursor = 0;
283 maxPos = cursor;
284 parsePos = 0;
285  
286 while ( ( cmd = GetFormatSpec( format, ref parsePos ) ) != FORMAT_END )
287 {
288 int count = GetFormatCount( format, ref parsePos );
289  
290 if ( ( count == 0 ) && ( cmd != '@' ) )
291 {
292 arg++;
293 continue;
294 }
295  
296 switch ( cmd )
297 {
298  
299 case 'a':
300 case 'A':
301 {
302 byte pad = ( cmd == 'a' ) ? (byte)0 : (byte)SupportClass.Identity( ' ' );
303 byte[] bytes = TclByteArray.getBytes( interp, argv[arg++] );
304 length = bytes.Length;
305  
306 if ( count == BINARY_ALL )
307 {
308 count = length;
309 }
310 else if ( count == BINARY_NOCOUNT )
311 {
312 count = 1;
313 }
314 if ( length >= count )
315 {
316 Array.Copy( bytes, 0, resultBytes, cursor, count );
317 }
318 else
319 {
320 Array.Copy( bytes, 0, resultBytes, cursor, length );
321 for ( int ix = 0; ix < count - length; ix++ )
322 {
323 resultBytes[cursor + length + ix] = pad;
324 }
325 }
326 cursor += count;
327 break;
328 }
329  
330 case 'b':
331 case 'B':
332 {
333 char[] str = argv[arg++].ToString().ToCharArray();
334 if ( count == BINARY_ALL )
335 {
336 count = str.Length;
337 }
338 else if ( count == BINARY_NOCOUNT )
339 {
340 count = 1;
341 }
342 int last = cursor + ( ( count + 7 ) / 8 );
343 if ( count > str.Length )
344 {
345 count = str.Length;
346 }
347 if ( cmd == 'B' )
348 {
349 for ( offset = 0; offset < count; offset++ )
350 {
351 value <<= 1;
352 if ( str[offset] == '1' )
353 {
354 value |= 1;
355 }
356 else if ( str[offset] != '0' )
357 {
358 expectedButGot( interp, "binary", new string( str ) );
359 }
360 if ( ( ( offset + 1 ) % 8 ) == 0 )
361 {
362 resultBytes[cursor++] = (byte)value;
363 value = 0;
364 }
365 }
366 }
367 else
368 {
369 for ( offset = 0; offset < count; offset++ )
370 {
371 value >>= 1;
372 if ( str[offset] == '1' )
373 {
374 value |= 128;
375 }
376 else if ( str[offset] != '0' )
377 {
378 expectedButGot( interp, "binary", new string( str ) );
379 }
380 if ( ( ( offset + 1 ) % 8 ) == 0 )
381 {
382 resultBytes[cursor++] = (byte)value;
383 value = 0;
384 }
385 }
386 }
387 if ( ( offset % 8 ) != 0 )
388 {
389 if ( cmd == 'B' )
390 {
391 value <<= 8 - ( offset % 8 );
392 }
393 else
394 {
395 value >>= 8 - ( offset % 8 );
396 }
397 resultBytes[cursor++] = (byte)value;
398 }
399 while ( cursor < last )
400 {
401 resultBytes[cursor++] = 0;
402 }
403 break;
404 }
405  
406 case 'h':
407 case 'H':
408 {
409 char[] str = argv[arg++].ToString().ToCharArray();
410 if ( count == BINARY_ALL )
411 {
412 count = str.Length;
413 }
414 else if ( count == BINARY_NOCOUNT )
415 {
416 count = 1;
417 }
418 int last = cursor + ( ( count + 1 ) / 2 );
419 if ( count > str.Length )
420 {
421 count = str.Length;
422 }
423 if ( cmd == 'H' )
424 {
425 for ( offset = 0; offset < count; offset++ )
426 {
427 value <<= 4;
428 int c = HEXDIGITS.IndexOf( Char.ToLower( str[offset] ) );
429 if ( c < 0 )
430 {
431 expectedButGot( interp, "hexadecimal", new string( str ) );
432 }
433 value |= ( c & 0xf );
434 if ( ( offset % 2 ) != 0 )
435 {
436 resultBytes[cursor++] = (byte)value;
437 value = 0;
438 }
439 }
440 }
441 else
442 {
443 for ( offset = 0; offset < count; offset++ )
444 {
445 value >>= 4;
446 int c = HEXDIGITS.IndexOf( Char.ToLower( str[offset] ) );
447 if ( c < 0 )
448 {
449 expectedButGot( interp, "hexadecimal", new string( str ) );
450 }
451 value |= ( ( c << 4 ) & 0xf0 );
452 if ( ( offset % 2 ) != 0 )
453 {
454 resultBytes[cursor++] = (byte)value;
455 value = 0;
456 }
457 }
458 }
459 if ( ( offset % 2 ) != 0 )
460 {
461 if ( cmd == 'H' )
462 {
463 value <<= 4;
464 }
465 else
466 {
467 value >>= 4;
468 }
469 resultBytes[cursor++] = (byte)value;
470 }
471 while ( cursor < last )
472 {
473 resultBytes[cursor++] = 0;
474 }
475 break;
476 }
477  
478 case 'c':
479 case 's':
480 case 'S':
481 case 'i':
482 case 'I':
483 case 'f':
484 case 'd':
485 {
486 TclObject[] listv;
487  
488 if ( count == BINARY_NOCOUNT )
489 {
490 listv = new TclObject[1];
491 listv[0] = argv[arg++];
492 count = 1;
493 }
494 else
495 {
496 listv = TclList.getElements( interp, argv[arg++] );
497 if ( count == BINARY_ALL )
498 {
499 count = listv.Length;
500 }
501 }
502 for ( int ix = 0; ix < count; ix++ )
503 {
504 cursor = FormatNumber( interp, cmd, listv[ix], resultBytes, cursor );
505 }
506 break;
507 }
508  
509 case 'x':
510 {
511 if ( count == BINARY_NOCOUNT )
512 {
513 count = 1;
514 }
515 for ( int ix = 0; ix < count; ix++ )
516 {
517 resultBytes[cursor++] = 0;
518 }
519 break;
520 }
521  
522 case 'X':
523 {
524 if ( cursor > maxPos )
525 {
526 maxPos = cursor;
527 }
528 if ( count == BINARY_NOCOUNT )
529 {
530 count = 1;
531 }
532 if ( count == BINARY_ALL || count > cursor )
533 {
534 cursor = 0;
535 }
536 else
537 {
538 cursor -= count;
539 }
540 break;
541 }
542  
543 case '@':
544 {
545 if ( cursor > maxPos )
546 {
547 maxPos = cursor;
548 }
549 if ( count == BINARY_ALL )
550 {
551 cursor = maxPos;
552 }
553 else
554 {
555 cursor = count;
556 }
557 break;
558 }
559 }
560 }
561 break;
562 }
563  
564 case CMD_SCAN:
565 {
566 if ( argv.Length < 4 )
567 {
568 throw new TclNumArgsException( interp, 2, argv, "value formatString ?varName varName ...?" );
569 }
570 byte[] src = TclByteArray.getBytes( interp, argv[2] );
571 length = src.Length;
572 format = argv[3].ToString().ToCharArray();
573 arg = 4;
574 cursor = 0;
575 offset = 0;
576 System.Int32 parsePos = 0;
577  
578 while ( ( cmd = GetFormatSpec( format, ref parsePos ) ) != FORMAT_END )
579 {
580 int count = GetFormatCount( format, ref parsePos );
581  
582 switch ( cmd )
583 {
584  
585 case 'a':
586 case 'A':
587 {
588 if ( arg >= argv.Length )
589 {
590 missingArg( interp );
591 }
592 if ( count == BINARY_ALL )
593 {
594 count = length - offset;
595 }
596 else
597 {
598 if ( count == BINARY_NOCOUNT )
599 {
600 count = 1;
601 }
602 if ( count > length - offset )
603 {
604 break;
605 }
606 }
607  
608 size = count;
609  
610 // Trim trailing nulls and spaces, if necessary.
611  
612 if ( cmd == 'A' )
613 {
614 while ( size > 0 )
615 {
616 if ( src[offset + size - 1] != '\x0000' && src[offset + size - 1] != ' ' )
617 {
618 break;
619 }
620 size--;
621 }
622 }
623  
624 interp.setVar( argv[arg++], TclByteArray.newInstance( src, offset, size ), 0 );
625  
626 offset += count;
627 break;
628 }
629  
630 case 'b':
631 case 'B':
632 {
633 if ( arg >= argv.Length )
634 {
635 missingArg( interp );
636 }
637 if ( count == BINARY_ALL )
638 {
639 count = ( length - offset ) * 8;
640 }
641 else
642 {
643 if ( count == BINARY_NOCOUNT )
644 {
645 count = 1;
646 }
647 if ( count > ( length - offset ) * 8 )
648 {
649 break;
650 }
651 }
652 StringBuilder s = new StringBuilder( count );
653 int thisOffset = offset;
654  
655 if ( cmd == 'b' )
656 {
657 for ( int ix = 0; ix < count; ix++ )
658 {
659 if ( ( ix % 8 ) != 0 )
660 {
661 value >>= 1;
662 }
663 else
664 {
665 value = src[thisOffset++];
666 }
667 s.Append( ( value & 1 ) != 0 ? '1' : '0' );
668 }
669 }
670 else
671 {
672 for ( int ix = 0; ix < count; ix++ )
673 {
674 if ( ( ix % 8 ) != 0 )
675 {
676 value <<= 1;
677 }
678 else
679 {
680 value = src[thisOffset++];
681 }
682 s.Append( ( value & 0x80 ) != 0 ? '1' : '0' );
683 }
684 }
685  
686 interp.setVar( argv[arg++], TclString.newInstance( s.ToString() ), 0 );
687  
688 offset += ( count + 7 ) / 8;
689 break;
690 }
691  
692 case 'h':
693 case 'H':
694 {
695 if ( arg >= argv.Length )
696 {
697 missingArg( interp );
698 }
699 if ( count == BINARY_ALL )
700 {
701 count = ( length - offset ) * 2;
702 }
703 else
704 {
705 if ( count == BINARY_NOCOUNT )
706 {
707 count = 1;
708 }
709 if ( count > ( length - offset ) * 2 )
710 {
711 break;
712 }
713 }
714 StringBuilder s = new StringBuilder( count );
715 int thisOffset = offset;
716  
717 if ( cmd == 'h' )
718 {
719 for ( int ix = 0; ix < count; ix++ )
720 {
721 if ( ( ix % 2 ) != 0 )
722 {
723 value >>= 4;
724 }
725 else
726 {
727 value = src[thisOffset++];
728 }
729 s.Append( HEXDIGITS[value & 0xf] );
730 }
731 }
732 else
733 {
734 for ( int ix = 0; ix < count; ix++ )
735 {
736 if ( ( ix % 2 ) != 0 )
737 {
738 value <<= 4;
739 }
740 else
741 {
742 value = src[thisOffset++];
743 }
744 s.Append( HEXDIGITS[value >> 4 & 0xf] );
745 }
746 }
747  
748 interp.setVar( argv[arg++], TclString.newInstance( s.ToString() ), 0 );
749  
750 offset += ( count + 1 ) / 2;
751 break;
752 }
753  
754 case 'c':
755 case 's':
756 case 'S':
757 case 'i':
758 case 'I':
759 case 'f':
760 case 'd':
761 {
762 if ( arg >= argv.Length )
763 {
764 missingArg( interp );
765 }
766 switch ( cmd )
767 {
768  
769 case 'c':
770 size = 1;
771 break;
772  
773 case 's':
774 case 'S':
775 size = 2;
776 break;
777  
778 case 'i':
779 case 'I':
780 size = 4;
781 break;
782  
783 case 'f':
784 size = 4;
785 break;
786  
787 case 'd':
788 size = 8;
789 break;
790 }
791 TclObject valueObj;
792 if ( count == BINARY_NOCOUNT )
793 {
794 if ( length - offset < size )
795 {
796 break;
797 }
798 valueObj = ScanNumber( src, offset, cmd );
799 offset += size;
800 }
801 else
802 {
803 if ( count == BINARY_ALL )
804 {
805 count = ( length - offset ) / size;
806 }
807 if ( length - offset < count * size )
808 {
809 break;
810 }
811 valueObj = TclList.newInstance();
812 int thisOffset = offset;
813 for ( int ix = 0; ix < count; ix++ )
814 {
815 TclList.append( null, valueObj, ScanNumber( src, thisOffset, cmd ) );
816 thisOffset += size;
817 }
818 offset += count * size;
819 }
820  
821 interp.setVar( argv[arg++], valueObj, 0 );
822  
823 break;
824 }
825  
826 case 'x':
827 {
828 if ( count == BINARY_NOCOUNT )
829 {
830 count = 1;
831 }
832 if ( count == BINARY_ALL || count > length - offset )
833 {
834 offset = length;
835 }
836 else
837 {
838 offset += count;
839 }
840 break;
841 }
842  
843 case 'X':
844 {
845 if ( count == BINARY_NOCOUNT )
846 {
847 count = 1;
848 }
849 if ( count == BINARY_ALL || count > offset )
850 {
851 offset = 0;
852 }
853 else
854 {
855 offset -= count;
856 }
857 break;
858 }
859  
860 case '@':
861 {
862 if ( count == BINARY_NOCOUNT )
863 {
864 alephWithoutCount( interp );
865 }
866 if ( count == BINARY_ALL || count > length )
867 {
868 offset = length;
869 }
870 else
871 {
872 offset = count;
873 }
874 break;
875 }
876  
877 default:
878 {
879 badField( interp, cmd );
880 }
881 break;
882  
883 }
884 }
885  
886 // Set the result to the last position of the cursor.
887  
888 interp.setResult( arg - 4 );
889 }
890 break;
891 }
892 return TCL.CompletionCode.RETURN;
893 }
894 private char GetFormatSpec( char[] format, ref System.Int32 parsePos )
895 // Current position in input.
896 {
897 int ix = parsePos;
898  
899 // Skip any leading blanks.
900  
901 while ( ix < format.Length && format[ix] == ' ' )
902 {
903 ix++;
904 }
905  
906 // The string was empty, except for whitespace, so fail.
907  
908 if ( ix >= format.Length )
909 {
910 parsePos = ix;
911 return FORMAT_END;
912 }
913  
914 // Extract the command character.
915  
916 parsePos = ix + 1;
917  
918 return format[ix++];
919 }
920 private int GetFormatCount( char[] format, ref System.Int32 parsePos )
921 // Current position in input.
922 {
923 int ix = parsePos;
924  
925 // Extract any trailing digits or '*'.
926  
927 if ( ix < format.Length && format[ix] == '*' )
928 {
929 parsePos = ix + 1;
930 return BINARY_ALL;
931 }
932 else if ( ix < format.Length && System.Char.IsDigit( format[ix] ) )
933 {
934 int length = 1;
935 while ( ix + length < format.Length && System.Char.IsDigit( format[ix + length] ) )
936 {
937 length++;
938 }
939 parsePos = ix + length;
940 return System.Int32.Parse( new string( format, ix, length ) );
941 }
942 else
943 {
944 return BINARY_NOCOUNT;
945 }
946 }
947 internal static int FormatNumber( Interp interp, char type, TclObject src, byte[] resultBytes, int cursor )
948 {
949 if ( type == 'd' )
950 {
951 double dvalue = TclDouble.get( interp, src );
952 MemoryStream ms = new MemoryStream( resultBytes, cursor, 8 );
953 BinaryWriter writer = new BinaryWriter( ms );
954 writer.Write( dvalue );
955 cursor += 8;
956 writer.Close();
957 ms.Close();
958 }
959 else if ( type == 'f' )
960 {
961 float fvalue = (float)TclDouble.get( interp, src );
962 MemoryStream ms = new MemoryStream( resultBytes, cursor, 4 );
963 BinaryWriter writer = new BinaryWriter( ms );
964 writer.Write( fvalue );
965 cursor += 4;
966 writer.Close();
967 ms.Close();
968 }
969 else
970 {
971 int value = TclInteger.get( interp, src );
972  
973 if ( type == 'c' )
974 {
975 resultBytes[cursor++] = (byte)value;
976 }
977 else if ( type == 's' )
978 {
979 resultBytes[cursor++] = (byte)value;
980 resultBytes[cursor++] = (byte)( value >> 8 );
981 }
982 else if ( type == 'S' )
983 {
984 resultBytes[cursor++] = (byte)( value >> 8 );
985 resultBytes[cursor++] = (byte)value;
986 }
987 else if ( type == 'i' )
988 {
989 resultBytes[cursor++] = (byte)value;
990 resultBytes[cursor++] = (byte)( value >> 8 );
991 resultBytes[cursor++] = (byte)( value >> 16 );
992 resultBytes[cursor++] = (byte)( value >> 24 );
993 }
994 else if ( type == 'I' )
995 {
996 resultBytes[cursor++] = (byte)( value >> 24 );
997 resultBytes[cursor++] = (byte)( value >> 16 );
998 resultBytes[cursor++] = (byte)( value >> 8 );
999 resultBytes[cursor++] = (byte)value;
1000 }
1001 }
1002 return cursor;
1003 }
1004 private static TclObject ScanNumber( byte[] src, int pos, int type )
1005 // Format character from "binary scan"
1006 {
1007 switch ( type )
1008 {
1009  
1010 case 'c':
1011 {
1012 return TclInteger.newInstance( (sbyte)src[pos] );
1013 }
1014  
1015 case 's':
1016 {
1017 short value = (short)( ( src[pos] & 0xff ) + ( ( src[pos + 1] & 0xff ) << 8 ) );
1018 return TclInteger.newInstance( (int)value );
1019 }
1020  
1021 case 'S':
1022 {
1023 short value = (short)( ( src[pos + 1] & 0xff ) + ( ( src[pos] & 0xff ) << 8 ) );
1024 return TclInteger.newInstance( (int)value );
1025 }
1026  
1027 case 'i':
1028 {
1029 int value = ( src[pos] & 0xff ) + ( ( src[pos + 1] & 0xff ) << 8 ) + ( ( src[pos + 2] & 0xff ) << 16 ) + ( ( src[pos + 3] & 0xff ) << 24 );
1030 return TclInteger.newInstance( value );
1031 }
1032 case 'I':
1033 {
1034 int value = ( src[pos + 3] & 0xff ) + ( ( src[pos + 2] & 0xff ) << 8 ) + ( ( src[pos + 1] & 0xff ) << 16 ) + ( ( src[pos] & 0xff ) << 24 );
1035 return TclInteger.newInstance( value );
1036 }
1037 case 'f':
1038 {
1039 MemoryStream ms = new MemoryStream( src, pos, 4, false );
1040 BinaryReader reader = new BinaryReader( ms );
1041 double fvalue = reader.ReadSingle();
1042 reader.Close();
1043 ms.Close();
1044 return TclDouble.newInstance( fvalue );
1045 }
1046 case 'd':
1047 {
1048 MemoryStream ms = new MemoryStream( src, pos, 8, false );
1049 BinaryReader reader = new BinaryReader( ms );
1050 double dvalue = reader.ReadDouble();
1051 reader.Close();
1052 ms.Close();
1053 return TclDouble.newInstance( dvalue );
1054 }
1055 }
1056 return null;
1057 }
1058  
1059 /// <summary> Called whenever a format specifier was detected
1060 /// but there are not enough arguments specified.
1061 ///
1062 /// </summary>
1063 /// <param name="interp"> - The TclInterp which called the cmdProc method.
1064 /// </param>
1065  
1066 private static void missingArg( Interp interp )
1067 {
1068 throw new TclException( interp, "not enough arguments for all format specifiers" );
1069 }
1070  
1071 /// <summary> Called whenever an invalid format specifier was detected.
1072 ///
1073 /// </summary>
1074 /// <param name="interp"> - The TclInterp which called the cmdProc method.
1075 /// </param>
1076 /// <param name="cmd"> - The invalid field specifier.
1077 /// </param>
1078  
1079 private static void badField( Interp interp, char cmd )
1080 {
1081 throw new TclException( interp, "bad field specifier \"" + cmd + "\"" );
1082 }
1083  
1084 /// <summary> Called whenever a letter aleph character (@) was detected
1085 /// but there was no count specified.
1086 ///
1087 /// </summary>
1088 /// <param name="interp"> - The TclInterp which called the cmdProc method.
1089 /// </param>
1090  
1091 private static void alephWithoutCount( Interp interp )
1092 {
1093 throw new TclException( interp, "missing count for \"@\" field specifier" );
1094 }
1095  
1096 /// <summary> Called whenever a format was found which restricts the valid range
1097 /// of characters in the specified string, but the string contains
1098 /// at least one char not in this range.
1099 ///
1100 /// </summary>
1101 /// <param name="interp"> - The TclInterp which called the cmdProc method.
1102 /// </param>
1103  
1104 private static void expectedButGot( Interp interp, string expected, string str )
1105 {
1106 throw new TclException( interp, "expected " + expected + " string but got \"" + str + "\" instead" );
1107 }
1108 } // end BinaryCmd
1109 }