OmniEvents
|
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