source: trunk/src/core/RpLibrary.cc @ 83

Last change on this file since 83 was 83, checked in by dkearney, 19 years ago
  1. More cleaning of RpUnits and RpLibrary? code
  2. added rp_result code to c++/fortran/c code
  3. added rp_children, rp_lib_node[comp,type,id] for fortran code (need to test)
  4. adjusted convert function to recognize statements as follows:

convert("5J","neV")
convert("3.12075e+28neV","J")

  1. made joules a metric unit in RpUnits.cc
  2. tested examples/app-fermi/fortran/fermi.f with new rappture library.

added units conversion.

File size: 20.3 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture Library Source
4 *
5 * ======================================================================
6 *  AUTHOR:  Derrick Kearney, Purdue University
7 *  Copyright (c) 2005
8 *  Purdue Research Foundation, West Lafayette, IN
9 * ======================================================================
10 */
11
12#include "RpLibrary.h"
13
14std::string
15RpLibrary::_get_attribute(scew_element* element, std::string attributeName)
16{
17    scew_attribute* attribute = NULL;
18    std::string attrVal;
19    // int attrValSize = 0;
20
21    if (element != NULL)
22    {
23        if (scew_attribute_count(element) > 0) {
24
25            while((attribute=scew_attribute_next(element, attribute)) != NULL)
26            {
27                if (    strcmp( scew_attribute_name(attribute),
28                                attributeName.c_str()) == 0     ){
29                    attrVal = scew_attribute_value(attribute);
30                }
31            }
32        }
33        else {
34            // there are no attributes, count == 0
35        }
36    }
37
38    return attrVal;
39}
40
41int
42RpLibrary::_path2list (std::string& path, std::string** list, int listLen)
43{
44    std::string::size_type pos = 0;
45    std::string::size_type start = 0;
46    int index = 0;
47    int retVal = 0;
48
49    // listLen should be the highest index + 1
50    for (   pos = path.find(".",0);
51            (pos != std::string::npos) || (index >= listLen);
52            pos = path.find(".",pos)   )
53    {
54        list[index++] = new std::string(path.substr(start,pos-start));
55        start = ++pos;
56    }
57
58    // add the last path to the list
59    if (index < listLen) {
60        // error checking for path names?
61        // what if you get something like p1.p2. ?
62        list[index] = new std::string(path.substr(start,path.length()-start));
63    }
64
65    retVal = index++;
66
67    // null out the rest of the pointers so we know where to stop free'ing
68    while (index < listLen) {
69        list[index++] = NULL;
70    }
71
72    return retVal;
73}
74
75std::string
76RpLibrary::_node2name (scew_element* node)
77{
78    // XML_Char const* name = _get_attribute(node,"id");
79    std::string name = _get_attribute(node,"id");
80    std::stringstream retVal;
81    XML_Char const* type = NULL;
82    scew_element* parent = NULL;
83    scew_element** siblings = NULL;
84    unsigned int count = 0;
85    int tmpCount = 0;
86    int index = 0;
87    std::string indexStr;
88
89    type = scew_element_name(node);
90    parent = scew_element_parent(node);
91
92    // if (name == NULL) {
93    if (name.empty()) {
94        siblings = scew_element_list(parent, type, &count);
95        if (count > 0) {
96            tmpCount = count;
97            while ((index < tmpCount) && (siblings[index] != node)) {
98                index++;
99            }
100
101            if (index < tmpCount) {
102
103                if (index > 0) {
104
105                    retVal << type << --index;
106                }
107                else {
108
109                    retVal << type;
110                }
111
112                /*
113                if (retVal == NULL) {
114                    // error with allocating space
115                    return NULL;
116                }
117                */
118            }
119        }
120
121        scew_element_list_free(siblings);
122
123    }
124    else {
125
126        retVal << name;
127    }
128
129    return (retVal.str());
130}
131
132std::string
133RpLibrary::_node2comp (scew_element* node)
134{
135    // XML_Char const* name = _get_attribute(node,"id");
136    std::string name = _get_attribute(node,"id");
137    std::stringstream retVal;
138    XML_Char const* type = NULL;
139    scew_element* parent = NULL;
140    scew_element** siblings = NULL;
141    unsigned int count = 0;
142    int tmpCount = 0;
143    int index = 0;
144    std::string indexStr;
145
146    type = scew_element_name(node);
147    parent = scew_element_parent(node);
148
149    // if (name == NULL) {
150    if (name.empty()) {
151        siblings = scew_element_list(parent, type, &count);
152        if (count > 0) {
153            tmpCount = count;
154            while ((index < tmpCount) && (siblings[index] != node)) {
155                index++;
156            }
157
158            if (index < tmpCount) {
159
160                if (index > 0) {
161                    retVal << type << --index;
162                }
163                else {
164                    retVal << type;
165                }
166
167                /*
168                if (retVal == NULL) {
169                    // error with allocating space
170                    return NULL;
171                }
172                */
173            }
174
175        }
176        else {
177            // count == 0 ???
178        }
179        scew_element_list_free(siblings);
180
181    }
182    else {
183        // node has attribute id
184        //
185
186        // retVal = scew_strjoinXX(type,name);
187        retVal << type << "(" << name << ")";
188
189    }
190
191    return (retVal.str());
192}
193
194int
195RpLibrary::_splitPath (std::string& path, std::string& tagName, int* idx, std::string& id )
196{
197    int stop = 0;
198    int start = 0;
199    int index = path.length();
200
201    if (index) {
202        index--;
203    }
204
205    if (!path.empty()) {
206        if (path[index] == ')') {
207            stop = index;
208            while (path[index] != '(') {
209                index--;
210            }
211            start = index+1;
212            // strncpy(id,path+start,stop-start);
213            // id = new std::string(path.substr(start,stop-start));
214            id = path.substr(start,stop-start);
215            index--;
216        }
217        if (isdigit(path[index])) {
218            stop = index;
219            while (isdigit(path[index])) {
220                index--;
221            }
222            // sscanf(path[index+1],"%d",idx);
223            sscanf(path.c_str()+index+1,"%d",idx);
224        }
225        if (isalpha(path[index])) {
226            start = 0;
227            stop = index+1;
228            // tagName = new std::string(path.substr(start,stop-start));
229            tagName = path.substr(start,stop-start);
230            // strncpy(tagName,path+start,stop-start);
231        }
232    }
233    else {
234        tagName = "";
235        *idx = 0;
236        id = "";
237    }
238
239    return 1;
240}
241
242scew_element*
243RpLibrary::_find(std::string path, int create)
244{
245    // std::string* tagName;
246    // std::string* id;
247    std::string tagName = "";
248    std::string id = "";
249    int index = 0;
250    int listLen = (path.length()/2)+1;
251    std::string* list[listLen];
252    int path_size = 0;
253    int listIdx = 0;
254    unsigned int count = 0;
255    int tmpCount = 0;
256    int lcv = 0;
257    std::string tmpId;
258
259    scew_element* tmpElement = this->root;
260    scew_element* node = NULL;
261    scew_element** eleList = NULL;
262
263
264    if (path.empty()) {
265        //user gave an empty path
266        // return this;
267        return tmpElement;
268    }
269
270    if (!list) {
271        // error calloc'ing space for list
272        return NULL;
273    }
274
275    path_size = _path2list (path,list,listLen);
276
277    while ( (listIdx <= path_size) && (tmpElement != NULL ) ){
278
279        _splitPath(*(list[listIdx]),tagName,&index,id);
280
281        // if (id->empty()) {
282        if (id.empty()) {
283            /*
284            # If the name is like "type2", then look for elements with
285            # the type name and return the one with the given index.
286            # If the name is like "type", then assume the index is 0.
287            */
288
289            // eleList = scew_element_list(tmpElement, tagName->c_str(), &count);
290            eleList = scew_element_list(tmpElement, tagName.c_str(), &count);
291            tmpCount = count;
292            if (index < tmpCount) {
293                node = eleList[index];
294            }
295            else {
296                /* there is no element with the specified index */
297                node = NULL;
298            }
299
300            scew_element_list_free(eleList);
301            eleList = NULL;
302        }
303        else {
304
305            /* what if its like type2(id) ? */
306            /* still unresolved */
307
308            /*
309            # If the name is like "type(id)", then look for elements
310            # that match the type and see if one has the requested name.
311            # if the name is like "(id)", then look for any elements
312            # with the requested name.
313            */
314
315            // eleList = scew_element_list(tmpElement, tagName->c_str(), &count);
316            if (!tagName.empty()) {
317                eleList = scew_element_list(tmpElement, tagName.c_str(), &count);
318            }
319            else {
320                eleList = scew_element_list_all(tmpElement, &count);
321            }
322
323            tmpCount = count;
324            for (lcv = 0; (lcv < tmpCount); lcv++) {
325                tmpId = _get_attribute(eleList[lcv], "id");
326                if (!tmpId.empty()) {
327                    // if (*id == tmpId) {
328                    if (id == tmpId) {
329                        node = eleList[lcv];
330                        break;
331                    }
332                }
333            }
334
335            if (lcv >= tmpCount) {
336                node = NULL;
337            }
338
339            scew_element_list_free(eleList);
340            eleList = NULL;
341
342        }
343
344        if (node == NULL) {
345            if (create == 0) {
346                // break out instead of returning because we still need to
347                // free the list variable
348                // return node;
349                tmpElement = node;
350                break;
351            }
352            else {
353                // create == 1
354                // we should create the rest of the path
355
356                // create the new element
357                // need to figure out how to properly number the new element
358                // node = scew_element_add(tmpElement,tagName->c_str());
359                node = scew_element_add(tmpElement,tagName.c_str());
360                if (! node) {
361                    // a new element was not created
362                }
363
364                // add an attribute and attrValue to the new element
365                // if (id && !id->empty()) {
366                    // scew_element_add_attr_pair(node,"id",id->c_str());
367                if (!id.empty()) {
368                    scew_element_add_attr_pair(node,"id",id.c_str());
369                }
370            }
371        }
372
373
374        // change this so youre not allocating and deallocating so much.
375        // make it static or something.
376        // if (tagName)    { delete (tagName); }
377        // if (id)         { delete (id); }
378        tagName = "";
379        id = "";
380        index = 0;
381        tmpElement = node;
382        listIdx++;
383    }
384
385    // need to free the strings inside of list
386
387    if (list) {
388        for (listIdx = 0; listIdx < listLen; listIdx++) {
389            if (list[listIdx]) {
390                delete(list[listIdx]);
391                list[listIdx] = NULL;
392            }
393        }
394
395        // should we really be freeing list since its on the stack as a fxn variable?
396        // free(list);
397        // list = NULL;
398    }
399
400
401    return tmpElement;
402}
403
404
405RpLibrary*
406RpLibrary::element (std::string path, std::string as)
407{
408    RpLibrary* retLib;
409
410    if (path.empty()) {
411        // an empty path returns the current RpLibrary
412        return this;
413    }
414
415    scew_element* retNode = _find(path,0);
416
417    if (retNode == NULL) {
418        // add error information as to why we are returning NULL
419        return NULL;
420    }
421
422    retLib = new RpLibrary( retNode );
423
424    if (!retLib) {
425        // add error information as to why we are returning NULL
426        /* there was an error mallocing memory for a RpLibrary object */
427        return NULL;
428    }
429
430    return retLib;
431}
432
433/*
434// as not implemented, use nodeType, nodeId, nodeComp.
435RpLibrary**
436RpLibrary::children (std::string path, std::string as, std::string type)
437{
438    RpLibrary** retLib = NULL;
439    int childCount = 0;
440    int childNum = 0;
441    scew_element* parentNode = NULL;
442    scew_element* childNode = NULL;
443    std::string childName = "";
444
445    if (path.empty()) {
446        // an empty path returns the current RpLibrary
447        // you can still get the children of the root node
448        parentNode = this->root;
449    }
450    else {
451        parentNode = _find(path,0);
452    }
453
454    if (parentNode == NULL) {
455        // node not found
456        // add error code here
457        return NULL;
458    }
459
460    childCount = scew_element_count(parentNode);
461
462    // even if there are no children, we can send back a null array
463    retLib = new RpLibrary*[childCount+1];
464
465    if (!retLib) {
466        // there was an error mallocing memory for a RpLibrary object
467        return NULL;
468    }
469
470    if (childCount) {
471
472        while ( (childNode = scew_element_next(parentNode,childNode)) ) {
473            if (childNode) {
474                if (!type.empty()) {
475                    childName = scew_element_name(childNode);
476                    if (type == childName) {
477                        retLib[childNum++] = new RpLibrary( childNode );
478                    }
479                }
480                else {
481                    retLib[childNum++] = new RpLibrary( childNode );
482                }
483            }
484            else {
485                // somthing happened within scew, get error code and display
486                return NULL;
487            }
488        }
489    }
490
491    std::cout << "childNum = " << childNum << std::endl;
492    retLib[childNum] = NULL;
493
494    // how do you free this??
495    return retLib;
496}
497*/
498
499RpLibrary*
500RpLibrary::children (   std::string path,
501                        RpLibrary* rpChildNode,
502                        std::string type,
503                        int* childCount)
504{
505    static std::string old_path = "";
506    static RpLibrary* retLib = NULL;
507    int myChildCount = 0;
508    scew_element* parentNode = NULL;
509    scew_element* childNode = NULL;
510    std::string childName = "";
511
512
513    if (path.empty()) {
514        // an empty path uses the current RpLibrary as parent
515        parentNode = this->root;
516    }
517    else {
518        // check to see if this path is the same as the one set
519        // in the last call to this function.
520        // if so, then we dont need to reset the parentNode
521        if ( path.compare(old_path) == 0 ) {
522            parentNode = NULL;
523        }
524        // we need to search for a new parentNode
525        else {
526            parentNode = _find(path,0);
527            if (parentNode == NULL) {
528                // node not found
529                // add error code here
530                return NULL;
531            }
532        }
533    }
534
535    old_path = path;
536
537
538    if (rpChildNode) {
539        childNode = rpChildNode->root;
540    }
541
542    if (parentNode) {
543        myChildCount = scew_element_count(parentNode);
544        std::cout << "myChildCount = " << myChildCount << std::endl;
545    }
546
547    if (childCount) {
548        *childCount = myChildCount;
549    }
550
551    if ( (childNode = scew_element_next(parentNode,childNode)) ) {
552
553        if (!type.empty()) {
554            childName = scew_element_name(childNode);
555            if (type == childName) {
556                // clean up old memory
557                if (retLib) {
558                    delete retLib;
559                }
560                retLib = new RpLibrary( childNode );
561            }
562        }
563        else {
564            // clean up old memory
565            if (retLib) {
566                delete retLib;
567            }
568            retLib = new RpLibrary( childNode );
569        }
570    }
571    else {
572        // somthing happened within scew, get error code and display
573        // its probable there are no more child elements left to report
574        // clean up old memory
575        if (retLib) {
576            delete retLib;
577        }
578        retLib = NULL;
579    }
580
581    return retLib;
582}
583
584
585RpLibrary*
586RpLibrary::get (std::string path)
587{
588    RpLibrary* retVal;
589
590    scew_element* retNode = _find(path,0);
591
592    if (retNode == NULL) {
593        // need to raise error
594        return NULL;
595    }
596
597    retVal = new RpLibrary(retNode);
598
599    //who delete's this memory?
600    return retVal;
601}
602
603std::string
604RpLibrary::getString (std::string path)
605{
606    std::string retVal;
607
608    /*
609    if (path.empty()) {
610        return "";
611    }
612    */
613
614    scew_element* retNode = _find(path,0);
615
616    if (retNode == NULL) {
617        // need to raise error
618        return "";
619    }
620
621    retVal = std::string(scew_element_contents(retNode));
622
623    return retVal;
624}
625
626double
627RpLibrary::getDouble (std::string path)
628{
629    std::string retValStr = "";
630    double retValDbl = 0;
631
632    retValStr = this->getString(path);
633    retValDbl = atof(retValStr.c_str());
634
635    // how do we reaise error?
636    // currently we depend on getString to raise the error
637    return retValDbl;
638}
639
640
641RpLibrary&
642RpLibrary::put ( std::string path, std::string value, std::string id, int append )
643{
644    scew_element* retNode = NULL;
645    std::string tmpVal = "";
646    const char* contents = NULL;
647
648    if (! path.empty()) {
649        retNode = _find(path,1);
650
651        if (retNode) {
652
653            if (append) {
654                if ( (contents = scew_element_contents(retNode)) ) {
655                    tmpVal = std::string(contents);
656                }
657                value = tmpVal + value;
658            }
659
660            scew_element_set_contents(retNode,value.c_str());
661        }
662    }
663
664    return *this;
665}
666
667RpLibrary&
668RpLibrary::put ( std::string path, double value, std::string id, int append )
669{
670    std::stringstream valStr;
671
672    valStr << value;
673
674    return this->put(path,valStr.str(),id,append);
675}
676
677/*
678RpLibrary&
679RpLibrary::remove ( std::string path )
680{
681    scew_element* ele = _find(path,0);
682    RpLibrary* retLib;
683    if (ele) {
684        retLib = new RpLibrary(ele)
685    }
686
687    return *retLib
688}
689*/
690
691std::string
692RpLibrary::xml ()
693{
694    std::stringstream outString;
695
696    outString << "<?xml version=\"1.0\"?>\n";
697    print_element(this->root, 0, outString);
698
699    return outString.str();
700}
701
702std::string
703RpLibrary::nodeType ()
704{
705    return std::string(scew_element_name(root));
706}
707
708std::string
709RpLibrary::nodeId ()
710{
711    return _node2name(root);
712}
713
714std::string
715RpLibrary::nodeComp ()
716{
717    return _node2comp(root);
718}
719
720/*
721 * ----------------------------------------------------------------------
722 *  FUNCTION: rpResult
723 *
724 *  Clients call this function at the end of their simulation, to
725 *  pass the simulation result back to the Rappture GUI.  It writes
726 *  out the given XML object to a runXXX.xml file, and then writes
727 *  out the name of that file to stdout.
728 * ======================================================================
729 *  AUTHOR:  Michael McLennan, Purdue University
730 *  Copyright (c) 2004-2005
731 *  Purdue Research Foundation, West Lafayette, IN
732 * ======================================================================
733 */
734void
735RpLibrary::result() {
736    std::stringstream outputFile;
737    std::fstream file;
738    std::string xmlText = "";
739    time_t t = 0;
740
741    outputFile << "run" << (int)time(&t) << ".xml";
742    file.open(outputFile.str().c_str(),std::ios::out);
743
744    if ( file.is_open() ) {
745        xmlText = xml();
746        if (!xmlText.empty()) {
747            file << xmlText;
748        }
749    }
750    std::cout << "=RAPPTURE-RUN=>" << outputFile.str() << std::endl;
751}
752
753void
754RpLibrary::print_indent(unsigned int indent, std::stringstream& outString)
755{
756
757    while ( (indent--) > 0)
758    {
759        outString << "\t";
760    }
761
762    // keep this around incase you want to use spaces instead of tabs
763    // while ( ((indent--)*4) > 0)
764    // {
765    //     outString << " ";
766    // }
767}
768
769void
770RpLibrary::print_attributes(scew_element* element, std::stringstream& outString)
771{
772    scew_attribute* attribute = NULL;
773
774    if (element != NULL)
775    {
776        /**
777         * Iterates through the element's attribute list, printing the
778         * pair name-value.
779         */
780        attribute = NULL;
781        while ((attribute = scew_attribute_next(element, attribute)) != NULL)
782        {
783            outString << " " << scew_attribute_name(attribute) << "=\"" <<
784                   scew_attribute_value(attribute) << "\"";
785        }
786    }
787}
788
789
790void
791RpLibrary::print_element(   scew_element* element,
792                            unsigned int indent,
793                            std::stringstream& outString    )
794{
795    scew_element* child = NULL;
796    XML_Char const* contents = NULL;
797
798    if (element == NULL)
799    {
800        return;
801    }
802
803    /**
804     * Prints the starting element tag with its attributes.
805     */
806    print_indent(indent, outString);
807    outString << "<" << scew_element_name(element);
808    print_attributes(element,outString);
809    outString << ">";
810    contents = scew_element_contents(element);
811    if (contents == NULL)
812    {
813        outString << "\n";
814    }
815
816    /**
817     * Call print_element function again for each child of the
818     * current element.
819     */
820    child = NULL;
821    while ((child = scew_element_next(element, child)) != NULL)
822    {
823        print_element(child, indent + 1, outString);
824    }
825
826    /* Prints element's content. */
827    if (contents != NULL)
828    {
829        outString << contents;
830    }
831    else
832    {
833        print_indent(indent, outString);
834    }
835
836    /**
837     * Prints the closing element tag.
838     */
839    outString << "</" << scew_element_name(element) << ">\n" ;
840}
841
Note: See TracBrowser for help on using the repository browser.