Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

PersistNode.cc

Go to the documentation of this file.
00001 //                            Package   : omniEvents
00002 // PersistNode.cc             Created   : 2004/04/29
00003 //                            Author    : Alex Tingle
00004 //
00005 //    Copyright (C) 2004 Alex Tingle.
00006 //
00007 //    This file is part of the omniEvents application.
00008 //
00009 //    omniEvents is free software; you can redistribute it and/or
00010 //    modify it under the terms of the GNU Lesser General Public
00011 //    License as published by the Free Software Foundation; either
00012 //    version 2.1 of the License, or (at your option) any later version.
00013 //
00014 //    omniEvents is distributed in the hope that it will be useful,
00015 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 //    Lesser General Public License for more details.
00018 //
00019 //    You should have received a copy of the GNU Lesser General Public
00020 //    License along with this library; if not, write to the Free Software
00021 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 
00024 #include "PersistNode.h"
00025 
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 
00029 namespace OmniEvents {
00030 
00031 
00032 PersistNode::PersistNode(istream& is)
00033 {
00034   while( readnode(is) ){}
00035 }
00036 
00037 PersistNode::~PersistNode()
00038 {
00039   for(map<string,PersistNode*>::iterator i=_child.begin(); i!=_child.end(); ++i)
00040       delete i->second;
00041 }
00042 
00043 void PersistNode::output(ostream& os,string name) const
00044 {
00045   if(!name.empty()) // Don't output root node.
00046   {
00047     os<<name<<'\n';
00048     for(map<string,string>::const_iterator i=_attr.begin();
00049         i!=_attr.end();
00050         ++i)
00051     {
00052       os<<" "<<i->first<<"="<<i->second<<'\n';
00053     }
00054     os<<" ;;\n";
00055     name+="/";
00056   }
00057   for(map<string,PersistNode*>::const_iterator i=_child.begin();
00058       i!=_child.end();
00059      ++i)
00060   {
00061     i->second->output(os,name+i->first);
00062   }
00063 }
00064 
00065 
00066 inline bool PersistNode::readnode(istream& is)
00067 {
00068   PersistNode* node =NULL;
00069   string tok;
00070   while(true)
00071   {
00072     if(!readtoken(is,tok) || tok==";;")
00073         return bool(node);
00074     else if(node)
00075         node->addattr(tok);
00076     else if(tok[0]=='-')
00077         delnode(tok.substr(1));
00078     else
00079         node=addnode(tok);
00080   }
00081 }
00082 
00083 inline bool PersistNode::readtoken(istream& is, string& tok)
00084 {
00085   while(is)
00086   {
00087     is>>tok;
00088     if(tok.empty())
00089         break;
00090     if(tok[0]!='#')
00091         return true;
00092     is.ignore(INT_MAX,'\n');
00093   }
00094   return false;
00095 }
00096 
00097 PersistNode* PersistNode::addnode(const string& name)
00098 {
00099   string::size_type pos =name.find('/');
00100   // get reference to Next node in the path.
00101   PersistNode*& newchild =_child[name.substr(0,pos)];
00102 
00103   if(pos==string::npos) // leaf: add new leaf.
00104   {
00105     if(newchild)
00106         delete newchild; // overwrite old leaf (and its children)
00107     newchild=new PersistNode();
00108     return newchild;
00109   }
00110   else // branch: just add the branch if it's missing, and then recurse.
00111   {
00112     if(!newchild)
00113         newchild=new PersistNode();
00114     return newchild->addnode(name.substr(pos+1));
00115   }
00116 }
00117 
00118 void PersistNode::delnode(const string& name)
00119 {
00120   string::size_type pos =name.find('/');
00121   // get reference to Next node in the path.
00122   map<string,PersistNode*>::iterator childpos =_child.find(name.substr(0,pos));
00123   if(childpos!=_child.end())
00124   {
00125     if(pos==string::npos) // leaf: delete leaf.
00126     {
00127       delete childpos->second;
00128       _child.erase(childpos);
00129     }
00130     else // branch: recurse
00131     {
00132       childpos->second->delnode(name.substr(pos+1));
00133     }
00134   }
00135 }
00136 
00137 void PersistNode::addattr(const string& keyvalue)
00138 {
00139   string::size_type pos =keyvalue.find('=');
00140   _attr[keyvalue.substr(0,pos)]=(pos==string::npos?"":keyvalue.substr(pos+1));
00141 }
00142 
00143 void PersistNode::addattr(const string& key, long value)
00144 {
00145   char buf[64];
00146   sprintf(buf,"%i",value);
00147   _attr[key]=string(buf);
00148 }
00149 
00150 bool PersistNode::hasAttr(const string& key) const
00151 {
00152   return( _attr.find(key)!=_attr.end() );
00153 }
00154 string PersistNode::attrString(const string& key, const string& fallback) const
00155 {
00156   map<string,string>::const_iterator pos=_attr.find(key);
00157   if(pos==_attr.end())
00158       return fallback;
00159   else
00160       return pos->second;
00161 }
00162 long PersistNode::attrLong(const string& key, long fallback) const
00163 {
00164   map<string,string>::const_iterator pos=_attr.find(key);
00165   if(pos==_attr.end())
00166       return fallback;
00167   else
00168       return atol(pos->second.c_str());
00169 }
00170 PersistNode* PersistNode::child(const string& key) const
00171 {
00172   map<string,PersistNode*>::const_iterator pos=_child.find(key);
00173   if(pos==_child.end())
00174       return NULL;
00175   else
00176       return pos->second;
00177 }
00178 
00179 }; // end namespace OmniEvents

Generated on Fri Aug 26 20:56:14 2005 for OmniEvents by  doxygen 1.4.3-20050530