Question about String.unpack

E

Eric Jacoboni

Hi,

Say i've a C struct like that:

typedef struct {
char name[30];
double size;
int age;
char stuff;
} enreg_t;

This record is written in a file that i want to re-read with a Ruby
script (just a toy example... to understand).

I've not found a "clean" way to unpack such a record...

My C compiler gives me a total sizeof of 48, so i use a
fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather
'tricky' (i suppose we don't have always such a
information). Furthermore, the first element is completed with
garbage if the name field have less than 30 "useful" chars ("Doe",
for example).

I'm sure i'm missing something but i've not managed to find the right
way to do that.

Any clue?
 
L

Logan Capaldo

Hi,

Say i've a C struct like that:

typedef struct {
char name[30];
double size;
int age;
char stuff;
} enreg_t;

This record is written in a file that i want to re-read with a Ruby
script (just a toy example... to understand).

I've not found a "clean" way to unpack such a record...

My C compiler gives me a total sizeof of 48, so i use a
fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather
'tricky' (i suppose we don't have always such a
information). Furthermore, the first element is completed with
garbage if the name field have less than 30 "useful" chars ("Doe",
for example).

I'm sure i'm missing something but i've not managed to find the right
way to do that.

Any clue?

there isn't really a "clean" way to do this, since you are doing
something inherently un-clean.
However, to fix the string issue, a possible solution is:

str.gsub!(/\000.*/, '')

assuming of course that name is a c-string.
 
J

Jacob Repp

I'm curious about binary protocol parsing in ruby and have scratched
around for some kind of BinaryReader-ish interface for strings. Seems
like you could solve this if you know that your struct is in a string
you could say:

str =3D fd.sysread(n)
name =3D str.read_str(30)
size =3D str.read_double
age =3D str.read_int
stuff =3D str.read_c

I was going to write a native extension to do this after I finish my
current Ruby/AIO extension project. Unless there is something that
does this already (maybe in a cleaner/more ruby-ish way?)

Hi,

Say i've a C struct like that:

typedef struct {
char name[30];
double size;
int age;
char stuff;
} enreg_t;

This record is written in a file that i want to re-read with a Ruby
script (just a toy example... to understand).

I've not found a "clean" way to unpack such a record...

My C compiler gives me a total sizeof of 48, so i use a
fd.sysread(48).unpack(A32dIC) to re-read. But that seems rather
'tricky' (i suppose we don't have always such a
information). Furthermore, the first element is completed with
garbage if the name field have less than 30 "useful" chars ("Doe",
for example).

I'm sure i'm missing something but i've not managed to find the right
way to do that.

Any clue?

there isn't really a "clean" way to do this, since you are doing
something inherently un-clean.
However, to fix the string issue, a possible solution is:

str.gsub!(/\000.*/, '')

assuming of course that name is a c-string.
 
L

Logan Capaldo

--Apple-Mail-2--964562428
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


I'm curious about binary protocol parsing in ruby and have scratched
around for some kind of BinaryReader-ish interface for strings. Seems
like you could solve this if you know that your struct is in a string
you could say:

str = fd.sysread(n)
name = str.read_str(30)
size = str.read_double
age = str.read_int
stuff = str.read_c

I was going to write a native extension to do this after I finish my
current Ruby/AIO extension project. Unless there is something that
does this already (maybe in a cleaner/more ruby-ish way?)

This is pretty much exactly what unpack does anyway., except its one
method that uses a format string. If you wanted a more stream
oriented wrapper around this, you certainly could write one fairly
easily.

ri String#unpack


--Apple-Mail-2--964562428--
 
T

ts

E> Your struct says char name[30] not 32...

Yes, but there is alignement

He just want Z32 rather than A32

biocluster1% cat a.c
#include <stdio.h>
#include <string.h>

typedef struct {
char name[30];
double size;
int age;
char stuff;
} enreg_t;

main()
{
FILE *fd;
enreg_t enreg;
strcpy(enreg.name, "abc");
enreg.size = 12.0;
enreg.age = 12;
enreg.stuff = 'a';
fd = fopen("aa", "w");
fwrite(&enreg, sizeof(enreg), 1, fd);
fclose(fd);
}
biocluster1%

biocluster1% ruby -e 'p a = IO::read("aa"); p a.unpack("Z32dIC")'
"abc\000\030\373\377\277U\203\004\010tp\001@\360z\001@8\373\377\277K\205\004\010\200\270\024@\000\000\000\000\000\000(@\f\000\000\000ae\001@"
["abc", 12.0, 12, 97]
biocluster1%


Guy Decoux
 
P

Patrick Hurley

E> Your struct says char name[30] not 32...

Yes, but there is alignement

He just want Z32 rather than A32

I would suggest that Z30xx would be a better choice.

pth
 
E

Eric Jacoboni

ts said:
E> Your struct says char name[30] not 32...

Yes, but there is alignement

He just want Z32 rather than A32

Thanks...

BTW: Eric, your message was not propagated to my Usenet Server...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,158
Latest member
Vinay_Kumar Nevatia
Top