source: trunk/src/core/RpLibrary.h @ 589

Last change on this file since 589 was 589, checked in by dkearney, 16 years ago

added c bindings to the putData and putFile functions
added example usage of putFile for c++ and c with example dx file
adjusted append flag from int to unsigned int on all c rpPut functions
adjusted a tcl units test

File size: 16.4 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture Library Header
4 *
5 * ======================================================================
6 *  AUTHOR:  Derrick Kearney, Purdue University
7 *  Copyright (c) 2004-2007  Purdue Research Foundation
8 *
9 *  See the file "license.terms" for information on usage and
10 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * ======================================================================
12 */
13
14#ifndef _RpLIBRARY_H
15#define _RpLIBRARY_H
16
17enum RP_LIBRARY_CONSTS {
18    RPLIB_OVERWRITE     = 0,
19    RPLIB_APPEND        = 1,
20    RPLIB_NO_TRANSLATE  = 0,
21    RPLIB_TRANSLATE     = 1,
22};
23
24
25#ifdef __cplusplus
26
27#include "scew/scew.h"
28#include "scew_extras.h"
29#include <iostream>
30#include <string>
31#include <sstream>
32#include <fstream>
33#include <stdlib.h>
34#include <errno.h>
35#include <time.h>
36#include <iterator>
37#include <cctype>
38#include <list>
39#include "RpBuffer.h"
40
41/* indentation size (in whitespaces) */
42
43#define INDENT_SIZE 4
44#define CREATE_PATH 1
45#define NO_CREATE_PATH 0
46#define E_QUEUE_SIZE 100
47
48#define TRANSLATE 1
49#define NO_TRANSLATE 0
50
51class RpLibrary
52{
53    public:
54
55        // users member fxns
56
57        RpLibrary* element (std::string path = "");
58        RpLibrary* parent (std::string path = "");
59
60        std::list<std::string> entities  (std::string path = "");
61        std::list<std::string> value     (std::string path = "");
62        std::list<std::string> diff      ( RpLibrary* otherLib,
63                                            std::string path);
64
65        bool isNull();
66
67        // should return RpObject& but for simplicity right now it doesnt
68        // RpObject will either be an Array, RpString, RpNumber ...
69
70        RpLibrary*  children  ( std::string path = "",
71                                RpLibrary* rpChildNode = NULL,
72                                std::string type = "",
73                                int* childCount = NULL  );
74
75        RpLibrary& childCount ( std::string path,
76                                int* childCount);
77
78        RpLibrary& copy       ( std::string toPath,
79                                std::string fromPath,
80                                RpLibrary* fromObj = NULL);
81
82        std::string get       ( std::string path = "",
83                                int translateFlag = RPLIB_TRANSLATE);
84        std::string getString ( std::string path = "",
85                                int translateFlag = RPLIB_TRANSLATE);
86
87        double      getDouble ( std::string path = "");
88        int         getInt    ( std::string path = "");
89        bool        getBool   ( std::string path = "");
90        // Rappture::Buffer& getData (std::string path);
91
92        /*
93         * Should return some kind of RpError object
94        RpLibrary&  get       ( std::string path = "",
95                                std::string retVal = "",
96                                int translateFlag = RPLIB_TRANSLATE);
97
98        RpLibrary&  get       ( std::string path = "",
99                                double retVal = 0.0,
100                                int translateFlag = RPLIB_TRANSLATE);
101
102        RpLibrary&  get       ( std::string path = "",
103                                int retVal = 0,
104                                int translateFlag = RPLIB_TRANSLATE);
105
106        RpLibrary&  get       ( std::string path = "",
107                                bool retVal = false,
108                                int translateFlag = RPLIB_TRANSLATE);
109        */
110
111        RpLibrary& put (    std::string path,
112                            std::string value,
113                            std::string id = "",
114                            int append = RPLIB_OVERWRITE,
115                            int translateFlag = RPLIB_TRANSLATE   );
116
117        RpLibrary& put (    std::string path,
118                            double value,
119                            std::string id = "",
120                            int append = RPLIB_OVERWRITE    );
121
122        RpLibrary& put (    std::string path,
123                            RpLibrary* value,
124                            std::string id = "",
125                            int append = RPLIB_OVERWRITE    );
126
127        RpLibrary& putData( std::string path,
128                            const char* bytes,
129                            int nbytes,
130                            int append = RPLIB_OVERWRITE    );
131
132        RpLibrary& putFile( std::string path,
133                            std::string fileName,
134                            bool binary,
135                            int append = RPLIB_OVERWRITE    );
136
137        RpLibrary* remove (std::string path = "");
138
139        std::string xml();
140
141        std::string nodeType();
142        std::string nodeId();
143        std::string nodeComp();
144        std::string nodePath();
145
146        void result();
147
148        // no arg constructor
149        // used when we dont want to read an xml file to populate the xml tree
150        // we are building a new xml structure
151        RpLibrary ()
152            :   parser      (NULL),
153                tree        (NULL),
154                root        (NULL),
155                freeTree    (1),
156                freeRoot    (1)
157        {
158            tree = scew_tree_create();
159            root = scew_tree_add_root(tree, "run");
160        }
161
162        RpLibrary (
163                    std::string filePath
164                )
165            :   parser      (NULL),
166                tree        (NULL),
167                root        (NULL),
168                freeTree    (0),
169                freeRoot    (1)
170        {
171
172            if (filePath.length() != 0) {
173                // file path should not be null or empty string unless we are
174                // creating a new xml file
175
176                parser = scew_parser_create();
177
178                scew_parser_ignore_whitespaces(parser, 1);
179
180                /* Loads an XML file */
181                if (!scew_parser_load_file(parser, filePath.c_str()))
182                {
183                    scew_error code = scew_error_code();
184                    printf("Unable to load file (error #%d: %s)\n", code,
185                           scew_error_string(code));
186
187                    /*
188                    std::cout << "Unable to load file (error #" \
189                              << code << ": " << scew_error_string(code) \
190                              << ")\n" << std::endl;
191                    */
192
193                    if (code == scew_error_expat)
194                    {
195                        enum XML_Error expat_code =
196                            scew_error_expat_code(parser);
197                        printf("Expat error #%d (line %d, column %d): %s\n",
198                               expat_code,
199                               scew_error_expat_line(parser),
200                               scew_error_expat_column(parser),
201                               scew_error_expat_string(expat_code));
202                    }
203                    // should probably exit program or something
204                    // return EXIT_FAILURE;
205                    fflush(stdout);
206                    scew_parser_free(parser);
207                    parser = NULL;
208                }
209                else
210                {
211                    tree = scew_parser_tree(parser);
212                    freeTree = 0;
213                    root = scew_tree_root(tree);
214                }
215            }
216            else {
217                // create a new xml (from an empty file)
218            }
219        }
220
221
222        // copy constructor
223        // for some reason making this a const gives me problems
224        // when calling xml()
225        // need help looking into this
226        // RpLibrary ( const RpLibrary& other )
227        RpLibrary ( RpLibrary& other )
228            : parser    (NULL),
229              tree      (NULL),
230              root      (NULL),
231              freeTree  (0),
232              freeRoot  (1)
233        {
234            std::string buffer;
235            int buffLen;
236
237            // fill in the current RpLibrary's data with other's data
238            parser = scew_parser_create();
239            scew_parser_ignore_whitespaces(parser, 1);
240
241            // Loads the XML from other
242            // the length cannot be 0 because xml() should not be returning
243            // empty strings
244            buffer = other.xml();
245            buffLen = buffer.length();
246
247            if (buffLen > 0) {
248                if (!scew_parser_load_buffer(parser,buffer.c_str(),buffLen))
249                {
250                    // there was an error loading the buffer
251                    // how do you tell the user, you couldn't make a copy?
252                    scew_error code = scew_error_code();
253                    printf("Unable to load buffer (error #%d: %s)\n", code,
254                           scew_error_string(code));
255
256                    if (code == scew_error_expat)
257                    {
258                        enum XML_Error expat_code =
259                            scew_error_expat_code(parser);
260                        printf("Expat error #%d (line %d, column %d): %s\n",
261                               expat_code,
262                               scew_error_expat_line(parser),
263                               scew_error_expat_column(parser),
264                               scew_error_expat_string(expat_code));
265                    }
266
267                    // return an empty RpLibrary?
268                    // return EXIT_FAILURE;
269
270                    parser = NULL;
271                }
272                else {
273
274                    // parsing the buffer was successful
275                    // populate the new data members.
276
277                    tree = scew_parser_tree(parser);
278                    freeTree = 0;
279                    freeRoot = 1;
280                    root = scew_tree_root(tree);
281
282                }
283
284            } // end if (buffer.length() != 0) {
285        }// end copy constructor
286
287        // copy assignment operator
288        // for some reason making this a const gives me problems
289        // when calling xml()
290        // need help looking into this
291        // RpLibrary& operator= (const RpLibrary& other) {
292        RpLibrary& operator= (RpLibrary& other) {
293
294            std::string buffer;
295            int buffLen;
296
297            scew_parser* tmp_parser;
298            scew_tree* tmp_tree;
299            scew_element* tmp_root;
300            int tmp_freeTree;
301            int tmp_freeRoot;
302
303            if (this != &other) {
304
305                tmp_parser   = parser;
306                tmp_tree     = tree;
307                tmp_root     = root;
308                tmp_freeTree = freeTree;
309                tmp_freeRoot = freeRoot;
310
311                // fill in the current RpLibrary's data with other's data
312                parser = scew_parser_create();
313                scew_parser_ignore_whitespaces(parser, 1);
314
315                // Loads the XML from other
316                // the length cannot be 0 because xml()
317                // should not be returning empty strings
318                buffer = other.xml();
319                buffLen = buffer.length();
320
321                if (buffLen > 0) {
322                    if (!scew_parser_load_buffer(parser,buffer.c_str(),buffLen))
323                    {
324                        // there was an error loading the buffer
325                        // how do you tell the user, you couldn't make a copy?
326                        scew_error code = scew_error_code();
327                        printf("Unable to load buffer (error #%d: %s)\n", code,
328                               scew_error_string(code));
329
330                        if (code == scew_error_expat)
331                        {
332                            enum XML_Error expat_code =
333                                scew_error_expat_code(parser);
334                            printf("Expat error #%d (line %d, column %d): %s\n",
335                                   expat_code,
336                                   scew_error_expat_line(parser),
337                                   scew_error_expat_column(parser),
338                                   scew_error_expat_string(expat_code));
339                        }
340
341                        // return things back to the way they used to be
342                        // or maybe return an empty RpLibrary?
343                        // return EXIT_FAILURE;
344
345                        // return this object to its previous state.
346                        parser = tmp_parser;
347                    }
348                    else {
349
350                        // parsing the buffer was successful
351                        // populate the new data members.
352
353                        tree = scew_parser_tree(parser);
354                        freeTree = 0;
355                        freeRoot = 1;
356                        root = scew_tree_root(tree);
357
358                        // free the current RpLibrary's data
359                        // we do the free so far down so we can see if
360                        // parsing the other object's xml fails.
361                        // if the parsing fails, we can still return this
362                        // object to its previous state.
363                        if (tmp_tree && tmp_freeTree) {
364                            scew_tree_free(tmp_tree);
365                            tmp_tree = NULL;
366                        }
367                        if (tmp_parser) {
368                            scew_parser_free(tmp_parser);
369                            tmp_parser = NULL;
370                        }
371                        if (tmp_root && tmp_freeRoot) {
372                            tmp_root = NULL;
373                        }
374                    }
375
376                } // end if (buffer.length() != 0) {
377            } // end if (this != &other)
378
379            return *this;
380        } // end operator=
381
382
383        // default destructor
384        virtual ~RpLibrary ()
385        {
386            // clean up dynamic memory
387
388            if (tree && freeTree) {
389                scew_tree_free(tree);
390                tree = NULL;
391            }
392            if (parser) {
393                scew_parser_free(parser);
394                parser = NULL;
395            }
396            if (root && freeRoot) {
397                scew_element_free(root);
398                root = NULL;
399            }
400        }
401
402    private:
403
404        scew_parser* parser;
405        scew_tree* tree;
406        scew_element* root;
407
408        // flag to tell if we are responsible for calling scew_tree_free
409        // on the tree structure. if we get our tree by using the
410        // scew_tree_create
411        // fxn, we need to free it. if we get our tree using the
412        // scew_parser_tree
413        // fxn, then it will be free'd when the parser is free'd.
414        int freeTree;
415
416        // some object (like those returned from children() and element )
417        // are previously allocated scew objects with an artificial RpLibrary
418        // wrapper. these objects never really allocated any memory, they
419        // just point to memory. they should not free any memory when they
420        // are deleted (because none was allocated when they were created).
421        // when the larger Rappture Library is deleted, they will have
422        // pointers to bad/deleted memory...libscew has the same problem in
423        // their implementation of a similar children() fxn.
424        //
425        // this flag tells the destructor that when above said object is
426        // deleted, dont act on the root pointer
427        int freeRoot;
428
429
430        RpLibrary ( scew_element* node, scew_tree* tree)
431            :   parser      (NULL),
432                tree        (tree),
433                root        (node)
434
435        {
436            freeTree = 0;
437            freeRoot = 0;
438        }
439
440
441        std::string _get_attribute(scew_element* element, std::string attributeName);
442        int _path2list (std::string& path, std::string** list, int listLen);
443        std::string _node2name (scew_element* node);
444        std::string _node2comp (scew_element* node);
445        std::string _node2path (scew_element* node);
446
447        int _splitPath (std::string& path,
448                        std::string& tagName,
449                        int* idx,
450                        std::string& id );
451        scew_element* _find (std::string path, int create);
452        void print_indent (unsigned int indent, std::stringstream& outString);
453        void print_attributes (scew_element* element, std::stringstream& outString);
454        void print_element( scew_element* element,
455                            unsigned int indent,
456                            std::stringstream& outString    );
457
458        static int _translateIn (std::string& value, std::string& translated);
459        static int _translateOut (char* inStr);
460
461};
462
463/*--------------------------------------------------------------------------*/
464/*--------------------------------------------------------------------------*/
465
466#endif // ifdef __cplusplus
467
468#endif // ifndef _RpLIBRARY_H
Note: See TracBrowser for help on using the repository browser.