|
From: Mike A. <mik...@au...> - 2007-01-08 08:53:49
|
Follow up to this - am i right in assuming that we should not be accessing the
attributes in an 'end' block ?
If so - should doing this cause an error ?
(My code wasn't working until I moved some of the checking to the 'start'
block instead..)
On Friday 05 January 2007 21:30, William F. Dowling wrote:
> Hi Mike,
>
> This must be a common app for flexml -- it's one of my own main uses for
> it. I too need to do marshalling and the reverse for basic values, and
> recursive types built from them by vectoring and map (hash-table)
> formation, down to any depth. (E.g. lists of lists of maps of strings,
> etc.) My implementation language is C++, which (IMO) makes things a
> little cleaner than straight C since I don't need to use void*, or
> casting operations anyplace.
>
> It is a fundamental limitation of flex that the communication between
> actions can only take place by global variables. There is no way around
> that.
>
> But you can structure your code so that it is quite clean by using stack
> operations. This strategy will work for any basic data types and any
> collection of type constructors (e.g. vector-formation,
> struct-formation, binding_comp_list-formation, etc.) One global Stack
> object is all you need.
>
> When a start tag is seen in the XML, push onto the stack a placeholder
> object. When an end tag is seen, you'll know how many objects to pop
> (and what types they should be); pop them and build your object, putting
> it into the placeholder you had pushed. For type constructors (like
> vector<> in C++) that take a variable number of parameters, use the
> 'cons' strategy from LISP; that is, cons in each argument as you
> encounter it, as if you were building a right-branching binary tree.
>
> You definitely don't want to be allocating and freeing in every action
> -- let your stack operation (push/pop) definitions do that for you.
>
> I can send you some sample C++ code that implements these ideas if that
> would be useful.
>
> Will
>
> On Fri, 2007-01-05 at 17:10 +0000, Mike Aubury wrote:
> > Hi - i've managed to do some *really* nice things with this software -
> > but one thing keeps me back.
> > Is there anyway to pass data around within the actions ?
> >
> >
> > Background
> >
> > I'm trying to marshall (serialize) some C structures into XML.
> > I've got a program which parses a definition of a C structure (if you've
> > ever used RPCGEN or ONCRPC - it works on the same principle (and uses the
> > .x file syntax :-)) and generates some code which dumps the XML.
> >
> > I'm now trying to get my parser to generate the .dtd and .act files for
> > reading that file back in...
> >
> > Take this snippet of XML :
> >
> > <binding_comp_list>
> > <binding_comp_list__abind VALUE="0"/>
> > <binding_comp_list__type VALUE="70"/>
> > <binding_comp_list__data SET='TRUE' VALUE=""/>
> > </binding_comp_list>
> >
> > Ideally - I'd want to
> > 1) allocate some memory for the binding_comp_list structure
> > in the 'start' for 'binding_comp_list'
> > 2) use that parent to set the data..
> > 3) use that memory in the 'end' 'binding_comp_list' to set something
> > else..
> >
> > ATM - i've done it using a series of temporary variables - but its really
> > messy (because these things can recurse - so I can't just declare once
> > temporary binding_comp_list - I need to use a dynamic array..)
> > It gets even worse when the structure contains structure or an array ( or
> > an array of structures!)
> >
> >
> >
> > For reference - that binding_comp_list is defined as :
> >
> > struct binding_comp_list {
> > long abind;
> > int type;
> > string data; // basically a char*
> > };
> >
> >
> >
> > My current actions look like this (excuse any errors - i've modified this
> > from the original for readability!):
> >
> > <start tag='something_using_a_binding_comp_list'>
> > <![CDATA[
> > Allocate("binding_comp_list", (void *)&tmp_binding_comp_list,
> > &tmp_binding_comp_list_cnt, sizeof(struct binding_comp_list));
> > ]]>
> > </start>
> >
> >
> >
> > <end tag='something_using_a_binding_comp_list'>
> > <![CDATA[
> >
> > setsomething=tmp_binding_comp_list[tmp_binding_comp_list_cnt-1];
> >
> > FreeMemory("binding_comp_list",(void ***)&tmp_binding_comp_list,
> > &tmp_binding_comp_list_cnt,1);
> >
> > ]]>
> > </end>
> >
> >
> >
> > <end tag='binding_comp_list__abind'>
> > <![CDATA[
> > tmp_binding_comp_list[tmp_binding_comp_list_cnt-1]->abind=atol({VALUE})
> >;
> >
> > ]]>
> > </end>
> >
> >
> > <end tag='binding_comp_list__type'>
> > <![CDATA[
> > tmp_binding_comp_list[tmp_binding_comp_list_cnt-1]->type=atol({VALUE});
> > ]]>
> > </end>
> >
> > <end tag='binding_comp_list__data'>
> > <![CDATA[
> > if (isyes({SET})) {
> >
> > tmp_binding_comp_list[tmp_binding_comp_list_cnt-1]->data=strdup({VALUE});
> > } else {
> >
> > tmp_binding_comp_list[tmp_binding_comp_list_cnt-1]->data=0; }
> >
> > ]]>
> > </end>
> >
> > Any thoughts ?
> >
> >
> > (Or alternative ways of marshalling the C to XML and back ?!)
--
Mike Aubury
|