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 |