AKIWEB
AKIWEB

Reputation: 19622

How to swap 64 bit integer while extracting bytes from bytearray in C++?

I am tring to read couple of bytes from byteData as mentioned below in my C++ code. The actual value within byteData is a binary blob byte array in BIG-ENDIAN byte order format. So I cannot simply just "cast" the byte array into a String..

byteData byte array is composed of these three things -

First is `schemaId` which is of two bytes (short datatype in Java)
Second is `lastModifiedDate` which is of eight bytes (long datatype in Java)
Third is the length of actual `byteArray` within `byteData` which we need from `byteData`.
Fourth is the actual value of that `byteArray` in `byteData`.

Now I am trying to extract the above particular information from the byteData in C++... Somehow I am able to extract schemaId and the value which I am getting is also correct.. Now I am not sure how to extract other things from it...

uint16_t schemaId;
uint64_t lastModifiedDate;
uint16_t attributeLength; // or it should be uint32_t?
const char* actual_binary_value;

while (result.next()) {
    for (size_t i = 0; i < result.column_count(); ++i) {
        cql::cql_byte_t* byteData = NULL;
        cql::cql_int_t size = 0;
        result.get_data(i, &byteData, size);

        // I cannot just "cast" the byte array into a String
        // value = reinterpret_cast<char*>(byteData);

        // this works fine
        schemaId = ntohs(*reinterpret_cast<uint16_t*>(byteData));

        // now how to retrieve lastModifiedDate, length of binary value and actual_binary_value from byteData?
        // the below doesn't works..
           lastModifiedDate = be64toh(*reinterpret_cast<uint64_t*>(data));

        // And how to extract other things as well?

    }

    // this prints out `9223090561897746107`  but it should print out `1289811105109`
    cout<< lastModifiedDate <<endl;

    // And print out other things..
}

If somebody needs to see my java code then this is my java code -

    byte[] avroBinaryValue = text.getBytes();

    long lastModifiedDate = 1289811105109L;
    short schemaId = 32767;

    int size = 2 + 8 + 4 + avroBinaryValue.length; // short is 2 bytes, long 8 and int 4

    ByteBuffer bbuf = ByteBuffer.allocate(size); 
    bbuf.order(ByteOrder.BIG_ENDIAN);

    bbuf.putShort(schemaId);
    bbuf.putLong(lastModifiedDate);
    bbuf.putInt(avroBinaryValue.length);
    bbuf.put(avroBinaryValue);

    // merge everything into one bytearray.
    byte[] bytesToStore = bbuf.array();

    Hex.encodeHexString(bytesToStore)

Can anybody help me what wrong I am doing in my C++ code and why I am not able to extract lastModifiedDate properly from it and other fields as well? As I understand lastModifiedDate is 64 bit integer, so is there any way to swap out 64 bit integer here? Or some other better way to do the conversion?

In short, I am trying to extract schemaId, lastModifiedDate, avroBinaryValue.length and avroBinaryValue from that byte array in C++..

I am able to extract schemaId but I am stuck on other things now...

Upvotes: 0

Views: 1601

Answers (1)

Chris Olsen
Chris Olsen

Reputation: 3511

Your method looks fine, there are just two possible issues I see.

  1. Your code as shown is simply casting an undefined variable data as a uint64_t. Make sure that you are actually advancing through the data buffer and converting the correct data.

  2. Platform dependency. From what I've seen, the 64-bit byte swapping functions (be64toh, betoh64, ntohll, etc), are not universally supported on all platforms. You may need to use a different function on your platform, and/or automatically detect what works if you want the code to be platform independent. See similar questions here and here, for example.

As to how to get the data, something like this should work:

int index=0;
schemaId = ntohs(*reinterpret_cast<uint16_t*>(&byteData[index]));
index += 2;
lastModifiedDate = be64toh(*reinterpret_cast<uint64_t*>(&byteData[index]));
index += 8;
attributeLength = ntohl(*reinterpret_cast<uint32_t*>(&byteData[index]));
index += 4;
actual_binary_data = (const char *)&byteData[index];

Upvotes: 1

Related Questions