Page 1 of 1

Getting the int value from bytes

Posted: Tue Mar 18, 2008 10:33 pm
by piranha
This may seem basic, but...

When you have an array of chars/bytes whatever, and you want to put them all into ints you do...

Code: Select all

int x = buf[10] | buf[11] | buf[12] <and so on...>
Right? Is this correct?

-JL

Posted: Tue Mar 18, 2008 11:01 pm
by Brynet-Inc
Personally, I prefer using the atoi() function.. :wink:

Posted: Tue Mar 18, 2008 11:14 pm
by piranha
This would be in my OS, so no standard functions...
This is specificaly for FS reading, in which the super-block's info for the number of blocks in the data area at offset 0x019C, length is 8 bytes....how to convert that into a long int...?
-JL

Posted: Tue Mar 18, 2008 11:28 pm
by bewing
piranha wrote:This would be in my OS, so no standard functions...
This is specificaly for FS reading, in which the super-block's info for the number of blocks in the data area at offset 0x019C, length is 8 bytes....how to convert that into a long int...?
-JL
Reorganize your data area so that the offset is a multiple of 8, and do:

long long result, *llp;

llp = (long long *) (data area + 0x0198); // after reorgainization
result = *llp;

Or, if you don't want to reorganize, then you are stuck with a dword boundary -- so do the same thing with longs, instead.

long long result;
unsigned long *lp;

lp = (long *) (data area + 0x019c);
result = (long long)*lp | (lp[1]<<32);

Posted: Tue Mar 18, 2008 11:56 pm
by Brynet-Inc
What's preventing you from reading this superblock into an allocated buffer?

Code: Select all

struct superblock {
        uint64_t length;
};
uint64_t sb_length_member;
struct superblock *sb = NULL;
sb = (struct superblock *)malloc(sizeof(struct superblock));
..int fd = open("/dev/something", O_RDONLY);
..lseek(fd, offset, ...);
..read(fd, sb, 8);
sb_length_member = sb->length;
Something along those lines would work... or so I'd assume... saves all the unnecessary conversion work.

Posted: Wed Mar 19, 2008 1:12 am
by Solar
Is the FS metadata big or little endian?

Is your OS platform big or little endian?

:twisted:

Posted: Wed Mar 19, 2008 1:35 am
by piranha
what......?

-JL

Posted: Wed Mar 19, 2008 2:20 am
by Solar
Endianess. The order in which the individual bytes of an integer reside in memory.

x86 -> Little Endian.

PPC, Network -> Big Endian.

Your file system -> ??

Your platform -> ??

Posted: Wed Mar 19, 2008 2:34 am
by JamesM
The easy way - assuming same endianness of processor and data.
--no need, bewing did that for me. Incidentally, he quotes something which isn't in your post. Strange. Confused me for a while. I did wonder where he got that 0x19C malarky from...

Little endian processor with little endian data:

Code: Select all

uint32_t val = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
Big endian processor with little endian data:

Code: Select all

uint32_t val = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
Other two (little endian processor w/ big endian data, big endian processor w/ little endian data) - you work them out! :twisted:

Posted: Wed Mar 19, 2008 9:37 am
by bewing

Code: Select all

uint32_t val = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
(I hope the compiler is smart enough to reoptimize the 16 opcodes necessary for that. :wink: )

Really, as Brynet is almost suggesting -- the *smart* way to do all this is to redesign your whole superblock, so that every element of the thing is aligned on the proper "type" boundary -- then load it into memory, assign a structure pointer to it, and use it as a structure.
i= superblock -> numblks;

Then you don't have to worry about endianness, for the next few years, until your OS is complete enough that you start porting it to other types of CPUs. But shifting and ORing bytes together (as has been pointed out several times) is endian specific. So try not to do that, if you can avoid it.