From: Greg Menke
Subject: Reading arrays of structs with binary-types
Date: 
Message-ID: <m3ps48iyxk.fsf@venus.pienet>
I'm writing an app to read files of data transfer timing info and
generate graphs from it.  The data was generated via C and consists of a
struct, one element of which is an array of structs of a different type,
and is of fixed & known length.

I'm setting up the classes using binary-types to read the data in.  The
individual fields in the struct are working fine & endianness is under
control, but I've not been able to deduce how to handle the struct
array.  Ideally, what I'd like to have is the given slot in the
top-level class containing a vector which itself contains the arrayed
structs.

If at all possible, I'd like to avoid adding duplicate slots to
represent each array entry.  Any hints are much appreciated.

Thanks,

Greg

From: Dan Bensen
Subject: Re: Reading arrays of structs with binary-types
Date: 
Message-ID: <f47h0v$1tu$1@wildfire.prairienet.org>
Greg Menke wrote:
> The data consists of a struct, one element of which is an array
> of structs of a different type, and is of fixed & known length.

> Ideally, what I'd like to have is the given slot in the top-level
> class containing a vector which itself contains the arrayed
> structs.
> If at all possible, I'd like to avoid adding 
> duplicate slots to represent each array entry.

Why would you have to do that?

-- 
Dan
www.prairienet.org/~dsb/
From: Greg Menke
Subject: Re: Reading arrays of structs with binary-types
Date: 
Message-ID: <m3tztkul4l.fsf@venus.pienet>
Dan Bensen <··········@cyberspace.net> writes:

> Greg Menke wrote:
> 
> > Ideally, what I'd like to have is the given slot in the top-level
> > class containing a vector which itself contains the arrayed
> > structs.
> > If at all possible, I'd like to avoid adding duplicate slots to
> > represent each array entry.
> 
> Why would you have to do that?

Shrug.. lacking some means of reading the array of structs, then one
approach is to add a sufficient # of slots, varying only by name, to
contain the array, then write a method to make a vector out of their
contents.  Do you have a better idea?

Thanks,

Greg
From: Dan Bensen
Subject: Re: Reading arrays of structs with binary-types
Date: 
Message-ID: <f48onr$ejq$1@wildfire.prairienet.org>
Greg Menke wrote:
> Dan Bensen <··········@cyberspace.net> writes:
>>> If at all possible, I'd like to avoid adding duplicate slots to
>>> represent each array entry.
>> Why would you have to do that?
> Shrug.. lacking some means of reading the array of structs, then one
> approach is to add a sufficient # of slots

You can read the array as usual.  If the struct type is called "outer"
and the array slot is called "array", then the name of the array in your 
struct is
   (outer-array my-struct)
so you can create a struct with
   (setf my-struct (make-outer :array (make-array *array-length*)))
or
   (setf my-struct (make-outer))
   (setf (outer-array my-struct) (make-array *array-length*))

then access an element of the array with
   (aref (outer-array my-struct) n)
and if an element of the array is a struct of type "inner" with
a slot named "var", then you can access the var slot with
   (inner-var (aref (outer-array my-struct) n))
as in
   (setf (inner-var (aref (outer-array my-struct) n)) 1.414)
   (format t "var[n] = ~A~%"
       (inner-var (aref (outer-array my-struct) n)))

-- 
Dan
www.prairienet.org/~dsb/
From: Greg Menke
Subject: Re: Reading arrays of structs with binary-types
Date: 
Message-ID: <m3odjsui2n.fsf@venus.pienet>
Dan Bensen <··········@cyberspace.net> writes:
> Greg Menke wrote:
> > Dan Bensen <··········@cyberspace.net> writes:
> >>> If at all possible, I'd like to avoid adding duplicate slots to
> >>> represent each array entry.
> >> Why would you have to do that?
> > Shrug.. lacking some means of reading the array of structs, then one
> > approach is to add a sufficient # of slots
> 
> You can read the array as usual.  If the struct type is called "outer"
> and the array slot is called "array", then the name of the array in your
> struct is
>    (outer-array my-struct)
> so you can create a struct with
>    (setf my-struct (make-outer :array (make-array *array-length*)))
> or
>    (setf my-struct (make-outer))
>    (setf (outer-array my-struct) (make-array *array-length*))
> 

I think I've not communicated well.  This is the data structure I'm
trying to read;



typedef struct 
{
      long      tv_secs;
      long      tv_usecs;

}   __attribute__ ((packed))   timerec_t;


typedef struct filedefheader
{
      unsigned char     filename[ FHDR_FILENAME_MAX_LEN ];
      unsigned long     file_length;

      timerec_t         timerecs[ MAX_TIME_RECORDS ];
      int               num_timerecs;

}  __attribute__ ((packed))   fdheader_t;



The #defines are known.  Below is the lisp that reads the nested
structure in.  You can see the duplicated slots, what I'd prefer is to
have one "trecs" slot which contains a vector of all 10 of the structure
entries.  I like how binary-types supportse nested structures- its quite
handy and avoids "userspace" I/O, the entire struct being read in via
one (read-binary) call- but I've not been able to figure out how to
represent the structure array.



(define-binary-class btrecord ()
  ((secs  :accessor tv-secs  :binary-type u32)
   (usecs :accessor tv-usecs :binary-type u32)))


(defmethod extract-btrecord-array ((fhdr file-metadata))
  (vector (slot-value fhdr 'trecs0)
          (slot-value fhdr 'trecs1)
          (slot-value fhdr 'trecs2)
          (slot-value fhdr 'trecs3)
          (slot-value fhdr 'trecs4)
          (slot-value fhdr 'trecs5)
          (slot-value fhdr 'trecs6)
          (slot-value fhdr 'trecs7)
          (slot-value fhdr 'trecs8)
          (slot-value fhdr 'trecs9)))



(define-binary-class file-metadata ()
  ((fname :accessor md-filename 
          :binary-type (define-null-terminated-string fname 200) )

   (flen  :accessor md-filelen  :binary-type u32)

   (trecs0 :binary-type btrecord)
   (trecs1 :binary-type btrecord)
   (trecs2 :binary-type btrecord)
   (trecs3 :binary-type btrecord)
   (trecs4 :binary-type btrecord)
   (trecs5 :binary-type btrecord)
   (trecs6 :binary-type btrecord)
   (trecs7 :binary-type btrecord)
   (trecs8 :binary-type btrecord)
   (trecs9 :binary-type btrecord)
          
   (numr  :accessor md-numrecs  :binary-type s32)))




Thanks,

Greg
From: Dan Bensen
Subject: Re: Reading arrays of structs with binary-types
Date: 
Message-ID: <f4932t$hpk$1@wildfire.prairienet.org>
Greg Menke wrote:
> (define-binary-class file-metadata ()
>   ((fname :accessor md-filename 
>           :binary-type (define-null-terminated-string fname 200) )
>    (flen  :accessor md-filelen  :binary-type u32)
>    (trecs0 :binary-type btrecord)
>    (trecs1 :binary-type btrecord)
>    (trecs2 :binary-type btrecord)
>    ...

I see.  Unless there's some kind of special binary array,
you could just define a binary class for the inner struct,
define a regular CL array of those binary objects,
and define file-metadata as a regular CLOS class
containing the array, with other binary classes or a single
binary subcontainer class defined for the other slots.
Unless binary objects are also allowed to contain regular
slots(?).  Then you could just mix a regular array of inner
binaries with the other binary slots.  Either way, you should
at least be able to make it work with a regular CLOS object.

-- 
Dan
www.prairienet.org/~dsb/