Sunday, January 8, 2017

Determine the byte order using Swift

As humans, when we look at a number, we put the most significant number first and the least significant number last.  As an example when we look at the number 123 we know that the number 1 represents 100 which is the most significant digit while 3 is the least significant digit.  For computers, the byte order refers to the order that data is stored in memory.  Some computers store the most significant bytes first (at the lowest byte address), while others store the most significant bytes last (highhest byte address). 

If a device stores the most significant bytes first, it is known big-endian while a device that stores the most significant bytes last is knows as little-endian. 

The order of how data is stored in memory is of great importance when doing network development because RFC1700 states that the byte order for Internet Protocols must be big-endian. If the device that our application is running on stores data in little-endian order than we need to convert it.  We can use the Network-to-Host and Host-to-Network functions to convert between the byte order of your device and the byte order of the network.  These function, will take into account the byte order of the device the application is running on (host) and will convert the data to big-endian (network) byte order if necessary.  These functions are:

·       htons() – Host to network short
·       htonl() – Host to network long
·       ntohs() – Network to host short
·       ntohl() – Network to host long

By using these functions we generally to not need to worry about the endianess of the device we are running on however there are times we will want to know.  In this post we will look at how we can determine the byte order of the device our application is running on.

It is a good idea to import the Foundation framework and either Glibc or Darwin framework depending on the operating system the application is running on therefore we will start off by importing these frameworks.  Here is our import statement.

    import Foundation
    #if os(Linux)
        import Glibc
    #else
        import Darwin
    #endif

In this code we import the Glibc framework if we are building for a Linux system otherwise we import the Darwin framework.  We import the Foundation framework for both platforms.
Now that we have imported the frameworks needed, lets determine the byte order for the device. 

    let number: UInt32 = 0x12345678
    let converted = number.bigEndian
    if number == converted {
        print("Big")
    } else {
        print("Little \(converted)")
    }

In this code we begin by defining a UInt32 number.  We then convert how it is stored to big endian.  When we compare the original number to the converted one, if the two numbers are equal then the device uses big endian otherwise we know it uses little endian.

The Swift standard library provides two instance properties that allow us to change the byte order.  These properties are bigEndian and littleEndian.  The device that our code is running on probably uses little endian therefore when we use the bigEndian property the byte order of the number is changed.  This will give us a different number therefore when we compare the original number to the converted one the numbers will not match.  This tells us that the device uses little endian to store data.  If the numbers do match, than we know the device uses big endian.


No comments:

Post a Comment