Passing and Returning Arrays of Bytes

Started by
12 comments, last by Ectara 10 years ago

I have an object that maintains three arbitrary precision (AP) integer keys. The caller may supply any of the keys by passing a pointer and a length; as the AP keys are of a templated type, they may change depending on the most optimal integer size, making passing arrays of bytes through an interface the only reasonable option that is agnostic of how it will be represented inside the AP integer.

So, there are two constructors: One that accepts up to three pointer-length pairs, and one that accepts parameters to generate the keys.

The biggest question is how the keys should be made accessible to the caller. It seems irrational to make the caller guess how big the buffer would be. My goal in asking is not really to find out how it is possible (I can think of a few ways), but to ask what would be most convenient and expected as a caller, as well as what is most likely to require the least amount of transformation into the desired format after retrieving it, like writing it to a file, or putting it in a vector.

If you were a caller, and had to get a yet unknown number of bytes from an object, how would you prefer that this interface be designed?

Advertisement
I would prefer the details of how the number is expressed in bytes, or limbs, or whatever to be hidden from me completely. Look at mpz_class in gmpxx for a good example.

I would prefer the details of how the number is expressed in bytes, or limbs, or whatever to be hidden from me completely. Look at mpz_class in gmpxx for a good example.

That is what is happening. Okay, I'll write an example:


template <class T>
class DontNeedToKnow<T>{
    T * stuff;
    
public:
    void fromBytes(const void * bytes, unsigned length);
    void toBytes(void * bytes, unsigned length);
};

class Keys{
    DontNeedToKnow<unsigned> x, y, z;
    
public:
    void getKeyX(/* My question */);
    
    void setKeyX(const void * bytes, unsigned length);
};
No, that interface is not nearly abstract enough.

  mpz_class factorial = 1;
  for (int i = 1; i <= 1000; ++i)
    factorial *= i;
That's what I am talking about. I don't need to know how many bytes it takes to store the number, if I don't want to.

No, that interface is not nearly abstract enough.


  mpz_class factorial = 1;
  for (int i = 1; i <= 1000; ++i)
    factorial *= i;
That's what I am talking about. I don't need to know how many bytes it takes to store the number, if I don't want to.

There's an interface for that, already. I'm not asking how to design an AP math class, I'm asking how to best retrieve the number from a containing object in a way that can be transmitted across the network, saved to a binary file, or entered in. Moreover, referring to my above example, I'm asking about the Keys class: how should that be designed?

I'm not asking a math question.

Some variation of this perhaps?


int getKeySize()
bool getKey(void *dest, int destLen)

Some variation of this perhaps?


int getKeySize()
bool getKey(void *dest, int destLen)

Hm... So, a two-step process of getting the length, then allocating, then getting the data would be most convenient? I can do that. (This is one place where I envy scripting languages with monolithic array types)

Either that or wrap the key-bytes, like std::vector<char> getKey(). You could have a constant static max-size to simplify using static arrays for the key if it's reasonably short.

Another alternative if it's acceptable is to just return a constant internal pointer and size to the caller and let the caller memcpy it.


Either that or wrap the key-bytes, like std::vector getKey(). You could have a constant static max-size to simplify using static arrays for the key if it's reasonably short.

It'd be convenient, but I'd like to not force the user to use a particular container, much less allocated memory yet again just to pass bytes back and forth. I suppose the first option really would be best.

Another alternative if it's acceptable is to just return a constant internal pointer and size to the caller and let the caller memcpy it.

Yeah, unfortunately, that'd break on a little-endian machine, making the bytes out of order by being grouped in small reversed-order segments.

This topic is closed to new replies.

Advertisement