| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| using System; |
| using System.IO; |
| |
| namespace Apache.NMS.Util |
| { |
| /// <summary> |
| /// A BinaryWriter that switches the endian orientation of the write operations so that they |
| /// are compatible across platforms. |
| /// </summary> |
| [CLSCompliant(false)] |
| public class EndianBinaryWriter : BinaryWriter |
| { |
| public const int MAXSTRINGLEN = short.MaxValue; |
| |
| public EndianBinaryWriter(Stream output) |
| : base(output) |
| { |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">A long</param> |
| public override void Write(long value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">An ushort</param> |
| public override void Write(ushort value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">An int</param> |
| public override void Write(int value) |
| { |
| int x = EndianSupport.SwitchEndian(value); |
| base.Write(x); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="chars">A char[]</param> |
| /// <param name="index">An int</param> |
| /// <param name="count">An int</param> |
| public override void Write(char[] chars, int index, int count) |
| { |
| char[] t = new char[count]; |
| for (int i = 0; i < count; i++) |
| { |
| t[index + i] = EndianSupport.SwitchEndian(t[index + i]); |
| } |
| |
| base.Write(t); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="chars">A char[]</param> |
| public override void Write(char[] chars) |
| { |
| Write(chars, 0, chars.Length); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">An uint</param> |
| public override void Write(uint value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="ch">A char</param> |
| public override void Write(char ch) |
| { |
| base.Write((byte) ((ch >> 8) & 0xFF)); |
| base.Write((byte) (ch & 0xFF)); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">An ulong</param> |
| public override void Write(ulong value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">A short</param> |
| public override void Write(short value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| /// <summary> |
| /// Method Write, writes a string to the output using the WriteString16 |
| /// method. |
| /// </summary> |
| /// <param name="text">A string</param> |
| public override void Write(String text) |
| { |
| WriteString16(text); |
| } |
| |
| /// <summary> |
| /// Method WriteString16, writes a string to the output using the Java |
| /// standard modified UTF-8 encoding with an unsigned short value written first to |
| /// indicate the length of the encoded data, the short is read as an unsigned |
| /// value so the max amount of data this method can write is 65535 encoded bytes. |
| /// |
| /// Unlike the WriteString32 method this method does not encode the length |
| /// value to -1 if the string is null, this is to match the behaviour of |
| /// the Java DataOuputStream class's writeUTF method. |
| /// |
| /// Because modified UTF-8 encding can result in a number of bytes greater that |
| /// the size of the String this method must first check that the encoding proces |
| /// will not result in a value that cannot be written becuase it is greater than |
| /// the max value of an unsigned short. |
| /// </summary> |
| /// <param name="text">A string</param> |
| public void WriteString16(String text) |
| { |
| if (text != null) |
| { |
| if (text.Length > ushort.MaxValue) |
| { |
| throw new IOException( |
| String.Format( |
| "Cannot marshall string longer than: {0} characters, supplied string was: " + |
| "{1} characters", ushort.MaxValue, text.Length)); |
| } |
| |
| char[] charr = text.ToCharArray(); |
| uint utfLength = CountUtf8Bytes(charr); |
| |
| if (utfLength > ushort.MaxValue) |
| { |
| throw new IOException( |
| String.Format( |
| "Cannot marshall an encoded string longer than: {0} bytes, supplied" + |
| "string requires: {1} characters to encode", ushort.MaxValue, utfLength)); |
| } |
| |
| byte[] bytearr = new byte[utfLength]; |
| encodeUTF8toBuffer(charr, bytearr); |
| |
| Write((ushort) utfLength); |
| Write(bytearr); |
| } |
| } |
| |
| /// <summary> |
| /// Method WriteString32, writes a string to the output using the Openwire |
| /// standard modified UTF-8 encoding which an int value written first to |
| /// indicate the length of the encoded data, the int is read as an signed |
| /// value so the max amount of data this method can write is 2^31 encoded bytes. |
| /// |
| /// In the case of a null value being passed this method writes a -1 to the |
| /// stream to indicate that the string is null. |
| /// |
| /// Because modified UTF-8 encding can result in a number of bytes greater that |
| /// the size of the String this method must first check that the encoding proces |
| /// will not result in a value that cannot be written becuase it is greater than |
| /// the max value of an int. |
| /// </summary> |
| /// <param name="text">A string</param> |
| public void WriteString32(String text) |
| { |
| if (text != null) |
| { |
| char[] charr = text.ToCharArray(); |
| uint utfLength = CountUtf8Bytes(charr); |
| |
| if (utfLength > int.MaxValue) |
| { |
| throw new IOException( |
| String.Format( |
| "Cannot marshall an encoded string longer than: {0} bytes, supplied" + |
| "string requires: {1} characters to encode", int.MaxValue, utfLength)); |
| } |
| |
| byte[] bytearr = new byte[utfLength]; |
| encodeUTF8toBuffer(charr, bytearr); |
| |
| Write(utfLength); |
| Write(bytearr); |
| } |
| else |
| { |
| Write((int) -1); |
| } |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">A double</param> |
| public override void Write(float value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| /// <summary> |
| /// Method Write |
| /// </summary> |
| /// <param name="value">A double</param> |
| public override void Write(double value) |
| { |
| base.Write(EndianSupport.SwitchEndian(value)); |
| } |
| |
| private static uint CountUtf8Bytes(char[] chars) |
| { |
| uint utfLength = 0; |
| int c = 0; |
| |
| for (int i = 0; i < chars.Length; i++) |
| { |
| c = chars[i]; |
| if ((c >= 0x0001) && (c <= 0x007F)) |
| { |
| utfLength++; |
| } |
| else if (c > 0x07FF) |
| { |
| utfLength += 3; |
| } |
| else |
| { |
| utfLength += 2; |
| } |
| } |
| |
| return utfLength; |
| } |
| |
| private static void encodeUTF8toBuffer(char[] chars, byte[] buffer) |
| { |
| int c = 0; |
| int count = 0; |
| |
| for (int i = 0; i < chars.Length; i++) |
| { |
| c = chars[i]; |
| if ((c >= 0x0001) && (c <= 0x007F)) |
| { |
| buffer[count++] = (byte) c; |
| } |
| else if (c > 0x07FF) |
| { |
| buffer[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F)); |
| buffer[count++] = (byte) (0x80 | ((c >> 6) & 0x3F)); |
| buffer[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); |
| } |
| else |
| { |
| buffer[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); |
| buffer[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); |
| } |
| } |
| } |
| } |
| } |