HDFAttributes.cc

00001 /*
00002  * $Id: HDFAttributes.cc,v 1.8 2006/03/29 14:21:35 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 "HDFAttributes.h"
00039 #include <stdexcept>
00040 #include <string>
00041 #include <string.h>
00042 #include <ClearSilver/util/neo_hdf.h>
00043 #include "ClearSilverError.h"
00044 #include "ClearSilverException.h"
00045 
00046 #if HAVE_BROKEN_HDF_SET_ATTR
00047 static NEOERR* XXX_hdf_set_attr (HDF *hdf, const char *name,
00048                                  const char *key, const char *value);
00049 #endif // HAVE_BROKEN_HDF_SET_ATTR
00050 
00051 namespace ClearSilver
00052 {
00053 
00054   // constructors
00055   HDFAttributes::HDFAttributes ()
00056     : path_(), head_(0) {}
00057 
00058   HDFAttributes::HDFAttributes (const Nodes& path, _attr* head)
00059     : path_(path), head_(head) {}
00060 
00061   HDFAttributes::HDFAttributes (const HDFAttributes& a)
00062     : path_(a.path_), head_(a.head_) {}
00063 
00064   HDFAttributes::~HDFAttributes () throw() {}
00065 
00066   // assignment
00067   HDFAttributes&
00068   HDFAttributes::operator = (const HDFAttributes& a)
00069   {
00070     HDFAttributes a_(a);
00071     swap (a_);
00072     return *this;
00073   }
00074 
00075   // swap contents
00076   void
00077   HDFAttributes::swap (HDFAttributes& a) throw()
00078   {
00079     std::swap (path_, a.path_);
00080     std::swap (head_, a.head_);
00081   }
00082 
00083   HDFAttributes::size_type
00084   HDFAttributes::size () const
00085   {
00086     HDF_ATTR* node = head_;
00087     size_type n = 0;
00088     while (node != 0)
00089       {
00090         ++n;
00091         node = node->next;
00092       }
00093     return n;
00094   }
00095 
00096   // is the container empty?
00097   bool
00098   HDFAttributes::empty () const
00099   {
00100     return head_ == 0;
00101   }
00102 
00103   HDFAttributes::size_type
00104   HDFAttributes::count (const key_type& key)
00105   {
00106     HDF_ATTR* node = head_;
00107     size_type n = 0;
00108     while (node != 0)
00109       {
00110         if (strcmp (key, node->key) == 0)
00111           ++n;
00112         node = node->next;
00113       }
00114     return n;
00115   }
00116 
00117   HDFAttributes::iterator
00118   HDFAttributes::find (const key_type& key)
00119   {
00120     HDF_ATTR* node = head_;
00121     while (node != 0)
00122       {
00123         if (strcmp (key, node->key) == 0)
00124           return iterator (node);
00125         node = node->next;
00126       }
00127     return iterator();
00128   }
00129 
00130   HDFAttributes::const_iterator
00131   HDFAttributes::find (const key_type& key) const
00132   {
00133     HDF_ATTR* node = head_;
00134     while (node != 0)
00135       {
00136         if (strcmp (key, node->key) == 0)
00137           return const_iterator (node);
00138         node = node->next;
00139       }
00140     return const_iterator();
00141   }
00142 
00143   HDFAttributes::mapped_type
00144   HDFAttributes::operator [] (const key_type& key)
00145   {
00146     iterator i = find (key);
00147     if (i)
00148       return i.value_->second;
00149 
00150     ClearSilverError error (hdf_set_attr (path_.top().top().get(),
00151                                           path_.path().c_str(), key, ""));
00152     if (error)
00153       {
00154         std::string message;
00155         message += "ClearSilver::HDFAttributes::operator[](const key_type&): ";
00156         ClearSilverException e (message);
00157         e += error;
00158         throw e;
00159       }
00160     i = find (key);
00161     return i.value_->second;
00162   }
00163 
00164   HDFAttributes::iterator
00165   HDFAttributes::begin ()
00166   {
00167     return iterator (head_);
00168   }
00169 
00170   HDFAttributes::iterator
00171   HDFAttributes::end ()
00172   {
00173     return iterator();
00174   }
00175 
00176   HDFAttributes::const_iterator
00177   HDFAttributes::begin () const
00178   {
00179     return const_iterator (head_);
00180   }
00181 
00182   HDFAttributes::const_iterator
00183   HDFAttributes::end () const
00184   {
00185     return const_iterator();
00186   }
00187 
00188   std::pair<HDFAttributes::iterator,bool>
00189   HDFAttributes::insert (const value_type& value)
00190   {
00191     iterator i = find (value.first);
00192     if (i)
00193       return std::pair<HDFAttributes::iterator,bool>(i, false);
00194 #if HAVE_BROKEN_HDF_SET_ATTR
00195     ClearSilverError error (XXX_hdf_set_attr (path_.top().get(), 0,
00196                                               value.first, value.second));
00197 #else // HAVE_BROKEN_HDF_SET_ATTR
00198     ClearSilverError error (hdf_set_attr (path_.top().top().get(),
00199                                           path_.path().c_str(),
00200                                           value.first, value.second));
00201 #endif // HAVE_BROKEN_HDF_SET_ATTR
00202     if (error)
00203       {
00204         std::string message;
00205         message += "ClearSilver::HDFAttributes::insert(const value_type&): ";
00206         ClearSilverException e (message);
00207         e += error;
00208         throw e;
00209       }
00210     i = find (value.first);
00211     return std::pair<HDFAttributes::iterator,bool>(i, true);
00212   }
00213 
00214   // XXX - ignore hint
00215   HDFAttributes::iterator
00216   HDFAttributes::insert (iterator, const value_type& value)
00217   {
00218     return insert (value).first;
00219   }
00220 
00221   HDFAttributes::size_type
00222   HDFAttributes::erase (const key_type& key) throw()
00223   {
00224     iterator i = find (key);
00225     if (i)
00226       {
00227         erase (i);
00228         return 1;
00229       }
00230     else
00231       return 0;
00232   }
00233 
00234   void
00235   HDFAttributes::erase (iterator i)
00236   {
00237     if (i == begin())           // must advance head_
00238       head_ = head_->next;
00239 
00240 #if HAVE_BROKEN_HDF_SET_ATTR
00241     ClearSilverError error (XXX_hdf_set_attr (path_.top().get(), 0,
00242                                               i.value_->first, 0));
00243 #else // HAVE_BROKEN_HDF_SET_ATTR
00244     ClearSilverError error (hdf_set_attr (path_.top().top().get(),
00245                                           path_.path().c_str(),
00246                                           i.value_->first, 0));
00247 #endif // HAVE_BROKEN_HDF_SET_ATTR
00248     if (error)
00249       {
00250         std::string message;
00251         message += "ClearSilver::HDFAttributes::erase(iterator): ";
00252         ClearSilverException e (message);
00253         e += error;
00254         throw e;
00255       }
00256   }
00257 
00258   void
00259   HDFAttributes::erase (iterator begin, iterator end)
00260   {
00261     while (begin != end)
00262       {
00263         iterator i = begin++;
00264         erase (i);
00265       }
00266   }
00267 
00268   void
00269   HDFAttributes::clear () throw()
00270   {
00271     erase (begin(), end());
00272   }
00273 
00274   bool
00275   operator == (const HDFAttributes& a1, const HDFAttributes& a2)
00276   {
00277     return a1.head_ == a2.head_;
00278   }
00279 
00280   bool&
00281   HDFAttributes::debug ()
00282   {
00283     static bool debug_ = false;
00284     return debug_;
00285   }
00286 
00287 
00288   HDFAttributes::mapped_type::mapped_type ()
00289     : value_(0), valuep_(&value_) {}
00290   HDFAttributes::mapped_type::mapped_type (const char* v)
00291     : value_(strdup(v)), valuep_(&value_) {}
00292   HDFAttributes::mapped_type::mapped_type (std::string v)
00293     : value_(strdup(v.c_str())), valuep_(&value_) {}
00294   HDFAttributes::mapped_type::mapped_type (char** v)
00295     : value_(0), valuep_(v)
00296     {
00297       if (!valuep_ || !*valuep_)
00298         {
00299           std::string message;
00300           message += "ClearSilver::HDFAttributes::mapped_type::mapped_type ";
00301           message += "(char**): ";
00302           message += "nil pointer argument";
00303           throw std::invalid_argument (message);
00304         }
00305     }
00306   HDFAttributes::mapped_type::mapped_type (const mapped_type& v)
00307     : value_(0), valuep_(&value_)
00308   {
00309     if (*v.valuep_ == v.value_) // v owns its data
00310       value_ = strdup(v.value_);
00311     else
00312       valuep_ = v.valuep_;
00313   }
00314 HDFAttributes::mapped_type::~mapped_type () throw()
00315     {
00316       if (value_)
00317         free(value_);
00318     }
00319   HDFAttributes::mapped_type&
00320   HDFAttributes::mapped_type::operator = (const mapped_type& v)
00321   {
00322     mapped_type v_(v);
00323     swap(v_);
00324     return *this;
00325   }
00326   HDFAttributes::mapped_type&
00327   HDFAttributes::mapped_type::operator = (const char* v)
00328   {
00329     if (!v)
00330       {
00331         std::string message;
00332         message += "ClearSilver::HDFAttributes::mapped_type::operator = ";
00333         message += "(const char*): ";
00334         message += "nil pointer argument";
00335         throw std::invalid_argument (message);
00336       }
00337     
00338     char* v_ = strdup(v);
00339     free (*valuep_);
00340     *valuep_ = v_;
00341     return *this;
00342   }
00343   void
00344   HDFAttributes::mapped_type::swap (mapped_type& v) throw()
00345   {
00346     std::swap (value_, v.value_);
00347     std::swap (valuep_, v.valuep_);
00348   }
00349   HDFAttributes::mapped_type::operator char* ()
00350   {
00351     return *valuep_;
00352   }
00353   HDFAttributes::mapped_type::operator const char* () const
00354   { return *valuep_; }
00355 
00356 
00357   HDFAttributes::iterator::iterator () : node_(0), value_() {}
00358 
00359   HDFAttributes::iterator::iterator (_attr* node)
00360     : node_(node), value_()
00361   {
00362     if (node_)
00363       value_ =
00364         boost::shared_ptr<value_type>
00365         (new value_type(node_->key, &node_->value));
00366   }
00367 
00368   HDFAttributes::iterator::iterator (const iterator& i)
00369     : node_(i.node_), value_(i.value_) {}
00370 
00371   HDFAttributes::iterator::~iterator () throw() {}
00372 
00373   HDFAttributes::iterator::iterator&
00374   HDFAttributes::iterator::operator = (const iterator& i)
00375   {
00376     HDFAttributes::iterator i_(i);
00377     swap(i_);
00378     return *this;
00379   }
00380 
00381   void
00382   HDFAttributes::iterator::swap (iterator& i) throw ()
00383   {
00384     std::swap (node_, i.node_);
00385     std::swap (value_, i.value_);
00386   }
00387 
00388   HDFAttributes::iterator::operator bool () const
00389   {
00390     return node_ != 0;
00391   }
00392 
00393   HDFAttributes::value_type
00394   HDFAttributes::iterator::operator * ()
00395   {
00396     return *value_;
00397   }
00398 
00399   HDFAttributes::value_type*
00400   HDFAttributes::iterator::operator -> ()
00401   {
00402     return value_.get();
00403   }
00404 
00405   HDFAttributes::iterator&
00406   HDFAttributes::iterator:: operator ++ ()
00407   {
00408     if (node_)
00409       {
00410         if (node_->next)
00411           {
00412             HDFAttributes::iterator i (node_->next);
00413             swap (i);
00414           }
00415         else
00416           { 
00417             HDFAttributes::iterator i;
00418             swap (i);
00419           }
00420       }
00421     return *this;
00422   }
00423 
00424   HDFAttributes::iterator
00425   HDFAttributes::iterator::operator ++ (int)
00426   {
00427     HDFAttributes::iterator i (*this);
00428     operator ++();
00429     return i;
00430   }
00431 
00432   bool
00433   operator == (const HDFAttributes::iterator& i1,
00434                const HDFAttributes::iterator& i2)
00435   {
00436     return i1.node_ == i2.node_;
00437   }
00438 
00439 
00440   HDFAttributes::const_iterator::const_iterator () : node_(0), value_() {}
00441 
00442   HDFAttributes::const_iterator::const_iterator (_attr* node)
00443     : node_(node), value_()
00444   {
00445     if (node_)
00446       value_ =
00447         boost::shared_ptr<value_type>
00448         (new value_type(node_->key, &node_->value));
00449   }
00450 
00451   HDFAttributes::const_iterator::const_iterator (const const_iterator& i)
00452     : node_(i.node_), value_(i.value_) {}
00453 
00454   HDFAttributes::const_iterator::~const_iterator () throw() {}
00455 
00456   HDFAttributes::const_iterator::const_iterator&
00457   HDFAttributes::const_iterator::operator = (const const_iterator& i)
00458   {
00459     HDFAttributes::const_iterator i_(i);
00460     swap(i_);
00461     return *this;
00462   }
00463 
00464   void
00465   HDFAttributes::const_iterator::swap (const_iterator& i) throw ()
00466   {
00467     std::swap (node_, i.node_);
00468     std::swap (value_, i.value_);
00469   }
00470 
00471   HDFAttributes::const_iterator::operator bool () const
00472   {
00473     return node_ != 0;
00474   }
00475 
00476   HDFAttributes::value_type
00477   HDFAttributes::const_iterator::operator * ()
00478   {
00479     return *value_;
00480   }
00481 
00482   HDFAttributes::value_type*
00483   HDFAttributes::const_iterator::operator -> ()
00484   {
00485     return value_.get();
00486   }
00487 
00488   HDFAttributes::const_iterator&
00489   HDFAttributes::const_iterator:: operator ++ ()
00490   {
00491     if (node_)
00492       {
00493         if (node_->next)
00494           {
00495             HDFAttributes::const_iterator i (node_->next);
00496             swap (i);
00497           }
00498         else
00499           { 
00500             HDFAttributes::const_iterator i;
00501             swap (i);
00502           }
00503       }
00504     return *this;
00505   }
00506 
00507   HDFAttributes::const_iterator
00508   HDFAttributes::const_iterator::operator ++ (int)
00509   {
00510     HDFAttributes::const_iterator i (*this);
00511     operator ++();
00512     return i;
00513   }
00514 
00515   bool
00516   operator == (const HDFAttributes::const_iterator& i1,
00517                const HDFAttributes::const_iterator& i2)
00518   {
00519     return i1.node_ == i2.node_;
00520   }
00521 
00522 };                              // namespace ClearSilver
00523 
00524 #if HAVE_BROKEN_HDF_SET_ATTR
00525 
00526 /*
00527  * The following function is to replace the analogous one from the
00528  * ClearSilver C library which is broken, at least in v0.9.14 and
00529  * v0.10.3.  In particular, the head of the list is advanced
00530  * incorrectly by the library version (see below).  Because this
00531  * version is only for use by the erase() method above and the actual
00532  * node is known, the argument list is slightly different from the
00533  * original.  Specifically, the correct node is known by the caller
00534  * and need not be found by walking the list.  The correct node is
00535  * therefore passed as the hdf argument and the name argument is
00536  * ignored.  Except for the lines marked with XXX below, this function
00537  * is a verbatim copy from the C library v0.9.14.  As soon as this bug
00538  * is fixed, this code will be removed from here.
00539  */
00540 
00541 NEOERR* XXX_hdf_set_attr (HDF *hdf, const char *name, const char *key, const char *value)
00542 {
00543   HDF *obj = hdf;               // XXX - don't walk the tree for this version
00544   HDF_ATTR *attr, *last;
00545 
00546   // _walk_hdf(hdf, name, &obj);        // XXX - see above
00547   if (obj == NULL) 
00548     return nerr_raise(NERR_ASSERT, "Unable to set attribute on none existant node");
00549 
00550   if (obj->attr != NULL)
00551   {
00552     attr = obj->attr;
00553     last = attr;
00554     while (attr != NULL)
00555     {
00556       if (!strcmp(attr->key, key))
00557       {
00558         if (attr->value) free(attr->value);
00559         /* a set of NULL deletes the attr */
00560         if (value == NULL)
00561         {
00562           if (attr == obj->attr) // XXX - originally if (last == obj->attr)
00563             obj->attr = attr->next;
00564           else
00565             last->next = attr->next;
00566           free(attr->key);
00567           free(attr);
00568           return STATUS_OK;
00569         }
00570         attr->value = strdup(value);
00571         if (attr->value == NULL)
00572           return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
00573         return STATUS_OK;
00574       }
00575       last = attr;
00576       attr = attr->next;
00577     }
00578     last->next = (HDF_ATTR *) calloc(1, sizeof(HDF_ATTR));
00579     if (last->next == NULL)
00580       return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
00581     attr = last->next;
00582   }
00583   else
00584   {
00585     if (value == NULL) return STATUS_OK;
00586     obj->attr = (HDF_ATTR *) calloc(1, sizeof(HDF_ATTR));
00587     if (obj->attr == NULL)
00588       return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
00589     attr = obj->attr;
00590   }
00591   attr->key = strdup(key);
00592   attr->value = strdup(value);
00593   if (attr->key == NULL || attr->value == NULL)
00594     return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
00595 
00596   return STATUS_OK;
00597 }
00598 #endif // HAVE_BROKEN_HDF_SET_ATTR

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