In programming, it’s common to deal with lengths or sizes of data. Depending on the size of that data, we represent its length using bytes. But how exactly does this encoding work? Let’s break it down step by step.
What is a Byte?
A byte is a unit of data that consists of 8 bits. Each bit is a binary value, meaning it can either be a 0
or a 1
. For example, if we have a sequence of 8 bits, it might look like this:
00000000
That’s a byte with all zeroes.
How We Encode Lengths Using Bytes
When encoding a length in bytes, we need to consider how large that length is. The larger the number, the more bytes we need to represent it. Let’s look at an example to make this clearer.
Example 1: Length = 255
Let’s say we have the value 255
, and we want to encode this length in bytes. Since 255
can fit in 1 byte (8 bits), it’s simple. The binary representation of 255
is:
11111111
This is the maximum value you can store in a single byte.
Now, if we represent this in hexadecimal (which is base-16), 11111111
becomes FF
. So, in hexadecimal, 255
is represented as:
FF
When we apply this to our code, we see that for a length of 255
, we use a 2-byte encoding because of the condition that values greater than or equal to 128
require extra bytes:
byteArrayOf(0x81.toByte(), 0xFF.toByte())
Here:
0x81.toByte()
is a special marker that tells the system we are using 2 bytes.
0xFF.toByte()
is the actual length, encoded in a single byte.
Example 2: Length = 256
What if the length is 256
? Since 256
is greater than what we can store in 1 byte, we need to use 2 bytes (or 16 bits) to represent this length. The 16-bit binary representation of 256
looks like this:
00000001 - 2nd byte
00000000 - 1st byte
If we convert this to hexadecimal, we get:
01 00
In the code, when we encounter a length of 256
, we enter the else
condition that handles lengths larger than 255, which requires 3 bytes of encoding:
byteArrayOf(0x82.toByte(), 0x01.toByte(), 0x00.toByte())
Here:
0x82.toByte()
is a marker that indicates we’re using 3 bytes for the length.
0x01.toByte()
and0x00.toByte()
represent the high and low bytes of the length256
, respectively.
Why Do We Need Different Byte Encodings?
The reason we use different encodings is efficiency. For small lengths (less than 128), we can fit the value into 1 byte, which saves space. As the length grows, we need more bytes to accurately represent the number, but by using markers like 0x81
and 0x82
, we help the system understand how many bytes are being used for the length.
Recap of the Implementation
Here is our implementation of the function that converts a length into its corresponding hex string representation, depending on whether it requires 1, 2, or 3 bytes of encoding:
private fun encodeLengthToHexString(length: Int): String {
val bytes = when {
length < 128 -> byteArrayOf(length.toByte()) // 1-byte length encoding
length <= 255 -> byteArrayOf(0x81.toByte(), length.toByte()) // 2-byte length encoding
else -> byteArrayOf(0x82.toByte(), (length shr 8).toByte(), length.toByte()) // 3-byte length encoding
}
return bytes.joinToString("") { String.format("%02X", it) }
}
This function takes an integer length
as input and:
- Uses 1 byte if the length is less than 128.
- Uses 2 bytes if the length is between 128 and 255.
- Uses 3 bytes for lengths greater than 255.
It then returns the encoded length as a hexadecimal string.
Conclusion
In summary, encoding lengths into bytes depends on the size of the value. Small values can fit in 1 byte, but larger values require 2 or 3 bytes. By using this encoding system, we ensure efficient storage and handling of data lengths, while the system knows exactly how many bytes to expect for any given value.
By understanding how binary and hexadecimal representations work, you can better manage length encodings in your programs and ensure your data is handled correctly.
If you’d like to learn more or get involved in the QCAT ecosystem, feel free to check out my guides on QCAT specification below or check out AF Payments Inc.’s GitHub for the latest updates and contribution guidelines.
- The QCAT Standard: Revolutionizing QR Code-Based Ticketing for Public Transport
- The QCAT Standard: An Overview of the QR Code Specification
- The QCAT Standard: Generating the QR Code
- The QCAT Standard: Implementing Public Key Management System for QR Code Signing
Don't forget to subscribe to my blog so you never miss out on my latest guides and content!
DISCLAIMER
The information provided in this article is for informational purposes only and does not constitute professional advice. While efforts have been made to ensure accuracy, AF Payments Inc. reserves the right to update or modify the QCAT standard and related materials at any time. Use of the QCAT standard is subject to the terms of its license agreement, and any implementation must adhere to AFPI’s guidelines and licensing requirements. For the latest details and official documentation, please refer to AF Payments Inc.’s authorized channels.
Comments
Post a Comment