0

I have the following packet layout:

struct PacketLayout
{
  int GateCode;
  BYTE StringLen;
  char String[StringLen];
  BYTE ServerStatus;
  BYTE ServerStorage;
  BYTE ServerNumber;
}

The class is this:

class ServerInfo
{
  short PacketSize;   //Size of the whole packet
  BYTE TotalServers; //total of PacketLayout structs
  PacketLayout Server[TotalServers];
  int GlobalSecCode;
  short EncryptedPacketSize; //Same as the first member, just xored
}

So the problem i have is making an variable size array inside an class or an struct which size depends of the last member pointed by BYTE StringLen (for struct) and BYTE TotalServers (for the class).

I don't know what is the solution to this, maybe implement a template?, if that's so can i see an example (i am not familiar with templates yet) also i want to reference my member names without calculating the pointer position by myself (as i am currently doing now).

Thanks.

10
  • I'm not sure what you mean by: "i want to reference my member names without calculating the pointer position by myself " Commented Aug 1, 2012 at 19:10
  • There's no solution to this problem in standard C++. Templates are not going to help unless you know the value of ServerInfo.TotalServer and PacketLayout.StringLen at compile time. You're just going to have to calculate the offsets yourself. Commented Aug 1, 2012 at 19:10
  • Flexo right now i am calculating the pointer position by myself to the string member since there is no way to make it a compile time. Commented Aug 1, 2012 at 19:12
  • Are you sure @jahhaj? i find this quiet disturbing... isnt a more high level approach beside calculating the offsets by myself like old ASM days? lol Commented Aug 1, 2012 at 19:16
  • 2
    @jahhaj - just write a function that pulls the bytes in off the wire and puts them into the right place of a sensibly designed struct then. 1:1 mapping between packets and structs isn't always the way to go. Commented Aug 1, 2012 at 19:30

3 Answers 3

2

Doing this with a template is possible, for example:

template <int StringSize>
struct PacketLayout
{
  int GateCode;
  BYTE StringLen;
  char String[StringSize];
  BYTE ServerStatus;
  BYTE ServerStorage;
  BYTE ServerNumber;
};

lets you use this as:

PacketLayout<100> pkt;

Normally what you would want to do is simpler though. For example if you reorder the packet and know the upper limit on size you can do simply:

struct PacketLayout
{
  int GateCode;
  BYTE StringLen;
  BYTE ServerStatus;
  BYTE ServerStorage;
  BYTE ServerNumber;
  char String[MAX_POSSIBLE_SIZE];
};

Or alternatively:

struct PacketLayout
{
  int GateCode;
  BYTE StringLen;
  BYTE ServerStatus;
  BYTE ServerStorage;
  BYTE ServerNumber;
  char *String;
};

and allocate/set String during reading.

Personally though I'd skip all this messy low level details and use something like protobuf to do the work for you and leave you free to concentrate on the more important higher level things that add value to your project.

There's a common but dirty trick used sometimes too:

struct PacketLayout
{
  int GateCode;
  BYTE StringLen;
  BYTE ServerStatus;
  BYTE ServerStorage;
  BYTE ServerNumber;
  char String[1];
};

Where people define the size of the variable part at the end to be 1 and then deliberately allocate more memory than needed for the struct so they can write past the end of it. This is evil and very much not recommended though.

Sign up to request clarification or add additional context in comments.

8 Comments

What about the class? the class have also a variable array of PacketLayout structs, and i dont know the size of the PacketLayout in compile time. The size of the string is pointed by StringLen member.
@ffenix can you use an std::string instead of your char array?
@ffenix: This is your problem, unless you know these sizes at compile time templates are not going to help you. See how Flexo has written PacketLayour<100> pkt;, the 100 must be a compile time constant.
@juanchopanza - that doesn't seem to be an option here - it looks like this is something that's meant to be a POD, i.e. can be written to a file/stream directly.
@jahhaj: Mostly of the packets i recv on my server are undetermined size by compile time, so i am screw to analyze them in a reasonable high level syntax?
|
0

Using templates is definitely the way to go:

template <size_t TotalServers>
class ServerInfo 
{
    PacketLayout Server[TotalServers];
    int GlobalSecCode;
};

This has the disadvantage of not having one ServerInfo assignable to another, so possibly using a std::vector is important, if that means a lot to you.

1 Comment

What about initializing the struct, its the same method? also as pointed on the answer by Flexo, i need to get the string sizes by the StringLen member, so can you set an more complete example? Thanks.
0

There is no nice way in C++ to achieve this.

This is how you can create variable size array in PacketLayout:

struct PacketLayout
{
  int GateCode;
  BYTE StringLen;
  BYTE ServerStatus;
  BYTE ServerStorage;
  BYTE ServerNumber;
  char String[1];
}

then you allocate an instance:

PacketLayout* createPacketLayout(BYTE stringLen)
{
    PacketLayout* packetLayout = (PacketLayout*)new char[sizeof(PacketLayout) - 1 + stringLen];
    packetLayout->StringLen = stringLen;
    return packetLayout;
}

in this case ServerInfo could hold array of pointers.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.