views:

215

answers:

4

Hi all,

I've searched and searched stackoverflow for the answer, but have not found what I needed.

I have a routine that takes an unsigned char array as a parameter in order to encode it as Base64. I would like to encode an STL float vector (vector) in Base64, and therefore would need to reinterpret the bytes in the float vector as an array of unsigned characters in order to pass it to the encode routine. I have tried a number of things from reinterpret and static casts, to mem copies, etc, but none of them seem to work (at least not the way I implemented them).

Likewise, I'll need to do the exact opposite when decoding the encoded data back to a float array. The decode routine will provide the decoded data as an unsigned char array, and I will need to reinterpret that array of bytes, converting it to a float vector again.

Here is a stripped down version of my C++ code to do the encoding:

std::string
EncodeBase64FloatVector( const vector<float>& p_vector )
{
  unsigned char* sourceArray;

  // SOMEHOW FILL THE sourceArray WITH THE FLOAT VECTOR DATA BITS!!

  char* target;
  size_t targetSize = p_vector.size() * sizeof(float);
  target = new char[ targetSize ];

  int result = EncodeBase64( sourceArray, floatArraySizeInUChars, target, targetSize );

  string returnResult;
  if( result != -1 )
  {
    returnResult = target;
  }
  delete target;
  delete sourceArray;
  return returnResult;
}

Any help would be greatly appreciated. Thanks.

Raymond.

+1  A: 

I have a routine that takes an unsigned char array as a parameter in order to encode it as Base64. I would like to encode an STL float vector (vector) in Base64, and therefore would need to reinterpret the bytes in the float vector as an array of unsigned characters in order to pass it to the encode routine.

Not an answer to your question but: Are you sure that your Base64 encoder works on floats? Because if it doesn't, it makes no sense to do the byte-jugglery you are after.

I have tried a number of things from reinterpret and static casts, to mem copies, etc, but none of them seem to work (at least not the way I implemented them).

Another question: What do you mean by not working? Also, did you try decoding the encoded value back? What are your results?

Here's a piece of code that may help you with the general logic.

dirkgently
Quote: "Are you sure that your Base64 encoder works on floats?"If I do this 'byte jugglery', then won't the routine work with floats? In the end, the base64 encoder just encodes a bunch of bytes regardless of what the source data was, no? We just need to provide the data in a usable format and then interpret the results properly.
Raymond
Which is why I asked if decoding works! Any luck?
dirkgently
So far, no... though I assume (though you are making me doubt my assumptions) that it's not the decoder, rather just how I reinterpret the decoded message. I'm still looking into this.
Raymond
+3  A: 
sourceArray = reinterpret_cast<const unsigned char *>(&(p_vector[0]))
Mark Ransom
+3  A: 

std::vector guarantees the data will be contiguous, and you can get a pointer to the first element in the vector by taking the address of the first element (assuming it's not empty).

typedef unsigned char byte;
std::vector<float> original_data;
...
if (!original_data.empty()) {
  const float *p_floats = &(original_data[0]);  // parens for clarity

Now, to treat that as an array of unsigned char, you use a reinterpret_cast:

  const byte *p_bytes = reinterpret_cast<const byte *>(p_floats);
  // pass p_bytes to your base-64 encoder
}

You might want to encode the length of the vector before the rest of the data, in order to make it easier to decode them.

CAUTION: You still have to worry about endianness and representation details. This will only work if your read back on the same (or compatible) platform that you wrote with.

Adrian McCarthy
A: 

I would highly recommend checking out Google's protobuf to solve your problem. Floats and doubles can vary in size and layout between platforms and that package has solved all those problems for you. Additionally, it can easily handle your data structure should it ever become more complicated than a simple array of floats.

If you do use that, you will have to do your own base64 encoding still as protobuf encodes data assuming you have an 8-bit clean channel to work with. But that's fairly trivial.

Omnifarious