The Origin Forum
File Exchange
Try Origin for Free
The Origin Forum
Home | Profile | Register | Active Topics | Members | Search | FAQ | Send File to Tech support
Username:
Password:
Save Password
Forgot your Password? | Admin Options

 All Forums
 Origin Forum for Programming
 Forum for Origin C
 Byte order
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic

Mike Buess

USA
3037 Posts

Posted - 02/25/2003 :  4:05:27 PM  Show Profile  Edit Topic  Reply with Quote  View user's IP address  Delete Topic
I know that you can specify the byte order (Little or Big Endian) when you read one integer at a time with ReadInt(). But how do you specify the byte order in a struct? Here's an abbreviated version of what I'm trying to do...
struct datablockhead {
long nblocks;
short status;
};


void ReadHeader(string strFile)
{
datablockhead vnmrh;
file ff;


ff.Open(strFile, file::modeRead);
ff.Read(&vnmrh, sizeof(vnmrh));
ff.Close();

printf("# blocks: %d", vnmrh.nblocks); // wrong byte order
printf("status: %d", vnmrh.status); // wrong byte order
}
BTW, I'm just starting out with structs so please let me know if I'm doing anything stupid.

...Forgot to declare ff above, but that was just a transcription error.

Mike Buess
Origin WebRing Member

Edited by - Mike Buess on 02/26/2003 3:18:34 PM

Mike Buess

USA
3037 Posts

Posted - 02/26/2003 :  8:38:26 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
I'm sure it's possible to write a Big2LittleEndian() (or vice versa) conversion function and apply it to each value in the struct, but I'm hoping there's an better way. If not, it would be easier just to read the values individually.

Mike Buess
Origin WebRing Member
Go to Top of Page

ML

USA
63 Posts

Posted - 02/27/2003 :  12:42:05 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
quote:

I'm sure it's possible to write a Big2LittleEndian() (or vice versa) conversion function and apply it to each value in the struct, but I'm hoping there's an better way. If not, it would be easier just to read the values individually.

Mike Buess
Origin WebRing Member


The trouble with reading structures (one of several) is that the method of the file class "Read", being general, has no idea what it is reading into, so it just reads the number of bytes demanded by the caller and puts them into the provided memory one by one. This is unlike the method "ReadInt" which does know what it is reading (which type), so it can correctly treat little-big-endian integer.

To read correctly a "big endian"-ed structure on Intel machines means that one needs to read every member individually according to its type and "endianness", using ReadInt() and alike (see http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=8tgcts%242uo1%241%40netnews.csie.NCTU.edu.tw&rnum=2&prev=/groups%3Fq%3Dstructure%2Bbig%2Bendian%2Blittle%26hl%3Den%26lr%3D%26ie%3DUTF-8%26selm%3D8tgcts%25242uo1%25241%2540netnews.csie.NCTU.edu.tw%26rnum%3D2 for a discussion on the matter). Note that it is not possible to just reverse the order of bytes in the entire structure to go from "big" to "little" and back (as it is possible for simple types like "long" and "short") since that would also change the order of individual members within the structure.

Note that the methods ReadInt() and ReadFloat() have arguments that can be used to specify the "endianness" of the file. If, aside from file reading, you still need to convert a simple variable from one "endianness" to another, you can write the function which will do the reversal. Here is an example:

// lp must point at at least nNumBytes bytes.
void reverse_bytes(void *p, int nNumBytes)
{
BYTE *pBytes = (BYTE*)p;
BYTE byTemp;

for (int ii = 0; ii < nNumBytes / 2; ii++)
{
int iiSwap = nNumBytes - 1 - ii;
byTemp = pBytes[iiSwap];
pBytes[iiSwap] = pBytes[ii];
pBytes[ii] = byTemp;
}

}


struct datablockhead {
long nblocks;
short status;
};

// This demonstrates the usage of reverse_bytes():
void test_reverse()
{
datablockhead st;

st.nblocks = 0x12131415;
st.status = 0x5678;


printf("Before reversal: \tnblocks = \t%#x\tstatus = %#x\n", st.nblocks, st.status);

reverse_bytes(&st.nblocks, sizeof(long));
reverse_bytes(&st.status, sizeof(short));

printf("AFTER reversal: \tnblocks = \t%#x\tstatus = %#x\n", st.nblocks, st.status);
}



Note also that, as with any structure and regardless of "endianness" of the files being read, padding issues come into play as well.

ML

Go to Top of Page

Mike Buess

USA
3037 Posts

Posted - 02/27/2003 :  3:39:04 PM  Show Profile  Edit Reply  Reply with Quote  View user's IP address  Delete Reply
Thanks, ML. That explains it pretty well.

Mike Buess
Origin WebRing Member
Go to Top of Page
  Previous Topic Topic Next Topic Lock Topic Edit Topic Delete Topic New Topic Reply to Topic
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
The Origin Forum © 2020 Originlab Corporation Go To Top Of Page
Snitz Forums 2000