From: William F. D. <wil...@th...> - 2007-01-05 21:30:33
|
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 ?!) > -- William F Dowling wil...@th... www.scientific.thomson.com |