Two little “endians”…and then there were none (of big)

1940 cover of the bookIf you don’t have problems, it means that you are doing nothing new. In my job, I do have problems almost everyday, and that’s making me happy!
If you deal with low-level data transfer, then you probably faced the different “endianness” of the processors. Traditionally, companies like Intel embraced the Little-endian choice, whereas Motorola (now Freescale) joined the Big-endian way.
Now, it seems that the .Net Framework cares only the Little-endian vision of the world. Here is an excerpt of the BitConverter class as seen with any decent disassembler:

	public static class BitConverter
	{
		/// <summary>Indicates the byte order ("endianness") in which data is stored in this computer architecture.</summary>
		/// <filterpriority>1</filterpriority>
		[__DynamicallyInvokable]
		public static readonly bool IsLittleEndian = true;

                // ...

Anyway, when you have to write a C#/.Net program which has to exchange data with a Big-endian device, you’re in trouble because the very poor support of this format. So, I created a pretty decent reader/writer pair that should come useful for many of you.

The “BIDI”-way.

Many modern processors supports both the “endiannesses”, so…why a BinaryReader/BinaryWriter shouldn’t act as them? Furthermore, it’s not unusual to see a mixed-format data in the same stream. One of the latest occasions was just on the FT800 chip, which requires a mixture of Big-endian for the addressing, despite the specs state that the chip is Little-endian based.
So, I definitely wanted a Reader/Writer capable of both. However, the interface is meant as “explicit” reference to a type yet the format. There’s no any “default” format, and this context might be interesting as well. The classes have been based by the original Microsoft’s BinaryReader and BinaryWriter, then I modified the data access. The pair of new classes are named as BidiBinaryReader and BidiBinaryWriter.
If any of you browsed the sources of my Modbus library, then the problem isn’t new at all. This time I turned the source to “wrap” a generic Stream object, instead a faster but less-abstract byte array. Here is an example of how the BidiBinaryReader:


        /// <summary>Reads a 4-byte signed integer (Little-endian) from the current stream and advances the current position of the stream by four bytes.</summary>
        /// <returns>A 4-byte signed integer read from the current stream.</returns>
        /// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
        /// <exception cref="T:System.ObjectDisposedException">The stream is closed. </exception>
        /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
        /// <filterpriority>2</filterpriority>
        public virtual int ReadInt32LE()
        {
            this.FillBuffer(4);
            return
                (int)this.m_buffer[0] |
                (int)this.m_buffer[1] << 8 |
                (int)this.m_buffer[2] << 16 |
                (int)this.m_buffer[3] << 24;
        }


        /// <summary>Reads a 4-byte signed integer (Big-endian) from the current stream and advances the current position of the stream by four bytes.</summary>
        /// <returns>A 4-byte signed integer read from the current stream.</returns>
        /// <exception cref="T:System.IO.EndOfStreamException">The end of the stream is reached. </exception>
        /// <exception cref="T:System.ObjectDisposedException">The stream is closed. </exception>
        /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
        /// <filterpriority>2</filterpriority>
        public virtual int ReadInt32BE()
        {
            this.FillBuffer(4);
            return
                (int)this.m_buffer[3] |
                (int)this.m_buffer[2] << 8 |
                (int)this.m_buffer[1] << 16 |
                (int)this.m_buffer[0] << 24;
        }

What the classes don’t expose.

The original Microsoft’s sources also offer the support for reading and writing chars, thus the codec-way to manipulate bytes. The problem is that those sources access to several internal stuffs, so the only way to leverage them is via reflection. I usually work with plain byte-arrays, and the text conversion is made by some specific codec (e.g. UTF8Encoding).
As stated, there’s no a support for setting a “default” endinanness of the Reader/Writer. I mean using the same original’s interface, but allowing the user to set whether adopt the Big- instead of the Little-endian format.

So far so well. As usual here are the sources.

2 thoughts on “Two little “endians”…and then there were none (of big)

    • Mario Vernari

      You mean an Int16/short? The source code covers almost all kind of data types. The above is just an example.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s