OmniEvents

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 #include <climits>
00029 
00030 namespace OmniEvents {
00031 
00032 
00033 PersistNode::PersistNode(istream& is)
00034 {
00035   while( readnode(is) ){}
00036 }
00037 
00038 PersistNode::~PersistNode()
00039 {
00040   for(map<string,PersistNode*>::iterator i=_child.begin(); i!=_child.end(); ++i)
00041       delete i->second;
00042 }
00043 
00044 void PersistNode::output(ostream& os,string name) const
00045 {
00046   if(!name.empty()) // Don't output root node.
00047   {
00048     os<<name<<'\n';
00049     for(map<string,string>::const_iterator i=_attr.begin();
00050         i!=_attr.end();
00051         ++i)
00052     {
00053       os<<" "<<i->first<<"="<<i->second<<'\n';
00054     }
00055     os<<" ;;\n";
00056     name+="/";
00057   }
00058   for(map<string,PersistNode*>::const_iterator i=_child.begin();
00059       i!=_child.end();
00060      ++i)
00061   {
00062     i->second->output(os,name+i->first);
00063   }
00064 }
00065 
00066 
00067 inline bool PersistNode::readnode(istream& is)
00068 {
00069   PersistNode* node =NULL;
00070   string tok;
00071   while(true)
00072   {
00073     if(!readtoken(is,tok) || tok==";;")
00074         return bool(node);
00075     else if(node)
00076         node->addattr(tok);
00077     else if(tok[0]=='-')
00078         delnode(tok.substr(1));
00079     else
00080         node=addnode(tok);
00081   }
00082 }
00083 
00084 inline bool PersistNode::readtoken(istream& is, string& tok)
00085 {
00086   while(is)
00087   {
00088     is>>tok;
00089     if(tok.empty())
00090         break;
00091     if(tok[0]!='#')
00092         return true;
00093     is.ignore(INT_MAX,'\n');
00094   }
00095   return false;
00096 }
00097 
00098 PersistNode* PersistNode::addnode(const string& name)
00099 {
00100   string::size_type pos =name.find('/');
00101   // get reference to Next node in the path.
00102   PersistNode*& newchild =_child[name.substr(0,pos)];
00103 
00104   if(pos==string::npos) // leaf: add new leaf.
00105   {
00106     if(newchild)
00107         delete newchild; // overwrite old leaf (and its children)
00108     newchild=new PersistNode();
00109     return newchild;
00110   }
00111   else // branch: just add the branch if it's missing, and then recurse.
00112   {
00113     if(!newchild)
00114         newchild=new PersistNode();
00115     return newchild->addnode(name.substr(pos+1));
00116   }
00117 }
00118 
00119 void PersistNode::delnode(const string& name)
00120 {
00121   string::size_type pos =name.find('/');
00122   // get reference to Next node in the path.
00123   map<string,PersistNode*>::iterator childpos =_child.find(name.substr(0,pos));
00124   if(childpos!=_child.end())
00125   {
00126     if(pos==string::npos) // leaf: delete leaf.
00127     {
00128       delete childpos->second;
00129       _child.erase(childpos);
00130     }
00131     else // branch: recurse
00132     {
00133       childpos->second->delnode(name.substr(pos+1));
00134     }
00135   }
00136 }
00137 
00138 void PersistNode::addattr(const string& keyvalue)
00139 {
00140   string::size_type pos =keyvalue.find('=');
00141   _attr[keyvalue.substr(0,pos)]=(pos==string::npos?"":keyvalue.substr(pos+1));
00142 }
00143 
00144 void PersistNode::addattr(const string& key, long value)
00145 {
00146   char buf[64];
00147   sprintf(buf,"%i",value);
00148   _attr[key]=string(buf);
00149 }
00150 
00151 bool PersistNode::hasAttr(const string& key) const
00152 {
00153   return( _attr.find(key)!=_attr.end() );
00154 }
00155 string PersistNode::attrString(const string& key, const string& fallback) const
00156 {
00157   map<string,string>::const_iterator pos=_attr.find(key);
00158   if(pos==_attr.end())
00159       return fallback;
00160   else
00161       return pos->second;
00162 }
00163 long PersistNode::attrLong(const string& key, long fallback) const
00164 {
00165   map<string,string>::const_iterator pos=_attr.find(key);
00166   if(pos==_attr.end())
00167       return fallback;
00168   else
00169       return atol(pos->second.c_str());
00170 }
00171 PersistNode* PersistNode::child(const string& key) const
00172 {
00173   map<string,PersistNode*>::const_iterator pos=_child.find(key);
00174   if(pos==_child.end())
00175       return NULL;
00176   else
00177       return pos->second;
00178 }
00179 
00180 }; // end namespace OmniEvents