gunslinger
gunslinger

Reputation: 105

How to convert any Data type into byte array

I was trying to generate Hash function using SHA256 that can convert any data type and give 64bit hash key.

Here's what I tried first

template<typename T >
uint64_t 
hyperloglog<T>::hash64 (T &value){
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256(reinterpret_cast<const unsigned char*>(value), sizeof(value), hash);
    uint64_t result = 0;
    memcpy(&result, hash, sizeof(result));
    return result;
}

But It seem to be converting value into pointer type of const unsigned char* instead of giving pointer to byte array where value is stored.

so I instead memcpy my value to byte-array

template<typename T >
uint64_t 
hyperloglog<T>::hash64 (const T &value){
    unsigned char hash[SHA256_DIGEST_LENGTH];
    unsigned char byte_arr[sizeof(value)];
    memcpy(byte_arr,&value,sizeof(value));
    SHA256(byte_arr, sizeof(byte_arr), hash);
    uint64_t result = 0;
    memcpy(&result, hash, sizeof(result));
    return result;
}

this seems to work.

Is there some better way to do this?

without creating byte-array and Is the above approach actually correct? or are there any errors doing it this way?

From what I have read so far using reinterpret_cast is considered unsafe and dangerous.

Are there any safer options?

[EDIT] It seem to work only for some data type like integer, pair,integer array. however it failed on set, strings and array of strings giving different hash value for same object different time when passed as rvalue. But when I pass same object as lvalue it give consistent value.

    string st = "12345";
    cout << HL.hash64(st)<<endl;
    cout << HL.hash64("12345")<<endl;

they both give different result I believe it's still copying memory address.

But in case of integers it is working correctly

    cout << HL.hash64(12345)<<endl;
    cout << HL.hash64(12345)<<endl;

[SOLVED] using boost serialization library to convert any class type into byte-array.

Upvotes: 0

Views: 84

Answers (0)

Related Questions