 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jared Guest
|
Posted: Tue Aug 02, 2005 11:17 pm Post subject: problem with binary i/o |
|
|
I know this has been touched on before, but I haven't been able to find
my answer still. I searched this newsgroup on google extensively before
writing this.
My problem is with binary i/o, but not specifically file i/o which has
proven to be easier for me.
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
I've played around with C++ streams, fread/fwrite, and even sscanf up
to this point without any luck.
I've also looked at code that dealt with this situation fine having
only integers, but it seems that the floats/longs being thrown into the
mix is really messing things up. It used a series memmove()'s to
accomplish the task, which I found particularly ugly. Is there a C++
way to solve this problem, or do I have to resort to a low level C-Style
solution? I'm kind of rusty on C-style I/O, but I thought there was a
decently easy way to solve this problem. If I'm missing something,
could someone please give me a hand?
Thanks,
Jared
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Wed Aug 03, 2005 9:58 am Post subject: Re: problem with binary i/o |
|
|
Jared wrote:
| Quote: | My problem is with binary i/o, but not specifically file i/o which has
proven to be easier for me.
|
I don't get it... what kind of "binary i/o" do you want that isn't
"file i/o"? Are you talking about writing non-standard caracters to
a character console?
| Quote: | I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
I've played around with C++ streams, fread/fwrite, and even sscanf up
to this point without any luck.
|
Well it looks as if you DO want to do file i/o. You're talking about
packing binary bits from a structure into a flat buffer so that you can
write it to a binary file. Then after you've read the binary file,
you're talking about unpacking the buffer back into a structure. Is
this
right, or did I misread you completely?
The question now is how portable you need to be. Do you want to assume
that every platform you're going to use has an 8-bit char, 32-bit long,
16-bit int, and so on? (It doesn't have to be those exact numbers -- my
point is, if you're only going to use one CPU and operating system.)
If so, you can just use struct DPOSN as-is. If there are any padding
bytes between fields, they'll get written out too -- but that shouldn't
be a problem.
If the data might be written by one CPU and then read back in by
another,
the problem gets more sticky. On some operating systems, a 2-byte
integer
is stored with the least-significant byte first; so the number 513
(which
is 0x0201 in hexidecimal) would be the same as x01, x02. On other
systems it would be most-significant first: x02, x01. For even
longer
integers the problem just gets worse. If you can at least assume 8-bit
bytes, you can pack the numbers manually, one byte at a time:
// Packs a LONG into 4 8-bit bytes
unsigned char *pack(unsigned long l, unsigned char *buff) {
*(buff++) = (unsigned char)(l & 0xFF);
l >>= 8;
*(buff++) = (unsigned char)(l & 0xFF);
l >>= 8;
*(buff++) = (unsigned char)(l & 0xFF);
l >>= 8;
*(buff++) = (unsigned char)(l & 0xFF);
return buff;
}
// Similar code for unsigned int, etc.
// Packs bytes of a DPOSN structure into a buffer
// before writing it to disk
void pack(DPOSN*d, unsigned char *buff) {
*(buff++) = d->rate;
buff = pack(d->northing, buff);
buff = pack(d->easting, buff);
// etc.
}
I'm out of time, so doing the reverse when reading the file is left as
an exercise for the reader.
If you can't even assume 8-bit bytes, it might be a wise idea to use
printable characters instead of binary. In fact, that's not a bad idea
in any case... consider XML.
Good luck.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Wed Aug 03, 2005 10:09 am Post subject: Re: problem with binary i/o |
|
|
Jared wrote:
| Quote: | I know this has been touched on before, but I haven't been able to find
my answer still. I searched this newsgroup on google extensively before
writing this.
My problem is with binary i/o, but not specifically file i/o which has
proven to be easier for me.
|
All IO is binary, they just differ in format.
| Quote: | I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
|
1. advise: use ALL_UPPERCASE only for macros, and always for those. This is
a good convention that immediately lets you spot something is a macro.
Other than that, you just need to move the bits inside 'buffer' into the
according fields in struct DPOSN. For that, you will probably need
operations like shifting and masking. All of course depending on the
particular format which your data has in 'buffer' and (!) the particular
format that a long or a float has in memory - in particular the latter can
be tricky.
| Quote: | I've played around with C++ streams, fread/fwrite, and even sscanf up
to this point without any luck.
|
Apart from fread/fwrite, these are all designed to do IO in ASCII or some
other textual format. The other two are just functions to exchange raw
bytes, no interpretation or formatting is done, so those are most suitable
to implementing your own formatting rules.
A more C++ish way is to use the streambuffer, which also does no formatting
but just character conversion to bytes, which is a no-op in many cases.
| Quote: | I've also looked at code that dealt with this situation fine having
only integers, but it seems that the floats/longs being thrown into the
mix is really messing things up. It used a series memmove()'s to
accomplish the task, which I found particularly ugly. Is there a C++
way to solve this problem, or do I have to resort to a low level C-Style
solution? I'm kind of rusty on C-style I/O, but I thought there was a
decently easy way to solve this problem. If I'm missing something,
could someone please give me a hand?
|
2. advise: do not use a packed binary format except you really need to, stay
with data formatted as text in general. Text is just soo much more
portable, easier to debug and edit, and not necessarily much larger when
compressed.
Other than that, your problem is generally called 'serialisation' or
'persistence'. There are C++ libraries out there that solve this and more
complicated cases, try google.
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Wed Aug 03, 2005 10:09 am Post subject: Re: problem with binary i/o |
|
|
Jared wrote:
| Quote: | I know this has been touched on before, but I haven't been able to find
my answer still. I searched this newsgroup on google extensively before
writing this.
My problem is with binary i/o, but not specifically file i/o which has
proven to be easier for me.
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
I've played around with C++ streams, fread/fwrite, and even sscanf up
to this point without any luck.
I've also looked at code that dealt with this situation fine having
only integers, but it seems that the floats/longs being thrown into the
mix is really messing things up. It used a series memmove()'s to
accomplish the task, which I found particularly ugly.
|
memmove or memcopy is the portable way to do that.
| Quote: | Is there a C++
way to solve this problem, or do I have to resort to a low level C-Style
solution?
|
You might probably like checking out boost::serialization library, but
I've never used it and am not aware if it supports binary
serialization.
| Quote: | I'm kind of rusty on C-style I/O, but I thought there was a
decently easy way to solve this problem. If I'm missing something,
could someone please give me a hand?
|
Standard C++ streams are no good for binary IO adding only confusion,
use plain C IO. Using XDR binary format you can read/write your
structure like:
#include <rpc/xdr.h>
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
void serialize(XDR* x, DPOSN* t)
{
xdr_char(x, &t->rate);
xdr_long(x, &t->northing);
xdr_long(x, &t->easting);
// ...
}
void write(FILE* f, DPOSN* t)
{
XDR x;
xdrstdio_create(&x, f, XDR_ENCODE);
serialize(&x, t);
}
void read(FILE* f, DPOSN* t)
{
XDR x;
xdrstdio_create(&x, f, XDR_DECODE);
serialize(&x, t);
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Aug 03, 2005 1:13 pm Post subject: Re: problem with binary i/o |
|
|
Jared wrote:
| Quote: | I know this has been touched on before, but I haven't been
able to find my answer still. I searched this newsgroup on
google extensively before writing this.
My problem is with binary i/o, but not specifically file i/o
which has proven to be easier for me.
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
|
In what format: XDR, BER... ? Unless you know the format, you
can't extract the data.
| Quote: | // I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
I've played around with C++ streams, fread/fwrite, and even
sscanf up to this point without any luck.
I've also looked at code that dealt with this situation fine
having only integers, but it seems that the floats/longs being
thrown into the mix is really messing things up.
|
Formats for floating point values tend to be fairly complex
(although XDR simply uses IEEE). I fail to see any different
between int and long, however.
| Quote: | It used a series memmove()'s to accomplish the task, which I
found particularly ugly.
|
It also doesn't work, except in exceptional cases.
| Quote: | Is there a C++ way to solve this problem, or do I have to
resort to a low level C-Style solution?
|
Well, the problem is the same in both languages. Templates can
help a little in C++, when different types have related formats
(e.g. 16, 32 and 64 bit integers, all 2's complement, network
byte order).
| Quote: | I'm kind of rusty on C-style I/O, but I thought there was a
decently easy way to solve this problem. If I'm missing
something, could someone please give me a hand?
|
The IO isn't the problem. Neither C nor C++ support any binary
format; so called binary IO is simply raw IO, transfering bytes
to or from the medium to a raw buffer (char[], or in C++
std::vector<char>). (One could argue that in th case of raw
data, the buffer should in fact be unsigned char. Formally,
this is so, and you'd need to instantiate the iostream classes
on <unsigned char> in order to do so. In practice, using char
will work, and no implementation would dare break such code.)
After, whether C or C++, its up to you to format or interpret
the raw data. Normally, this will be done using separate
functions for each type that needs to be handled. Thus, for an
integer in XDR format or Internet format:
template< typename FwdIter >
int32_t
getInt(
FwdIter begin,
FwdIter end )
{
int32_t result = 0 ;
for ( int count = 4 ; count > 0 ; -- count ) {
if ( begin == end ) {
throw FormatError() ;
}
result = (result << | (*begin ++ & 0xFF) ;
}
return result ;
}
If your implementation doesn't support an int32_t, the problem
becomes much more complicated. But such implementations are
relatively rare today.
If performance is an issue, and you can restrict your template
to random access iterators (usually not a problem -- unless you
are using istreambuffer iterators), you can easily unroll the
loop, ending up with a single expression:
if ( end - begin < 4 ) {
throw FormatError() ;
}
return ((begin[ 0 ] & 0xFF) << 24)
| Quote: | ((begin[ 1 ] & 0xFF) << 16)
((begin[ 2 ] & 0xFF) <<
(begin[ 3 ] & 0xFF) ;
|
Of course, in both cases, you'll also have to ensure that the
iterator is advances exactly four times after the value is
read. (In the first version, this can easily be handled by
simply passing begin as a non-const reference.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
lampard Guest
|
Posted: Wed Aug 03, 2005 1:14 pm Post subject: Re: problem with binary i/o |
|
|
Jared wrote:
| Quote: | I know this has been touched on before, but I haven't been able to find
my answer still. I searched this newsgroup on google extensively before
writing this.
My problem is with binary i/o, but not specifically file i/o which has
proven to be easier for me.
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
I've played around with C++ streams, fread/fwrite, and even sscanf up
to this point without any luck.
I've also looked at code that dealt with this situation fine having
only integers, but it seems that the floats/longs being thrown into the
mix is really messing things up. It used a series memmove()'s to
accomplish the task, which I found particularly ugly. Is there a C++
way to solve this problem, or do I have to resort to a low level C-Style
solution? I'm kind of rusty on C-style I/O, but I thought there was a
decently easy way to solve this problem. If I'm missing something,
could someone please give me a hand?
Is it a padding issue???, as you are saying it works for only integers.
From the struct I can see that the values will be allocated at 4 byte
position???. |
For your buffer, rate should be allocated at 0th position, northing
should be allocated at 4th position leaving 3 spaces to cater for the
padding value.
Now you can use memcpy to copy the value from the buffer to the struct.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jared Guest
|
Posted: Wed Aug 03, 2005 3:25 pm Post subject: Re: problem with binary i/o |
|
|
| Quote: |
I don't get it... what kind of "binary i/o" do you want that isn't
"file i/o"? Are you talking about writing non-standard caracters to
a character console?
|
I guess I wasn't very clear. The only interface I have is this buffer.
As Kanze mentioned, the buffer actually is an unsigned char[BSIZE]. I
have no choice in the matter.
| Quote: |
Well it looks as if you DO want to do file i/o. You're talking about
packing binary bits from a structure into a flat buffer so that you can
write it to a binary file. Then after you've read the binary file,
you're talking about unpacking the buffer back into a structure. Is
this
right, or did I misread you completely?
|
Basically correct, see above. I have an external piece of hardware that
is sending information over some communication means (serial, ethernet,
wireless, doesn't really matter) and the information is given to me in
binary, packed into the unsigned char buffer.
| Quote: |
The question now is how portable you need to be. Do you want to assume
that every platform you're going to use has an 8-bit char, 32-bit long,
16-bit int, and so on?
|
Doesn't need to be portable at all.
| Quote: |
// Packs a LONG into 4 8-bit bytes
unsigned char *pack(unsigned long l, unsigned char *buff) {
*(buff++) = (unsigned char)(l & 0xFF);
l >>= 8;
*(buff++) = (unsigned char)(l & 0xFF);
l >>= 8;
*(buff++) = (unsigned char)(l & 0xFF);
l >>= 8;
*(buff++) = (unsigned char)(l & 0xFF);
return buff;
}
// Similar code for unsigned int, etc.
// Packs bytes of a DPOSN structure into a buffer
// before writing it to disk
void pack(DPOSN*d, unsigned char *buff) {
*(buff++) = d->rate;
buff = pack(d->northing, buff);
buff = pack(d->easting, buff);
// etc.
}
I'm out of time, so doing the reverse when reading the file is left as
an exercise for the reader.
|
Thanks for the help. I assumed I needed to do something like this, but
was hoping there was a "pretty" way to do it using C++ streams.
| Quote: |
If you can't even assume 8-bit bytes, it might be a wise idea to use
printable characters instead of binary. In fact, that's not a bad idea
in any case... consider XML.
|
I wish!
Again, thanks for the help.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mzdude Guest
|
Posted: Wed Aug 03, 2005 10:34 pm Post subject: Re: problem with binary i/o |
|
|
<<
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
You can always use the *evil* union to extract packed data.
union EvilSecretDecode {
char *charPtr;
long *longPtr;
float *floatPtr;
int *intPtr;
unsigned long *ulongPtr;
};
Then to decode you can do the following
EvilSecretDecode sd;
sd.charPtr = &buffer[0]; // set all the ptrs
DPOSN dposn;
dposn.rate = *sd.charPtr++; // increment by 1 byte
dposn.northing = *sd.longPtr++; // increment by default size of long
(usually 4 bytes)
dposn.easting = *sd.longPtr++;
...
dposn.speed = *sd.floatPtr;
I would use a function to wrap the call. However, if you want to
impress your peers (not necessarily your boss) you can sexy it up with
a class wrapper like :
class MyClass {
public:
MyClass( char *pBuffer_ )
{ pBuffer.charPtr = pBuffer_; }
operator DPOSN()
{
DPOSN dp;
dp.rate = *pBuffer.charPtr++;
dp.northing = *pBuffer.longPtr++;
dp.easting = *pBuffer.longPtr++;
dp.latitude = *pBuffer.floatPtr++;
dp.longitude = *pBuffer.floatPtr++;
dp.altitude = *pBuffer.intPtr++;
dp.heading = *pBuffer.intPtr++;
dp.epe = *pBuffer.intPtr++;
dp.distance = *pBuffer.ulongPtr++;
dp.speed = *pBuffer.floatPtr++;
return dp;
}
private:
union EvilSecretDecode {
char *charPtr;
long *longPtr;
float *floatPtr;
int *intPtr;
unsigned long *ulongPtr;
};
EvilSecretDecode pBuffer;
};
int main(int argc, char* argv[])
{
char buffer[ 50 ];
memset( buffer, 1, sizeof(buffer) );
MyClass mc( buffer );
DPOSN dposn = mc;
std::cout << dposn.rate;
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Zhenghui Zhou Guest
|
Posted: Thu Aug 04, 2005 10:43 am Post subject: Re: problem with binary i/o |
|
|
Don't use the deprecated struct type in such situation, since it lose
the type infomation and cann't be extracted in a consistent way.
You may try boost::tuple on some dedicated package protocols instead.
Working with traits, and some recursive template functions, you can
build a separate i/o layer in common. I'm using in package exchanging
of fieldbus and network communications.
Many one can work it out I think, or I'll write some codes here.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Aug 04, 2005 10:47 am Post subject: Re: problem with binary i/o |
|
|
Allan W wrote:
| Quote: | The question now is how portable you need to be. Do you want
to assume that every platform you're going to use has an 8-bit
char, 32-bit long, 16-bit int, and so on? (It doesn't have to
be those exact numbers -- my point is, if you're only going to
use one CPU and operating system.)
|
Which is a lot more restrictive than what you said. All of the
systems I've used over the last 15 years have had 8 bit char, 32
bit int and 32 bit float. All have also used 2's complement for
integers, which helps. There have been, however, two different
formats for float, and one machine used EBCDIC for character
data.
| Quote: | If so, you can just use struct DPOSN as-is. If there are any
padding bytes between fields, they'll get written out too --
but that shouldn't be a problem.
|
To do that, you also have to be able to guarantee that the code
is always compiled by the same version of the same compiler,
using exactly the same flags. I've seen byte order change from
one version of the compiler to the next, and padding frequently
depends on compiler options.
If the data is to be written out to a temporary file, then later
read by the same executable, you can do this. In all other
cases, I'd avoid it. Define the format, then implement it.
Don't take what you get by chance, without necessarily even
knowing exactly what it is.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Sat Aug 06, 2005 9:57 am Post subject: Re: problem with binary i/o |
|
|
Zhenghui Zhou <zhouzhenghui (AT) gmail (DOT) com> wrote:
| Quote: | Don't use the deprecated struct type in such situation, since it lose
the type infomation and cann't be extracted in a consistent way.
You may try boost::tuple on some dedicated package protocols instead.
Working with traits, and some recursive template functions, you can
build a separate i/o layer in common. I'm using in package exchanging
of fieldbus and network communications.
Many one can work it out I think, or I'll write some codes here.
Struct depreiciated? Chapter and verse please. |
As far as storing one value in a union and extracting another is a
violation of the standard, if I recall correctly. This in this exammple
is that all pointers are stored in the same format. This is not
guaranteed by the standard. The standard says all int *'s have the same
format, but not that int * and char * do. It will probably work anyway,
but its not portable or standard compliant.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
M Jared Finder Guest
|
Posted: Sat Aug 06, 2005 11:14 am Post subject: Re: problem with binary i/o |
|
|
Jared wrote:
| Quote: | I know this has been touched on before, but I haven't been able to find
my answer still. I searched this newsgroup on google extensively before
writing this.
My problem is with binary i/o, but not specifically file i/o which has
proven to be easier for me.
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
I've played around with C++ streams, fread/fwrite, and even sscanf up
to this point without any luck.
I've also looked at code that dealt with this situation fine having
only integers, but it seems that the floats/longs being thrown into the
mix is really messing things up. It used a series memmove()'s to
accomplish the task, which I found particularly ugly. Is there a C++
way to solve this problem, or do I have to resort to a low level C-Style
solution? I'm kind of rusty on C-style I/O, but I thought there was a
decently easy way to solve this problem. If I'm missing something,
could someone please give me a hand?
|
Since DPOSN is a POD structure (essentially, a C structure) with no
pointers, it is perfectly safe to just do a bit for bit read and write:
DPOSN dposn;
fread( &dposn, sizeof( dposn ), 1, file );
or
DPOSN dposn;
// dposn is filled out
fwrite( &dposn, sizeof( dposn ), 1, file );
-- MJF
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hans Odeberg Guest
|
Posted: Sun Aug 14, 2005 6:53 pm Post subject: Re: problem with binary i/o |
|
|
mzdude skrev:
| Quote: |
I basically have a situation like below:
// some char buffer containing a packet of data (in binary)
char buffer[BSIZE];
// I want to extract the data (that has a constrained format)
// into the following struct
struct DPOSN
{
char rate;
long northing;
long easting;
float latitude;
float longitude;
int altitude;
int heading;
int epe;
unsigned long distance;
float speed;
};
You can always use the *evil* union to extract packed data.
union EvilSecretDecode {
char *charPtr;
long *longPtr;
float *floatPtr;
int *intPtr;
unsigned long *ulongPtr;
};
Then to decode you can do the following
EvilSecretDecode sd;
sd.charPtr = &buffer[0]; // set all the ptrs
DPOSN dposn;
dposn.rate = *sd.charPtr++; // increment by 1 byte
dposn.northing = *sd.longPtr++; // increment by default size of long
(usually 4 bytes)
|
Warning: This will not work if your CPU has problems accessing word
data at uneven addresses, such as Motorola 68k or Renesas H8. With such
HW, memcpy is the only option, unless the sender made sure that all
data is aligned to even addresses.
To add to the problems, the sender may have different endianness. Then
you will also have to swap bytes around.
[snip]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|