Il 01/09/2011 03:26, Eric Sosman ha scritto:
>>> I said "probably," because perhaps your file actually does hold
>>> "the size of myStruct." This could be the case if an actual `struct
>>> myStruct' was written to the file originally, complete with whatever
>>> padding it might have included. If you never, never need to move the
>>> data to another system (not even for post-mortem analysis), you can
>>> probably get away with this.
>>
>> I understand your point and I expaling what I'm trying to do.
>
> I'm not so sure you understand my points. For myself, I'm
> *sure* I don't understand "expaling."
I wanted to write "explaining"... :-)
I think I understood your point of view. Data in the file can be of two
types:
- blob of data of exactly N bytes sized
- myStruct previously written to the file by the same software
on the same platform (so with the same layout of padding and data)
I'm in the first case. I know the file contains a sequence of blobs of
the same size N. N is constant for a file, but may vary from file to
file. So the software should be ready to read blobs of 10 or 15 or 30
or 32 bytes.
How the software can know the size of blobs in the file? There are two
bytes at the beginning of the file (just one time and *not* for each
blob) coded as a 16-bits unsigned integer in Big Endian.
>> I have to read a file, created by another application on another
>> platform, that is composed by blocks of data (what you named "blob of
>> data"). The size of these blocks (between 3 and 32) is written in the
>> same file at the beginning.
>> A single block is composed by 2 bytes and (block_size - 2) bytes.
>
> You haven't said so, but I guess that the initial two bytes
> somehow encode `block_size'. Whether the remaining bytes are all
> "payload" or may themselves include padding may be known to you, but
> remains a mystery to the rest of us.
Just to better explain the content of the file:
- 2 bytes that code the size N of all the subsequent blocks
- N bytes for block 1
- N bytes for block 2
- ...up to the end of the file
A single N-bytes block is composed by two field:
- 2 bytes for field1
- N-2 bytes for field2
field1 and field2 are application data that aren't important now for our
discussion.
>> Because I don't know the size of blocks I'll read and I can't malloc the
>> right size at run-time, I was trying to define the maximum size of
>> block, splitting it in the two fields:
>
> Again the hangup over the absence of malloc(). If this has
> anything at all to do with the problem, it has to do with some aspect
> of the problem that you have not yet revealed. Based on what you've
> said and shown, the existence or non-existence of malloc() has zilch
> to do with the matter.
On a "full" operating system I could write:
open the file
read the first two bytes and calculate N
dynamically allocate an array of N bytes
read block 1 from file and copy it into array
other instructions based on array content
read block 2 from file and copy it into array
other instructions based on array content
...up to the end of file
Because I can't use malloc on my system, I was thinking to use an array
calibrated to the maximum value for N, that is 32.
static declaration of an array of 32 bytes
open the file
read the first two bytes and calculate N
read block 1 from file and copy it into array
other instructions based on array content
read block 2 from file and copy it into array
other instructions based on array content
...up to the end of file
>> struct myStruct {
>> unsigned char field1[2];
>> unsigned char field2[30];
>> };
>
> ... but here comes the "splitting it in the two fields" part,
> which you're going about (as several people have told you) in an
> unreliable way.
Logically the block is splitted in two fields, so it is useful to have a
struct like this. But I understand I can't read bytes from file and
directly copy them into the structure. I have to use a function that
reads exactly N bytes and copy the two fields into the structure.
>> I thought I could have read the block and copy it directly to myStruct.
>> Anyway if padding could be present in myStruct, I can't use this
>> approach.
>>
>> Maybe the best approach is:
>>
>> #define FIELD1_OFFSET 0
>> #define FIELD1_SIZE 2
>> #define FIELD2_OFFSET FIELD1_SIZE
>> #define BLOCK_MAXSIZE 32
>> void read_block(struct myStruct *s, size_t block_size) {
>> unsigned char block[BLOCK_MAXSIZE];
>> <read BLOCK_MAXSIZE bytes and copy it in block array>
>> memcpy(s->field1, &block[FIELD1_OFFSET], FIELD1_SIZE);
>> memcpy(s->field2, &block[FIELD2_OFFSET], block_size - FIELD1_SIZE);
>> }
>>
>> Here block_size is passed as an argument, because I don't know it in
>> advance.
>
> That's odd. Where do you learn `block_size', *before* reading
> the first two bytes of your blob?
Yes, now I think it's clearer. See above.
> And if `block_size' turns out to
> be less than thirty-two, how does your "read BLOCK_MAXSIZE bytes"
> avoid running off the end and into whatever follows the blob?
Indeed I was wrong. The code below should be correct.
#define FIELD1_OFFSET 0
#define FIELD1_SIZE 2
#define FIELD2_OFFSET FIELD1_SIZE
#define BLOCK_MAXSIZE 32
void read_block(struct myStruct *s, size_t block_size) {
unsigned char block[BLOCK_MAXSIZE];
<read block_size bytes and copy it in block array>
memcpy(s->field1, &block[FIELD1_OFFSET], FIELD1_SIZE);
memcpy(s->field2, &block[FIELD2_OFFSET], block_size - FIELD1_SIZE);
}