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

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