/// <summary>Set to contain the contents of a string.</summary> public virtual void Set(string @string) { if (@string.Length > unchecked ((int)(0xffff)) / 3) { // maybe too long Log.Warn("truncating long string: " + @string.Length + " chars, starting with " + Runtime.Substring(@string, 0, 20)); @string = Runtime.Substring(@string, 0, unchecked ((int)(0xffff)) / 3); } length = Utf8Length(@string); // compute length if (length > unchecked ((int)(0xffff))) { // double-check length throw new RuntimeException("string too long!"); } if (bytes == null || length > bytes.Length) { // grow buffer bytes = new byte[length]; } try { // avoid sync'd allocations DataOutputBuffer obuf = ObufFactory.Get(); obuf.Reset(); WriteChars(obuf, @string, 0, @string.Length); System.Array.Copy(obuf.GetData(), 0, bytes, 0, length); } catch (IOException e) { throw new RuntimeException(e); } }
/// <summary>Used by child copy constructors.</summary> protected internal virtual void Copy(IWritable other) { lock (this) { if (other != null) { try { var memoryStream = new MemoryStream(); var binaryWriter = new BinaryWriter(memoryStream); DataOutputBuffer outputBuffer = new DataOutputBuffer(); other.Write(binaryWriter); DataInputBuffer inputBuffer = new DataInputBuffer(); inputBuffer.Reset(outputBuffer.GetData(), outputBuffer.GetLength()); ReadFields(inputBuffer); } catch (IOException e) { throw new ArgumentException("map cannot be copied: " + e.Message); } } else { throw new ArgumentException("source map cannot be null"); } } }
/// STATIC UTILITIES FROM HERE DOWN /// These are probably not used much anymore, and might be removed... /// <summary>Convert a string to a UTF-8 encoded byte array.</summary> /// <seealso cref="Runtime.GetBytesForString(string)"/> public static byte[] GetBytes(string @string) { byte[] result = new byte[Utf8Length(@string)]; try { // avoid sync'd allocations DataOutputBuffer obuf = ObufFactory.Get(); obuf.Reset(); WriteChars(obuf, @string, 0, @string.Length); System.Array.Copy(obuf.GetData(), 0, result, 0, obuf.GetLength()); } catch (IOException e) { throw new RuntimeException(e); } return(result); }
/// <exception cref="System.IO.UTFDataFormatException"/> /// <exception cref="System.IO.IOException"/> private static void ReadChars(BinaryReader reader, StringBuilder buffer, int nBytes) { DataOutputBuffer obuf = ObufFactory.Get(); obuf.Reset(); obuf.Write(@in, nBytes); byte[] bytes = obuf.GetData(); int i = 0; while (i < nBytes) { byte b = bytes[i++]; if ((b & unchecked ((int)(0x80))) == 0) { // 0b0xxxxxxx: 1-byte sequence buffer.Append((char)(b & unchecked ((int)(0x7F)))); } else { if ((b & unchecked ((int)(0xE0))) == unchecked ((int)(0xC0))) { if (i >= nBytes) { throw new UTFDataFormatException("Truncated UTF8 at " + StringUtils.ByteToHexString (bytes, i - 1, 1)); } // 0b110xxxxx: 2-byte sequence buffer.Append((char)(((b & unchecked ((int)(0x1F))) << 6) | (bytes[i++] & unchecked ( (int)(0x3F))))); } else { if ((b & unchecked ((int)(0xF0))) == unchecked ((int)(0xE0))) { // 0b1110xxxx: 3-byte sequence if (i + 1 >= nBytes) { throw new UTFDataFormatException("Truncated UTF8 at " + StringUtils.ByteToHexString (bytes, i - 1, 2)); } buffer.Append((char)(((b & unchecked ((int)(0x0F))) << 12) | ((bytes[i++] & unchecked ( (int)(0x3F))) << 6) | (bytes[i++] & unchecked ((int)(0x3F))))); } else { if ((b & unchecked ((int)(0xF8))) == unchecked ((int)(0xF0))) { if (i + 2 >= nBytes) { throw new UTFDataFormatException("Truncated UTF8 at " + StringUtils.ByteToHexString (bytes, i - 1, 3)); } // 0b11110xxx: 4-byte sequence int codepoint = ((b & unchecked ((int)(0x07))) << 18) | ((bytes[i++] & unchecked (( int)(0x3F))) << 12) | ((bytes[i++] & unchecked ((int)(0x3F))) << 6) | ((bytes[i++ ] & unchecked ((int)(0x3F)))); buffer.Append(HighSurrogate(codepoint)).Append(LowSurrogate(codepoint)); } else { // The UTF8 standard describes 5-byte and 6-byte sequences, but // these are no longer allowed as of 2003 (see RFC 3629) // Only show the next 6 bytes max in the error code - in case the // buffer is large, this will prevent an exceedingly large message. int endForError = Math.Min(i + 5, nBytes); throw new UTFDataFormatException("Invalid UTF8 at " + StringUtils.ByteToHexString (bytes, i - 1, endForError)); } } } } } }