ClearSilverNode.cc

00001 /*
00002  * $Id: ClearSilverNode.cc,v 1.13 2006/04/03 15:09:21 brook Exp $
00003  */
00004 
00005 /*
00006  * ClearSilver++ Software License.
00007  *
00008  * Copyright (c) 2005,2006 Brook Milligan <brook@nmsu.edu>
00009  * All rights reserved.
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  * 
00015  * 1. Redistributions of source code must retain the above copyright
00016  *    notice, this list of conditions and the following disclaimer.
00017  * 2. Redistributions in binary form must reproduce the above
00018  *    copyright notice, this list of conditions and the following
00019  *    disclaimer in the documentation and/or other materials provided
00020  *    with the distribution.
00021  * 3. The name of the author may not be used to endorse or promote
00022  *    products derived from this software without specific prior
00023  *    written permission.
00024  * 
00025  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00026  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00027  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00028  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00029  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00030  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00031  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00033  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036  */
00037 
00038 #include "ClearSilverNode.h"
00039 
00040 #include <algorithm>
00041 #include <stdexcept>
00042 #include <string.h>
00043 #include <syslog.h>
00044 #include <boost/lexical_cast.hpp>
00045 #include <ClearSilver/util/neo_misc.h> // must precede neo_hdf.h
00046 #include <ClearSilver/util/neo_hdf.h>
00047 #include "ClearSilverError.h"
00048 #include "ClearSilverException.h"
00049 #include "ClearSilverNodeComparator.h"
00050 #include "ConstHDF.h"
00051 #include "RootNode.h"
00052 
00053 using namespace std;
00054 
00055                                 // node sorting function
00056 static int sort_nodes (const void*, const void*);
00057                                 // comparator used by node sorting function
00058 ClearSilver::ClearSilverNodeComparator::Ptr comparator;
00059 
00060 
00061                                 // constructors
00062 ClearSilver::ClearSilverNode::ClearSilverNode ()
00063   : node_(0) {}
00064 
00065 ClearSilver::ClearSilverNode::ClearSilverNode (HDF* node)
00066   : node_(node) {}
00067 
00068 ClearSilver::ClearSilverNode::ClearSilverNode (const ClearSilverNode& n)
00069   : node_(n.node_) {}
00070 
00071 ClearSilver::ClearSilverNode::~ClearSilverNode () throw()
00072 {}
00073 
00074                                 // assignment
00075 ClearSilver::ClearSilverNode&
00076 ClearSilver::ClearSilverNode::operator = (const ClearSilverNode& n)
00077 {
00078   ClearSilverNode n0 (n);
00079   swap (n0);
00080   return *this;
00081 }
00082 
00083 ClearSilver::ClearSilverNode&
00084 ClearSilver::ClearSilverNode::operator = (const char* value)
00085 {
00086   return operator = (std::string(value));
00087 }
00088 
00089                                 // Note: the ClearSilver C API
00090                                 // provides no function analogous to
00091                                 // assignment.  Therefore, this
00092                                 // function depends on the internals
00093                                 // of the _hdf structure.
00094 ClearSilver::ClearSilverNode&
00095 ClearSilver::ClearSilverNode::operator = (const string& value)
00096 {
00097   if (!node_)
00098     {
00099       string message;
00100       message += "ClearSilverNode::operator = (const std::string&): ";
00101       message += "cannot assign to null node";
00102       throw logic_error (message);
00103     }
00104   if (debug())
00105     {
00106       string message;
00107       message
00108         += "ClearSilver::ClearSilverNode::operator = (const string&): ";
00109       if (node_->name)
00110         message += string("name=") + node_->name + ", ";
00111       message += "value=" + value;
00112       syslog (LOG_DEBUG, "%s", message.c_str());
00113     }
00114   if (node_->value)
00115     free (node_->value);
00116   node_->value = strdup(value.c_str());
00117   return *this;
00118 }
00119 
00120 ClearSilver::ClearSilverNode&
00121 ClearSilver::ClearSilverNode::operator = (int value)
00122 {
00123   if (debug())
00124     {
00125       string message;
00126       message += "ClearSilver::ClearSilverNode::operator = (int): ";
00127       if (node_ && node_->name)
00128         message += string("name=") + node_->name + ", ";
00129       message += "value=" + value;
00130       syslog (LOG_DEBUG, "%s", message.c_str());
00131     }
00132   return operator = (boost::lexical_cast<string>(value));
00133 }
00134 
00135 ClearSilver::ClearSilverNode&
00136 ClearSilver::ClearSilverNode::operator = (bool value)
00137 {
00138   return operator = (std::string(value?True():False()));
00139 }
00140 
00141 
00142                                 // STL inspectors
00143                                 // is this node empty?
00144 bool
00145 ClearSilver::ClearSilverNode::empty () const
00146 {
00147   return node_ == 0;
00148 }
00149 
00150                                 // conversions
00151                                 // is this node valid?
00152 ClearSilver::ClearSilverNode::operator bool () const
00153 {
00154   return !empty();
00155 }
00156 
00157                                 // node accessors
00158 string
00159 ClearSilver::ClearSilverNode::name () const
00160 {
00161   if (debug())
00162     syslog (LOG_DEBUG, "%s", "ClearSilver::ClearSilverNode::name () const");
00163   if (!node_)
00164     {
00165       string message;
00166       message += "ClearSilverNode::name () const: ";
00167       message += "null node";
00168       throw logic_error (message);
00169     }
00170   return string(hdf_obj_name(node_));
00171 }
00172 
00173 string
00174 ClearSilver::ClearSilverNode::value () const
00175 {
00176   if (!node_)
00177     {
00178       string message;
00179       message += "ClearSilverNode::value () const: ";
00180       message += "null node";
00181       throw logic_error (message);
00182     }
00183   if (debug())
00184     {
00185       string message;
00186       message += string("ClearSilver::ClearSilverNode::value () const: ");
00187       if (node_->name)
00188         message += string("name=") + node_->name + ", ";
00189       if (node_->value)
00190         message += string("value=") + node_->value;
00191       syslog (LOG_DEBUG, "%s", message.c_str());
00192     }
00193   char * value = hdf_obj_value(node_);
00194   return value? string (value) : string();
00195 }
00196 
00197 
00198                                 //  tree traversers
00199                                 // access the node structure directly.
00200 ClearSilver::ClearSilverNode::HDF*
00201 ClearSilver::ClearSilverNode::get () const
00202 {
00203   return node_;
00204 }
00205 
00206 ClearSilver::ClearSilverNode
00207 ClearSilver::ClearSilverNode::top () const
00208 {
00209   if (debug())
00210     syslog (LOG_DEBUG, "%s", "ClearSilverNode::top () const");
00211   return ClearSilverNode (hdf_obj_top (node_));
00212 }
00213 
00214 ClearSilver::ClearSilverNode
00215 ClearSilver::ClearSilverNode::next () const
00216 {
00217   if (debug())
00218     syslog (LOG_DEBUG, "%s", "ClearSilverNode::next () const");
00219   return ClearSilverNode (hdf_obj_next (node_));
00220 }
00221 
00222 ClearSilver::ClearSilverNode
00223 ClearSilver::ClearSilverNode::child () const
00224 {
00225   if (debug())
00226     syslog (LOG_DEBUG, "%s", "ClearSilverNode::child () const");
00227   return ClearSilverNode (hdf_obj_child (node_));
00228 }
00229 
00230 ClearSilver::ClearSilverNode::HDF_ATTR*
00231 ClearSilver::ClearSilverNode::attr () const
00232 {
00233   if (debug())
00234     syslog (LOG_DEBUG, "%s", "ClearSilverNode::attr () const");
00235   return node_->attr;
00236 }
00237 
00238                                 // HDF dataset operations
00239 string
00240 ClearSilver::ClearSilverNode::get_value
00241 (const string& key, const string& default_value) const
00242 {
00243   if (key.empty())
00244     {
00245       string message;
00246       message += "ClearSilver::ClearSilverNode::get_value ";
00247       message += "(const string&, const string&) const: ";
00248       message += "empty key";
00249       throw invalid_argument (message);
00250     }
00251   if (debug())
00252     {
00253       string message;
00254       message += "ClearSilver::ClearSilverNode::get_value";
00255       message += "(const string& key, const string& default_value) const: ";
00256       message += "key=" + key + ", ";
00257       message += "default_value=" + default_value;
00258       syslog (LOG_DEBUG, "%s", message.c_str());
00259     }
00260   return string(hdf_get_value (node_, key.c_str(), default_value.c_str()));
00261 }
00262 
00263 void
00264 ClearSilver::ClearSilverNode::set_value
00265 (const std::string& key, const string& value)
00266 {
00267   if (key.empty())
00268     {
00269       string message;
00270       message += "ClearSilver::ClearSilverNode::set_value ";
00271       message += "(const string&, int): ";
00272       message += "empty key";
00273       throw invalid_argument (message);
00274     }
00275   if (debug())
00276     {
00277       string message;
00278       message += string("ClearSilverNode::set_value ")
00279         + "(const string& key, const string& value): ";
00280       message += "key=" + key + ", ";
00281       message += "value=" + value;
00282       syslog (LOG_DEBUG, "%s", message.c_str());
00283     }
00284   ClearSilverError error (hdf_set_value(node_,key.c_str(),value.c_str()));
00285   if (error)
00286     {
00287       string message;
00288       message += "ClearSilver::ClearSilverNode::set_value ";
00289       message += "(const std::string&, const std::string&):";
00290       ClearSilverException e (message);
00291       e += error;
00292       throw e;
00293     }
00294 }
00295 
00296 void
00297 ClearSilver::ClearSilverNode::set_value
00298 (const std::string& key, int value)
00299 {
00300   if (key.empty())
00301     {
00302       string message;
00303       message += "ClearSilver::ClearSilverNode::set_value ";
00304       message += "(const string&, int): ";
00305       message += "empty key";
00306       throw invalid_argument (message);
00307     }
00308   if (debug())
00309     {
00310       string message;
00311       message += string("ClearSilverNode::set_value ")
00312         + "(const string& key, int value): ";
00313       message += "key=" + key + ", ";
00314       message += "value=" + boost::lexical_cast<string>(value);
00315       syslog (LOG_DEBUG, "%s", message.c_str());
00316     }
00317   ClearSilverError error (hdf_set_int_value (node_, key.c_str(), value));
00318   if (error)
00319     {
00320       string message;
00321       message += "ClearSilver::ClearSilverNode::set_value ";
00322       message += "(const string&, int):";
00323       ClearSilverException e (message);
00324       e += error;
00325       throw e;
00326     }
00327 }
00328 
00329 void
00330 ClearSilver::ClearSilverNode::set_value
00331 (const std::string& key, unsigned int value)
00332 {
00333   if (key.empty())
00334     {
00335       string message;
00336       message += "ClearSilver::ClearSilverNode::set_value ";
00337       message += "(const string&, unsigned int): ";
00338       message += "empty key";
00339       throw invalid_argument (message);
00340     }
00341   if (debug())
00342     {
00343       string message;
00344       message += string("ClearSilverNode::set_value ")
00345         + "(const string& key, unsigned int value): ";
00346       message += "key=" + key + ", ";
00347       message += "value=" + boost::lexical_cast<string>(value);
00348       syslog (LOG_DEBUG, "%s", message.c_str());
00349     }
00350   ClearSilverError error (hdf_set_int_value (node_, key.c_str(),
00351                                              static_cast<int>(value)));
00352   if (error)
00353     {
00354       string message;
00355       message += "ClearSilver::ClearSilverNode::set_value ";
00356       message += "(const string&, unsigned int):";
00357       ClearSilverException e (message);
00358       e += error;
00359       throw e;
00360     }
00361 }
00362 
00363 void
00364 ClearSilver::ClearSilverNode::set_value
00365 (const std::string& key, bool value)
00366 {
00367   if (debug())
00368     {
00369       string message;
00370       message += string("ClearSilverNode::set_value ")
00371         + "(const string& key, bool value): ";
00372       message += "key=" + key + ", ";
00373       message += string("value=") + (value?"true":"false");
00374       syslog (LOG_DEBUG, "%s", message.c_str());
00375     }
00376   set_value (key, string(value? True() : False()));
00377 }
00378 
00379 ClearSilver::ClearSilverNode
00380 ClearSilver::ClearSilverNode::get_node
00381 (const string& key)
00382 {
00383   if (key.empty())
00384     {
00385       string message;
00386       message += "ClearSilver::ClearSilverNode::get_node ";
00387       message += "(const string&) const: ";
00388       message += "empty key";
00389       throw invalid_argument (message);
00390     }
00391   if (debug())
00392     {
00393       string message;
00394       message += string("ClearSilverNode::get_node (const string& key): ");
00395       message += "key=" + key;
00396       syslog (LOG_DEBUG, "%s", message.c_str());
00397     }
00398   HDF* node;
00399   ClearSilverError error (hdf_get_node (node_, key.c_str(), &node));
00400   if (error)
00401     {
00402       string message;
00403       message += "ClearSilver::ClearSilverNode::get_node ";
00404       message += "(const string& key): ";
00405       message += "key=" + key;
00406       ClearSilverException e (message);
00407       e += error;
00408       throw e;
00409     }
00410   if (!node)
00411     {
00412       string message;
00413       message += "ClearSilver::ClearSilverNode::get_node ";
00414       message += "(const string&) const: ";
00415       message += "impossible error: ";
00416       message += "cannot create intermediate nodes";
00417       throw logic_error (message);
00418     }
00419   return ClearSilverNode(node);
00420 }
00421 
00422 ClearSilver::ClearSilverNode
00423 ClearSilver::ClearSilverNode::get_obj
00424 (const string& key) const
00425 {
00426   if (key.empty())
00427     {
00428       string message;
00429       message += "ClearSilver::ClearSilverNode::get_obj ";
00430       message += "(const string&) const: ";
00431       message += "empty key";
00432       throw invalid_argument (message);
00433     }
00434   if (debug())
00435     {
00436       string message;
00437       message += string("ClearSilverNode::get_obj (const string& key): ");
00438       message += "key=" + key;
00439       syslog (LOG_DEBUG, "%s", message.c_str());
00440     }
00441   return ClearSilverNode (hdf_get_obj (node_, key.c_str()));
00442 }
00443 
00444 ClearSilver::ClearSilverNode
00445 ClearSilver::ClearSilverNode::get_child
00446 (const string& key) const
00447 {
00448   if (key.empty())
00449     {
00450       string message;
00451       message += "ClearSilver::ClearSilverNode::get_child ";
00452       message += "(const string&) const: ";
00453       message += "empty key";
00454       throw invalid_argument (message);
00455     }
00456   if (debug())
00457     {
00458       string message;
00459       message += string("ClearSilverNode::get_child(const string& key): ");
00460       message += "key=" + key;
00461       syslog (LOG_DEBUG, "%s", message.c_str());
00462     }
00463   return ClearSilverNode (hdf_get_child (node_, key.c_str()));
00464 }
00465 
00466 void
00467 ClearSilver::ClearSilverNode::remove_tree ()
00468 {
00469   hdf_destroy (&node_);
00470   if (node_ != 0)
00471     {
00472       string message;
00473       message += "ClearSilver::ClearSilverNode::remove_tree(): ";
00474       message += "node_ not empty";
00475       throw logic_error(message);
00476     }
00477 }
00478 
00479 void
00480 ClearSilver::ClearSilverNode::remove_tree
00481 (const std::string& key)
00482 {
00483   ClearSilverError error (hdf_remove_tree (node_, key.c_str()));
00484   if (error)
00485     {
00486       string message;
00487       message += "ClearSilver::ClearSilverNode::remove_tree ";
00488       message += "(const string& key): ";
00489       message += "key=" + key;
00490       ClearSilverException e (message);
00491       e += error;
00492       throw e;
00493     }
00494 }
00495 
00496 void
00497 ClearSilver::ClearSilverNode::read_file
00498 (const std::string& path)
00499 {
00500   if (path.empty())
00501     {
00502       string message;
00503       message += "ClearSilver::ClearSilverNode::read_file ";
00504       message += "(const string&): ";
00505       message += "empty path";
00506       throw invalid_argument (message);
00507     }
00508   ClearSilverError error (hdf_read_file (node_, path.c_str()));
00509   if (error)
00510     {
00511       string message;
00512       message += "ClearSilver::ClearSilverNode::read_file ";
00513       message += "(const string& path): ";
00514       message += "path=" + path;
00515       ClearSilverException e (message);
00516       e += error;
00517       throw e;
00518     }
00519 }
00520 
00521 void
00522 ClearSilver::ClearSilverNode::write_file
00523 (const std::string& path) const
00524 {
00525   if (path.empty())
00526     {
00527       string message;
00528       message += "ClearSilver::ClearSilverNode::write_file ";
00529       message += "(const string&): ";
00530       message += "empty path";
00531       throw invalid_argument (message);
00532     }
00533   ClearSilverError error (hdf_write_file_atomic (node_, path.c_str()));
00534   if (error)
00535     {
00536       string message;
00537       message += "ClearSilver::ClearSilverNode::write_file ";
00538       message += "(const string& path): ";
00539       message += "path=" + path;
00540       ClearSilverException e (message);
00541       e += error;
00542       throw e;
00543     }
00544 }
00545 
00546 void
00547 ClearSilver::ClearSilverNode::dump
00548 (const std::string& prefix) const
00549 {
00550   ClearSilverError error (hdf_dump (node_, prefix.c_str()));
00551   if (error)
00552     {
00553       string message;
00554       message += "ClearSilver::ClearSilverNode::dump ";
00555       message += "(const string& prefix): ";
00556       message += "prefix=" + prefix;
00557       ClearSilverException e (message);
00558       e += error;
00559       throw e;
00560     }
00561 }
00562 
00563 void
00564 ClearSilver::ClearSilverNode::copy (const string& key,
00565                                            const ClearSilverNode& src)
00566 {
00567   ClearSilverError error (hdf_copy (node_, key.c_str(), src.node_));
00568   if (error)
00569     {
00570       string message;
00571       message += "ClearSilver::ClearSilverNode::copy ";
00572       message += "(const string&, const ClearSilverNode&): ";
00573       ClearSilverException e (message);
00574       e += error;
00575       throw e;
00576     }
00577 }
00578 
00579                                 // debug flag
00580 bool&
00581 ClearSilver::ClearSilverNode::debug ()
00582 {
00583   static bool debug_ = false;
00584   return debug_;
00585 }
00586 
00587                                 // boolean constants
00588 std::string
00589 ClearSilver::ClearSilverNode::Boolean (bool b)
00590 {
00591   return b? True() : False();
00592 }
00593 
00594 std::string
00595 ClearSilver::ClearSilverNode::True ()
00596 {
00597   return std::string("1");
00598 }
00599 
00600 std::string
00601 ClearSilver::ClearSilverNode::False ()
00602 {
00603   return std::string("0");
00604 }
00605 
00606                                 // swap contents with another object.
00607 void
00608 ClearSilver::ClearSilverNode::swap (ClearSilverNode& n) throw()
00609 {
00610   std::swap (node_, n.node_);
00611 }
00612 
00613 
00614                                 // sort the children
00615 void
00616 ClearSilver::ClearSilverNode::sort (ClearSilverNodeComparator::Ptr c)
00617 {
00618   comparator = c;
00619   ClearSilverError error (hdf_sort_obj (node_, sort_nodes));
00620   if (error)
00621     {
00622       string message;
00623       message += "ClearSilver::ClearSilverNode::sort ";
00624       message += "(const ClearSilverNodeComparator::Ptr): ";
00625       ClearSilverException e (message);
00626       e += error;
00627       throw e;
00628     }
00629 }
00630 
00631 int
00632 sort_nodes (const void* lhs, const void* rhs)
00633 {
00634   ClearSilver::ConstHDF n1
00635     (ClearSilver::RootNode(*(ClearSilver::ClearSilverNode::HDF**) lhs, false));
00636   ClearSilver::ConstHDF n2
00637     (ClearSilver::RootNode(*(ClearSilver::ClearSilverNode::HDF**) rhs, false));
00638   return (*comparator) (n1, n2);
00639 }
00640 
00641 namespace ClearSilver
00642 {
00643                                 // logical comparison operators
00644   bool
00645   operator == (const ClearSilverNode& n1, const ClearSilverNode& n2)
00646   {
00647     return n1.node_ == n2.node_;
00648   }
00649 };                              // namespace ClearSilver

Generated on Tue May 16 14:50:52 2006 for ClearSilver C++ Library by  doxygen 1.4.5