OmniEvents
PersistNode.cc
Go to the documentation of this file.
1 // Package : omniEvents
2 // PersistNode.cc Created : 2004/04/29
3 // Author : Alex Tingle
4 //
5 // Copyright (C) 2004 Alex Tingle.
6 //
7 // This file is part of the omniEvents application.
8 //
9 // omniEvents is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // omniEvents is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 
24 #include "PersistNode.h"
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <climits>
29 
30 namespace OmniEvents {
31 
32 
34 {
35  while( readnode(is) ){}
36 }
37 
39 {
40  for(map<string,PersistNode*>::iterator i=_child.begin(); i!=_child.end(); ++i)
41  delete i->second;
42 }
43 
44 void PersistNode::output(ostream& os,string name) const
45 {
46  if(!name.empty()) // Don't output root node.
47  {
48  os<<name<<'\n';
49  for(map<string,string>::const_iterator i=_attr.begin();
50  i!=_attr.end();
51  ++i)
52  {
53  os<<" "<<i->first<<"="<<i->second<<'\n';
54  }
55  os<<" ;;\n";
56  name+="/";
57  }
58  for(map<string,PersistNode*>::const_iterator i=_child.begin();
59  i!=_child.end();
60  ++i)
61  {
62  i->second->output(os,name+i->first);
63  }
64 }
65 
66 
67 inline bool PersistNode::readnode(istream& is)
68 {
69  PersistNode* node =NULL;
70  string tok;
71  while(true)
72  {
73  if(!readtoken(is,tok) || tok==";;")
74  return bool(node);
75  else if(node)
76  node->addattr(tok);
77  else if(tok[0]=='-')
78  delnode(tok.substr(1));
79  else
80  node=addnode(tok);
81  }
82 }
83 
84 inline bool PersistNode::readtoken(istream& is, string& tok)
85 {
86  while(is)
87  {
88  is>>tok;
89  if(tok.empty())
90  break;
91  if(tok[0]!='#')
92  return true;
93  is.ignore(INT_MAX,'\n');
94  }
95  return false;
96 }
97 
98 PersistNode* PersistNode::addnode(const string& name)
99 {
100  string::size_type pos =name.find('/');
101  // get reference to Next node in the path.
102  PersistNode*& newchild =_child[name.substr(0,pos)];
103 
104  if(pos==string::npos) // leaf: add new leaf.
105  {
106  if(newchild)
107  delete newchild; // overwrite old leaf (and its children)
108  newchild=new PersistNode();
109  return newchild;
110  }
111  else // branch: just add the branch if it's missing, and then recurse.
112  {
113  if(!newchild)
114  newchild=new PersistNode();
115  return newchild->addnode(name.substr(pos+1));
116  }
117 }
118 
119 void PersistNode::delnode(const string& name)
120 {
121  string::size_type pos =name.find('/');
122  // get reference to Next node in the path.
123  map<string,PersistNode*>::iterator childpos =_child.find(name.substr(0,pos));
124  if(childpos!=_child.end())
125  {
126  if(pos==string::npos) // leaf: delete leaf.
127  {
128  delete childpos->second;
129  _child.erase(childpos);
130  }
131  else // branch: recurse
132  {
133  childpos->second->delnode(name.substr(pos+1));
134  }
135  }
136 }
137 
138 void PersistNode::addattr(const string& keyvalue)
139 {
140  string::size_type pos =keyvalue.find('=');
141  _attr[keyvalue.substr(0,pos)]=(pos==string::npos?"":keyvalue.substr(pos+1));
142 }
143 
144 void PersistNode::addattr(const string& key, long value)
145 {
146  char buf[64];
147  sprintf(buf,"%i",value);
148  _attr[key]=string(buf);
149 }
150 
151 bool PersistNode::hasAttr(const string& key) const
152 {
153  return( _attr.find(key)!=_attr.end() );
154 }
155 string PersistNode::attrString(const string& key, const string& fallback) const
156 {
157  map<string,string>::const_iterator pos=_attr.find(key);
158  if(pos==_attr.end())
159  return fallback;
160  else
161  return pos->second;
162 }
163 long PersistNode::attrLong(const string& key, long fallback) const
164 {
165  map<string,string>::const_iterator pos=_attr.find(key);
166  if(pos==_attr.end())
167  return fallback;
168  else
169  return atol(pos->second.c_str());
170 }
171 PersistNode* PersistNode::child(const string& key) const
172 {
173  map<string,PersistNode*>::const_iterator pos=_child.find(key);
174  if(pos==_child.end())
175  return NULL;
176  else
177  return pos->second;
178 }
179 
180 }; // end namespace OmniEvents
void output(ostream &os, string name) const
Definition: PersistNode.cc:44
bool readtoken(istream &is, string &tok)
Definition: PersistNode.cc:84
map< string, PersistNode * > _child
Definition: PersistNode.h:71
bool hasAttr(const string &key) const
Definition: PersistNode.cc:151
map< string, string > _attr
Definition: PersistNode.h:72
~PersistNode()
Free node and all its children.
Definition: PersistNode.cc:38
string attrString(const string &key, const string &fallback="") const
Definition: PersistNode.cc:155
void delnode(const string &name)
Definition: PersistNode.cc:119
PersistNode * addnode(const string &name)
Definition: PersistNode.cc:98
bool readnode(istream &is)
Definition: PersistNode.cc:67
long attrLong(const string &key, long fallback=0) const
Definition: PersistNode.cc:163
PersistNode()
Create an empty node.
Definition: PersistNode.h:51
PersistNode * child(const string &key) const
Definition: PersistNode.cc:171
void addattr(const string &keyvalue)
Definition: PersistNode.cc:138