g++/final: don't add extra code to check for buffer overflows (-fno-stack-protector)
[senf.git] / senf / Utils / Console / Node.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief Node non-inline non-template implementation */
30
31 #include "Node.hh"
32
33 // Custom includes
34 #include <senf/Utils/Range.hh>
35
36 //#include "Node.mpp"
37 #define prefix_
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39
40 prefix_ senf::console::DirectoryNode & senf::console::root()
41 {
42     static DirectoryNode::ptr rootNode (new DirectoryNode());
43     return *rootNode;
44 }
45
46 namespace {
47     void dodump(std::ostream & output, unsigned level, senf::console::DirectoryNode & node)
48     {
49         std::string pad (2*level, ' ');
50         senf::console::DirectoryNode::child_iterator i (node.children().begin());
51         senf::console::DirectoryNode::child_iterator const i_end (node.children().end());
52         for (; i != i_end; ++i) {
53             output << pad << i->first;
54             if (i->second->isDirectory()) {
55                 output << "/\n";
56                 dodump(output, level+1,static_cast<senf::console::DirectoryNode&>(*i->second));
57             }
58             else if (i->second->isLink())
59                 output << "@ -> " << i->second->followLink().path() << '\n';
60             else
61                 output << '\n';
62         }
63     }
64 }
65
66 prefix_ void senf::console::dump(std::ostream & os, DirectoryNode & dir)
67 {
68     dodump(os,0,dir);
69 }
70
71 //-/////////////////////////////////////////////////////////////////////////////////////////////////
72 // senf::console::GenericNode
73
74 prefix_ std::string senf::console::GenericNode::path()
75     const
76 {
77     std::string path (name());
78     ptr node (parent());
79     while (node) {
80         path = node->name() + "/" + path;
81         node = node->parent();
82     }
83     return path.empty() ? "/" : path;
84 }
85
86 prefix_ std::string senf::console::GenericNode::path(DirectoryNode const & root)
87     const
88 {
89     std::string path;
90     cptr node (thisptr());
91     while (node && node != root.thisptr()) {
92         if (! path.empty())
93             path = node->name() + "/" + path;
94         else
95             path = node->name();
96         node = node->parent();
97     }
98     if (path.empty() || path[0] != '/')
99         path = "/" + path;
100     return path;
101 }
102
103 prefix_ bool senf::console::GenericNode::active()
104     const
105 {
106     cptr node (thisptr());
107     while (node->parent())
108         node = node->parent();
109     return node == root().thisptr();
110 }
111
112 prefix_ bool senf::console::GenericNode::isChildOf(DirectoryNode & parent)
113     const
114 {
115     cptr node (thisptr());
116     while (node && node != parent.thisptr())
117         node = node->parent();
118     return node;
119 }
120
121 //-/////////////////////////////////////////////////////////////////////////////////////////////////
122 // senf::console::LinkNode
123
124 prefix_ void senf::console::LinkNode::v_help(std::ostream & os)
125     const
126 {
127     follow().help(os);
128 }
129
130 prefix_ std::string senf::console::LinkNode::v_shorthelp()
131     const
132 {
133     return follow().shorthelp();
134 }
135
136 //-/////////////////////////////////////////////////////////////////////////////////////////////////
137 //senf::console::DirectoryNode
138
139 prefix_ senf::console::DirectoryNode::~DirectoryNode()
140 {
141     ChildMap::iterator i (children_.begin());
142     ChildMap::iterator const i_end (children_.end());
143     for (; i != i_end; ++i)
144         i->second->parent_ = 0;
145 }
146
147 prefix_ senf::console::GenericNode::ptr
148 senf::console::DirectoryNode::remove(std::string const & name)
149 {
150     ChildMap::iterator i (children_.find(name));
151     if (i == children_.end())
152         throw UnknownNodeNameException() << ": '" << name << "'";
153     GenericNode::ptr node (i->second);
154     children_.erase(i);
155     node->parent_ = 0;
156     node->name_.clear();
157     return node;
158 }
159
160 prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node)
161 {
162     BOOST_ASSERT( ! node->parent() );
163     if (node->name().empty()) {
164         node->name("unnamed");
165         SENF_LOG((senf::log::MESSAGE)("Adding 'unnamed' node"));
166     }
167     if (children_.find(node->name()) != children_.end()) {
168         unsigned suffix (0);
169         std::string newName;
170         do {
171             ++suffix;
172             newName = node->name() + "-" + boost::lexical_cast<std::string>(suffix);
173         } while (children_.find(newName) != children_.end());
174         SENF_LOG((senf::log::MESSAGE)("Uniquifying node '" << node->name() << "' to '"
175                                       << newName << "'"));
176         node->name(newName);
177     }
178     children_.insert(std::make_pair(node->name(),node));
179     node->parent_ = this;
180 }
181
182 prefix_ senf::console::GenericNode &
183 senf::console::DirectoryNode::getLink(std::string const & name)
184     const
185 {
186     ChildMap::const_iterator i (children_.find(name));
187     if (i == children_.end())
188         throw UnknownNodeNameException() << ": '" << name << "'";
189     return *(i->second);
190 }
191
192 prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output)
193     const
194 {
195     output << doc_ << "\n";
196 }
197
198 prefix_ std::string senf::console::DirectoryNode::v_shorthelp()
199     const
200 {
201     if (! shortdoc_.empty())
202         return shortdoc_;
203     return doc_.substr(0,doc_.find('\n'));
204 }
205
206 //-/////////////////////////////////////////////////////////////////////////////////////////////////
207 // senf::console::SimpleCommandNode
208
209 prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
210     const
211 {
212     output << doc_ << "\n";
213 }
214
215 prefix_ std::string senf::console::SimpleCommandNode::v_shorthelp()
216     const
217 {
218     if (! shortdoc_.empty())
219         return shortdoc_;
220     return doc_.substr(0,doc_.find('\n'));
221 }
222
223 prefix_ void senf::console::SimpleCommandNode::v_execute(boost::any & rv, std::ostream & os,
224                                                          ParseCommandInfo const & command)
225     const
226 {
227     fn_(os, command);
228 }
229
230 //-/////////////////////////////////////////////////////////////////////////////////////////////////
231 #undef prefix_
232 //#include "Node.mpp"
233
234 \f
235 // Local Variables:
236 // mode: c++
237 // fill-column: 100
238 // comment-column: 40
239 // c-file-style: "senf"
240 // indent-tabs-mode: nil
241 // ispell-local-dictionary: "american"
242 // compile-command: "scons -u test"
243 // End: