Struct with dynamic sized array member

J

joe

An external interface is sending over the wire basically a variable
sized struct, similar to:

struct ExternalMessage
{
int m_numberOfOranges;
int m_numberOfApples;
Apple m_foo[=m_numberOfApples];
Orange m_orange[=m_numberOfOrange];
};

Having to access this struct which is of unknown size until it is
received is not straightforward.

I was considering trying to use templates to pre-create every possible
struct layout and use the accessors that way.

Something like:

class VarLenBase {};

template<int NUM_ORANGE,int NUM_APPLE>
struct VarLenMsg : public VarLenBase
{
int m_numberOfOranges;
int m_numberOfApples;
Apple m_foo[NUM_APPLE];
Orange m_orange[NUM_ORANGE];

// then accessors such as:
Orange getOrange(int index) { return m_orange[index]; }
// would just work without counting bytes and hopping
};

To pre-create them, i need some sort of mapping of the known params to
the concrete struct that matches:
std::map<std::pair<int,int>, VarLenBase*> ;

But I'm strugglnig how to then use this information to cast the
received buffer as the type that I now know it is.

Is there a better way (probably yes). using std::vectors is not the
answer since i am not in control of the sender, and it has to be sent
over a network anyway.
Thanks,
JC
 
G

Goran

An external interface is sending over the wire basically a variable
sized struct, similar to:

struct ExternalMessage
{
  int m_numberOfOranges;
  int m_numberOfApples;
  Apple m_foo[=m_numberOfApples];
  Orange m_orange[=m_numberOfOrange];

};

Having to access this struct which is of unknown size until it is
received is not straightforward.

I was considering trying to use templates to pre-create every possible
struct layout and use the accessors that way.

Something like:

class VarLenBase  {};

class VarLenBase
{
int m_numberOfOranges;
int m_numberOfApples;
};

would probably serve you better.

But...
template<int NUM_ORANGE,int NUM_APPLE>
struct VarLenMsg : public VarLenBase
{
  int m_numberOfOranges;
  int m_numberOfApples;
  Apple m_foo[NUM_APPLE];
  Orange m_orange[NUM_ORANGE];

  // then accessors such as:
  Orange getOrange(int index)  { return m_orange[index]; }
  // would just work without counting bytes and hopping

};

To pre-create them, i need some sort of mapping of the known params to
the concrete struct that matches:
  std::map<std::pair<int,int>, VarLenBase*> ;

But I'm strugglnig how to then use this information to cast the
received buffer as the type that I now know it is.

Is there a better way (probably yes).  using std::vectors is not the
answer since i am not in control of the sender, and it has to be sent
over a network anyway.
Thanks,

Even if you got your idea to work, as soon as wire-representation of
Apple and Orange isn't fixed size, it wouldn't work again. In other
words, the total number of "type" combination is massive for any but
the "smallest" cases.

I'd advise not to do that. Ever. Separate wire-(disk?) representation
from actual data you'd use in code. Only try to match the two in
lowest-level code dedicated to creation of non-wire data
representation. Do use, however, "internal" representation, for wire-
reading/writing purposes only; you still need to observe bit-count and
endiannes issues that Paavo mentions. For example "base" with counts
only is reasonable IMO. After that, go back to reading off to another
type of a buffer (Apples).

e.g.

// Internal. Matches wire-representation, sizes, layout, and endiannes
included.
// Platform-specific.
struct sizes
{
int capples, coranges; // "c" meant "count.
};

struct data
{
std::vector<apple> apples;
std::vector<oranges> oranges;
};

template<typename T>
read(stream& s, T* first, size_t count)
{
s.read(first, count * sizeof(*first));
}

template<typename T>
read(stream& s, vector<T>& v)
{
read(&v[0], v.size());
}

data read(stream& str)
{
sizes s;
str.read(&s, sizeof s);
data result;
result.apples.resize(s.capples);
read(s, result.apples);
result.oranges.resize(s.coranges);
read(s, result.oranges);
}

Goran.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top