/// <summary> Returns the bytes of a ByteArray object. If tobj is not a ByteArray /// object, an attempt will be made to convert it to a ByteArray. <p> /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="tobj">the byte array object. /// </param> /// <returns> a byte array. /// </returns> /// <exception cref=""> TclException if tobj is not a valid ByteArray. /// </exception> public static byte[] getBytes(Interp interp, TclObject tobj) { setByteArrayFromAny(interp, tobj); TclByteArray tbyteArray = (TclByteArray)tobj.InternalRep; return(tbyteArray.bytes); }
/// <summary> Queries the length of the byte array. If tobj is not a byte array /// object, an attempt will be made to convert it to a byte array. /// /// </summary> /// <param name="interp">current interpreter. /// </param> /// <param name="tobj">the TclObject to use as a byte array. /// </param> /// <returns> the length of the byte array. /// </returns> /// <exception cref=""> TclException if tobj is not a valid byte array. /// </exception> public static int getLength(Interp interp, TclObject tobj) { setByteArrayFromAny(interp, tobj); TclByteArray tbyteArray = (TclByteArray)tobj.InternalRep; return(tbyteArray.used); }
public static TclObject Tcl_NewByteArrayObj(string value, int bytes) { if (value == null || bytes == 0) { return(TclByteArray.NewInstance()); } else { return(TclByteArray.NewInstance(System.Text.Encoding.UTF8.GetBytes(value.Substring(0, bytes)))); } }
public static TclObject Tcl_NewByteArrayObj(byte[] value, int bytes) { if (value == null || value.Length == 0 || bytes == 0) { return(TclByteArray.NewInstance()); } else { return(TclByteArray.NewInstance(value, 0, bytes)); } }
/// <summary> /// This method changes the length of the byte array for this /// object. Once the caller has set the length of the array, it /// is acceptable to directly modify the bytes in the array up until /// Tcl_GetStringFromObj() has been called on this object. /// /// Results: /// The new byte array of the specified length. /// /// Side effects: /// Allocates enough memory for an array of bytes of the requested /// size. When growing the array, the old array is copied to the /// new array; new bytes are undefined. When shrinking, the /// old array is truncated to the specified length. /// </summary> public static byte[] SetLength(Interp interp, TclObject tobj, int length) { if (tobj.Shared) { throw new TclRuntimeError("TclByteArray.setLength() called with shared object"); } setByteArrayFromAny(interp, tobj); TclByteArray tbyteArray = (TclByteArray)tobj.InternalRep; if (length > tbyteArray.bytes.Length) { byte[] newBytes = new byte[length]; Array.Copy(tbyteArray.bytes, 0, newBytes, 0, tbyteArray.used); tbyteArray.bytes = newBytes; } tobj.invalidateStringRep(); tbyteArray.used = length; return(tbyteArray.bytes); }
/// <summary> This procedure is invoked to process the "read" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv) { Channel chan; // The channel being operated on this // method int i = 1; // Index to the next arg in argv int toRead = 0; // Number of bytes or chars to read from channel int charactersRead; // Number of bytes or chars read from channel bool readAll = true; // If true read-all else toRead bool noNewline = false; // If true, strip the newline if there TclObject result; if ((argv.Length != 2) && (argv.Length != 3)) { errorWrongNumArgs(interp, argv[0].ToString()); } if (argv[i].ToString().Equals("-nonewline")) { noNewline = true; i++; } if (i == argv.Length) { errorWrongNumArgs(interp, argv[0].ToString()); } chan = TclIO.getChannel(interp, argv[i].ToString()); if (chan == null) { throw new TclException(interp, "can not find channel named \"" + argv[i].ToString() + "\""); } // Consumed channel name. i++; // Compute how many bytes or chars to read, and see whether the final // noNewline should be dropped. if (i < argv.Length) { string arg = argv[i].ToString(); if (System.Char.IsDigit(arg[0])) { toRead = TclInteger.Get(interp, argv[i]); readAll = false; } else if (arg.Equals("nonewline")) { noNewline = true; } else { throw new TclException(interp, "bad argument \"" + arg + "\": should be \"nonewline\""); } } try { if ((System.Object)chan.Encoding == null) { result = TclByteArray.NewInstance(); } else { result = TclString.NewInstance(new StringBuilder(64)); } if (readAll) { charactersRead = chan.read(interp, result, TclIO.READ_ALL, 0); // If -nonewline was specified, and we have not hit EOF // and the last char is a "\n", then remove it and return. if (noNewline) { string inStr = result.ToString(); if ((charactersRead > 0) && (inStr[charactersRead - 1] == '\n')) { interp.SetResult(inStr.Substring(0, ((charactersRead - 1)) - (0))); return(TCL.CompletionCode.RETURN); } } } else { // FIXME: Bug here, the -nonewline flag must be respected // when reading a set number of bytes charactersRead = chan.read(interp, result, TclIO.READ_N_BYTES, toRead); } /* * // FIXME: Port this -nonewline logic from the C code. * if (charactersRead < 0) { * Tcl_ResetResult(interp); * Tcl_AppendResult(interp, "error reading \"", name, "\": ", * Tcl_PosixError(interp), (char *) NULL); * Tcl_DecrRefCount(resultPtr); * return TCL_ERROR; * } * * // If requested, remove the last newline in the channel if at EOF. * * if ((charactersRead > 0) && (newline != 0)) { * char *result; * int length; * * result = Tcl_GetStringFromObj(resultPtr, length); * if (result[length - 1] == '\n') { * Tcl_SetObjLength(resultPtr, length - 1); * } * } * */ interp.SetResult(result); } catch (IOException e) { throw new TclRuntimeError("ReadCmd.cmdProc() Error: IOException when reading " + chan.ChanName); } return(TCL.CompletionCode.RETURN); }
public static byte[] Tcl_GetByteArrayFromObj(TclObject to, out int n) { n = TclByteArray.getLength(null, to); return(Encoding.UTF8.GetBytes(to.ToString())); }
/// <summary> This procedure is invoked to process the "encoding" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv) { if (argv.Length < 2) { throw new TclNumArgsException(interp, 1, argv, "option ?arg ...?"); } int index = TclIndex.Get(interp, argv[1], validCmds, "option", 0); switch (index) { case OPT_CONVERTTO: case OPT_CONVERTFROM: { string tclEncoding; Encoding javaEncoding; TclObject data; if (argv.Length == 3) { tclEncoding = systemTclEncoding; data = argv[2]; } else if (argv.Length == 4) { tclEncoding = argv[2].ToString(); data = argv[3]; } else { throw new TclNumArgsException(interp, 2, argv, "?encoding? data"); } javaEncoding = getJavaName(tclEncoding); if ((System.Object)javaEncoding == null) { throw new TclException(interp, "unknown encoding \"" + tclEncoding + "\""); } try { if (index == OPT_CONVERTFROM) { // Treat the string as binary data byte[] bytes = TclByteArray.getBytes(interp, data); // ATK interp.SetResult(System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length)); } else { // Store the result as binary data // ATK byte[] bytes = data.ToString().getBytes(javaEncoding); byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data.ToString()); interp.SetResult(TclByteArray.NewInstance(bytes)); } } catch (IOException ex) { throw new TclRuntimeError("Encoding.cmdProc() error: " + "unsupported java encoding \"" + javaEncoding + "\""); } break; } case OPT_NAMES: { if (argv.Length > 2) { throw new TclNumArgsException(interp, 2, argv, null); } TclObject list = TclList.NewInstance(); for (int i = 0; i < tclNames.Length; i++) { TclList.Append(interp, list, TclString.NewInstance(tclNames[i])); } interp.SetResult(list); break; } case OPT_SYSTEM: { if (argv.Length > 3) { throw new TclNumArgsException(interp, 2, argv, "?encoding?"); } if (argv.Length == 2) { interp.SetResult(systemTclEncoding); } else { string tclEncoding = argv[2].ToString(); Encoding javaEncoding = getJavaName(tclEncoding); if (javaEncoding == null) { throw new TclException(interp, "unknown encoding \"" + tclEncoding + "\""); } systemTclEncoding = tclEncoding; systemJavaEncoding = javaEncoding; } break; } default: { throw new TclRuntimeError("Encoding.cmdProc() error: " + "incorrect index returned from TclIndex.get()"); } } return(TCL.CompletionCode.RETURN); }
private const char FORMAT_END = ' '; // End of format was found. public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv) { int arg; // Index of next argument to consume. char[] format = null; // User specified format string. char cmd; // Current format character. int cursor; // Current position within result buffer. int maxPos; // Greatest position within result buffer that cursor has visited. int value = 0; // Current integer value to be packed. int offset, size = 0, length; // Initialized to avoid compiler warning. if (argv.Length < 2) { throw new TclNumArgsException(interp, 1, argv, "option ?arg arg ...?"); } int cmdIndex = TclIndex.Get(interp, argv[1], _validCmds, "option", 0); switch (cmdIndex) { case CMD_FORMAT: { if (argv.Length < 3) { throw new TclNumArgsException(interp, 2, argv, "formatString ?arg arg ...?"); } // 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 = argv[2].ToString().ToCharArray(); arg = 3; length = 0; offset = 0; int parsePos = 0; while ((cmd = GetFormatSpec(format, ref parsePos)) != FORMAT_END) { int count = GetFormatCount(format, ref parsePos); switch (cmd) { case 'a': case 'A': case 'b': case 'B': case 'h': case 'H': { // For string-type specifiers, the count corresponds to the number of bytes in a single argument. if (arg >= argv.Length) { MissingArg(interp); } if (count == BINARY_ALL) { count = TclByteArray.getLength(interp, argv[arg]); } else if (count == BINARY_NOCOUNT) { count = 1; } arg++; switch (cmd) { case 'a': case 'A': offset += count; break; case 'b': case 'B': offset += (count + 7) / 8; break; case 'h': case 'H': offset += (count + 1) / 2; break; } break; } case 'c': case 's': case 'S': case 'i': case 'I': case 'f': case 'd': { if (arg >= argv.Length) { MissingArg(interp); } switch (cmd) { case 'c': size = 1; break; case 's': case 'S': size = 2; break; case 'i': case 'I': size = 4; break; case 'f': size = 4; break; case 'd': size = 8; break; } // For number-type specifiers, the count corresponds to the number of elements in the list stored in // a single argument. If no count is specified, then the argument is taken as a single non-list value. if (count == BINARY_NOCOUNT) { arg++; count = 1; } else { int listc = TclList.getLength(interp, argv[arg++]); if (count == BINARY_ALL) { count = listc; } else if (count > listc) { throw new TclException(interp, "number of elements in list" + " does not match count"); } } offset += count * size; break; } case 'x': { if (count == BINARY_ALL) { throw new TclException(interp, "cannot use \"*\"" + " in format string with \"x\""); } if (count == BINARY_NOCOUNT) { count = 1; } offset += count; break; } case 'X': { if (count == BINARY_NOCOUNT) { count = 1; } if (count > offset || count == BINARY_ALL) { count = offset; } if (offset > length) { length = offset; } offset -= count; break; } case '@': { if (offset > length) { length = offset; } if (count == BINARY_ALL) { offset = length; } else if (count == BINARY_NOCOUNT) { AlephWithoutCount(interp); } else { offset = count; } break; } default: { BadField(interp, cmd); } break; } } if (offset > length) { length = offset; } if (length == 0) { return(TCL.CompletionCode.RETURN); } // Prepare the result object by preallocating the calculated number of bytes and filling with nulls. TclObject resultObj = TclByteArray.NewInstance(); byte[] resultBytes = TclByteArray.SetLength(interp, resultObj, length); interp.SetResult(resultObj); // 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; cursor = 0; maxPos = cursor; parsePos = 0; while ((cmd = GetFormatSpec(format, ref parsePos)) != FORMAT_END) { int count = GetFormatCount(format, ref parsePos); if (count == 0 && cmd != '@') { arg++; continue; } switch (cmd) { case 'a': case 'A': { byte pad = (cmd == 'a' ? (byte)0 : (byte)SupportClass.Identity(' ')); byte[] bytes = TclByteArray.getBytes(interp, argv[arg++]); length = bytes.Length; if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; } if (length >= count) { Array.Copy(bytes, 0, resultBytes, cursor, count); } else { Array.Copy(bytes, 0, resultBytes, cursor, length); for (int ix = 0; ix < count - length; ix++) { resultBytes[cursor + length + ix] = pad; } } cursor += count; break; } case 'b': case 'B': { char[] str = argv[arg++].ToString().ToCharArray(); if (count == BINARY_ALL) { count = str.Length; } else if (count == BINARY_NOCOUNT) { count = 1; } int last = cursor + ((count + 7) / 8); if (count > str.Length) { count = str.Length; } if (cmd == 'B') { for (offset = 0; offset < count; offset++) { value <<= 1; if (str[offset] == '1') { value |= 1; } else if (str[offset] != '0') { ExpectedButGot(interp, "binary", new string(str)); } if (((offset + 1) % 8) == 0) { resultBytes[cursor++] = (byte)value; value = 0; } } } else { for (offset = 0; offset < count; offset++) { value >>= 1; if (str[offset] == '1') { value |= 128; } else if (str[offset] != '0') { ExpectedButGot(interp, "binary", new string(str)); } if (((offset + 1) % 8) == 0) { resultBytes[cursor++] = (byte)value; value = 0; } } } if ((offset % 8) != 0) { if (cmd == 'B') { value <<= 8 - (offset % 8); } else { value >>= 8 - (offset % 8); } resultBytes[cursor++] = (byte)value; } while (cursor < last) { resultBytes[cursor++] = 0; } break; } case 'h': case 'H': { char[] str = argv[arg++].ToString().ToCharArray(); if (count == BINARY_ALL) { count = str.Length; } else if (count == BINARY_NOCOUNT) { count = 1; } int last = cursor + ((count + 1) / 2); if (count > str.Length) { count = str.Length; } if (cmd == 'H') { for (offset = 0; offset < count; offset++) { value <<= 4; int c = HEXDIGITS.IndexOf(Char.ToLower(str[offset])); if (c < 0) { ExpectedButGot(interp, "hexadecimal", new string(str)); } value |= (c & 0xf); if ((offset % 2) != 0) { resultBytes[cursor++] = (byte)value; value = 0; } } } else { for (offset = 0; offset < count; offset++) { value >>= 4; int c = HEXDIGITS.IndexOf(Char.ToLower(str[offset])); if (c < 0) { ExpectedButGot(interp, "hexadecimal", new string(str)); } value |= ((c << 4) & 0xf0); if ((offset % 2) != 0) { resultBytes[cursor++] = (byte)value; value = 0; } } } if ((offset % 2) != 0) { if (cmd == 'H') { value <<= 4; } else { value >>= 4; } resultBytes[cursor++] = (byte)value; } while (cursor < last) { resultBytes[cursor++] = 0; } break; } case 'c': case 's': case 'S': case 'i': case 'I': case 'f': case 'd': { TclObject[] listv; if (count == BINARY_NOCOUNT) { listv = new TclObject[1]; listv[0] = argv[arg++]; count = 1; } else { listv = TclList.getElements(interp, argv[arg++]); if (count == BINARY_ALL) { count = listv.Length; } } for (int ix = 0; ix < count; ix++) { cursor = FormatNumber(interp, cmd, listv[ix], resultBytes, cursor); } break; } case 'x': { if (count == BINARY_NOCOUNT) { count = 1; } for (int ix = 0; ix < count; ix++) { resultBytes[cursor++] = 0; } break; } case 'X': { if (cursor > maxPos) { maxPos = cursor; } if (count == BINARY_NOCOUNT) { count = 1; } if (count == BINARY_ALL || count > cursor) { cursor = 0; } else { cursor -= count; } break; } case '@': { if (cursor > maxPos) { maxPos = cursor; } if (count == BINARY_ALL) { cursor = maxPos; } else { cursor = count; } break; } } } break; } case CMD_SCAN: { if (argv.Length < 4) { throw new TclNumArgsException(interp, 2, argv, "value formatString ?varName varName ...?"); } byte[] src = TclByteArray.getBytes(interp, argv[2]); length = src.Length; format = argv[3].ToString().ToCharArray(); arg = 4; cursor = 0; offset = 0; int parsePos = 0; while ((cmd = GetFormatSpec(format, ref parsePos)) != FORMAT_END) { int count = GetFormatCount(format, ref parsePos); switch (cmd) { case 'a': case 'A': { if (arg >= argv.Length) { MissingArg(interp); } if (count == BINARY_ALL) { count = length - offset; } else { if (count == BINARY_NOCOUNT) { count = 1; } if (count > length - offset) { break; } } size = count; // Trim trailing nulls and spaces, if necessary. if (cmd == 'A') { while (size > 0) { if (src[offset + size - 1] != '\x0000' && src[offset + size - 1] != ' ') { break; } size--; } } interp.SetVar(argv[arg++], TclByteArray.NewInstance(src, offset, size), 0); offset += count; break; } case 'b': case 'B': { if (arg >= argv.Length) { MissingArg(interp); } if (count == BINARY_ALL) { count = (length - offset) * 8; } else { if (count == BINARY_NOCOUNT) { count = 1; } if (count > (length - offset) * 8) { break; } } StringBuilder s = new StringBuilder(count); int thisOffset = offset; if (cmd == 'b') { for (int ix = 0; ix < count; ix++) { if ((ix % 8) != 0) { value >>= 1; } else { value = src[thisOffset++]; } s.Append((value & 1) != 0 ? '1' : '0'); } } else { for (int ix = 0; ix < count; ix++) { if ((ix % 8) != 0) { value <<= 1; } else { value = src[thisOffset++]; } s.Append((value & 0x80) != 0 ? '1' : '0'); } } interp.SetVar(argv[arg++], TclString.NewInstance(s.ToString()), 0); offset += (count + 7) / 8; break; } case 'h': case 'H': { if (arg >= argv.Length) { MissingArg(interp); } if (count == BINARY_ALL) { count = (length - offset) * 2; } else { if (count == BINARY_NOCOUNT) { count = 1; } if (count > (length - offset) * 2) { break; } } StringBuilder s = new StringBuilder(count); int thisOffset = offset; if (cmd == 'h') { for (int ix = 0; ix < count; ix++) { if ((ix % 2) != 0) { value >>= 4; } else { value = src[thisOffset++]; } s.Append(HEXDIGITS[value & 0xf]); } } else { for (int ix = 0; ix < count; ix++) { if ((ix % 2) != 0) { value <<= 4; } else { value = src[thisOffset++]; } s.Append(HEXDIGITS[value >> 4 & 0xf]); } } interp.SetVar(argv[arg++], TclString.NewInstance(s.ToString()), 0); offset += (count + 1) / 2; break; } case 'c': case 's': case 'S': case 'i': case 'I': case 'f': case 'd': { if (arg >= argv.Length) { MissingArg(interp); } switch (cmd) { case 'c': size = 1; break; case 's': case 'S': size = 2; break; case 'i': case 'I': size = 4; break; case 'f': size = 4; break; case 'd': size = 8; break; } TclObject valueObj; if (count == BINARY_NOCOUNT) { if (length - offset < size) { break; } valueObj = ScanNumber(src, offset, cmd); offset += size; } else { if (count == BINARY_ALL) { count = (length - offset) / size; } if (length - offset < count * size) { break; } valueObj = TclList.NewInstance(); int thisOffset = offset; for (int ix = 0; ix < count; ix++) { TclList.Append(null, valueObj, ScanNumber(src, thisOffset, cmd)); thisOffset += size; } offset += count * size; } interp.SetVar(argv[arg++], valueObj, 0); break; } case 'x': { if (count == BINARY_NOCOUNT) { count = 1; } if (count == BINARY_ALL || count > length - offset) { offset = length; } else { offset += count; } break; } case 'X': { if (count == BINARY_NOCOUNT) { count = 1; } if (count == BINARY_ALL || count > offset) { offset = 0; } else { offset -= count; } break; } case '@': { if (count == BINARY_NOCOUNT) { AlephWithoutCount(interp); } if (count == BINARY_ALL || count > length) { offset = length; } else { offset = count; } break; } default: { BadField(interp, cmd); } break; } } // Set the result to the last position of the cursor. interp.SetResult(arg - 4); } break; } return(TCL.CompletionCode.RETURN); }