HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Parsing GSM 7-Bit messages in Java

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
bitgsmjavaparsingmessages

Problem

I wrote a function to decode GSM 7-Bit encoded messages as defined in the 3GPP standard. Example available here. I found a tool to help me check my answers here. I used the charset from here.

public String decode(final byte[] data) {
    if (data == null) {
        return null;
    }

    final ByteArrayOutputStream bos = new ByteArrayOutputStream();
    for (int i = 0, counter = 0; i > (8 - counter);
        bos.write(shiftedCurrent | shiftedPrevious);

        if (counter == 6) {
            bos.write((current & 0xFF) >> 1);
        }
    }

    try {
        final String result = bos.toString("X-Gsm7Bit");
        return result.endsWith("\r") ? result.substring(0, result.length() - 1) : result;
    } catch (final UnsupportedEncodingException e) {
        throw new AsnDecodeException("Cannot get charset: X-Gsm7Bit");
    }
}


Tests:

@Test
public void decodeTests() throws DecoderException {
    assertThat(decode(Hex.decodeHex("f4f29c9e769f1b".toCharArray()))).isEqualTo("testing");
    assertThat(decode(Hex.decodeHex("31D98C56B3DD70".toCharArray()))).isEqualTo("12345678");
    assertThat(decode(Hex.decodeHex("6176D94DAFCB1B".toCharArray()))).isEqualTo("alentur");
    assertThat(decode(Hex.decodeHex("61F79B8E2ECB5B657CB80D679701E77638CD768DDF6D".toCharArray()))).isEqualTo("another-example@gmail.com");
}


I feel like I could have done this with fewer shifts or & checks, but the thing I really don't like is my counter variable that I reset at 7. Any advice on how to improve this code?

Solution

thing I really don't like is my counter variable that I reset at 7

may be just keep incrementing the counter as counter = (counter + 1) % 8 instead of keeping it in the for loop.


Any advice on how to improve this code?

this may be just me, but bit operations are very mysterious so I'd like to have a variable for 0x7F & 0xFF to understand what's to special

Also, I'm not really sure why counter == 6 leads to the additional bit. It would help if you could take it out into a function that gets called.

result.endsWith("\r") seems a bit odd. Is that a specific requirement. If so, do you also need to handle \n ?

throw new AsnDecodeException("Cannot get charset: X-Gsm7Bit"); when throwing exceptions, I'd recommend adding some context on the input data leading to the error message. It helps a lot when

Don't forget to test for bad input data like

  • ""



  • null



  • "zz"



  • "123456789ø"



I'd also just recommend creating a helper class and using hamcrest matchers to make the testing more readable i.e. assertThat(hex("f4f29c9e769f1b"), is("testing"))

Context

StackExchange Code Review Q#155961, answer score: 2

Revisions (0)

No revisions yet.