3 * Helper templates to provide per-class information for class hierarchies. */
6 * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifndef __GINAC_CLASS_INFO_H__
24 #define __GINAC_CLASS_INFO_H__
26 #include <cstddef> // for size_t
35 // OPT is the class that stores the actual per-class data. It must provide
36 // get_name(), get_parent_name() and get_id() members.
41 class_info(const OPT & o) : options(o), next(first), parent(NULL)
44 parents_identified = false;
47 /** Get pointer to class_info of parent class (or NULL). */
48 class_info *get_parent() const
54 /** Find class_info by name. */
55 static const class_info *find(const std::string &class_name)
57 // Use a map for faster lookup. The registered_class_info list doesn't
58 // change at run-time, so it's sufficient to construct the map once
59 // on the first trip through this function.
60 typedef std::map<std::string, const class_info *> name_map_type;
61 static name_map_type name_map;
62 static bool name_map_initialized = false;
64 if (!name_map_initialized) {
66 const class_info *p = first;
68 name_map[p->options.get_name()] = p;
71 name_map_initialized = true;
74 typename name_map_type::const_iterator it = name_map.find(class_name);
75 if (it == name_map.end())
76 throw (std::runtime_error("class '" + class_name + "' not registered"));
83 tree_node(class_info *i) : info(i) {}
84 void add_child(tree_node *n) { children.push_back(n); }
86 std::vector<tree_node *> children;
90 static void dump_tree(tree_node *n, const std::string & prefix, bool verbose)
92 std::string name = n->info->options.get_name();
95 std::cout << " [ID 0x" << std::hex << std::setw(8) << std::setfill('0') << n->info->options.get_id() << std::dec << "]" << std::endl;
97 size_t num_children = n->children.size();
99 for (size_t i = 0; i < num_children; ++i) {
101 std::cout << prefix << " +- ";
102 if (i == num_children - 1)
103 dump_tree(n->children[i], prefix + " ", verbose);
105 dump_tree(n->children[i], prefix + " | ", verbose);
107 std::string spaces(name.size(), ' ');
109 std::cout << prefix << spaces;
110 if (num_children == 1)
111 std::cout << " --- ";
115 std::cout << " -+- ";
116 if (i == num_children - 1)
117 dump_tree(n->children[i], prefix + spaces + " ", verbose);
119 dump_tree(n->children[i], prefix + spaces + " | ", verbose);
123 std::cout << std::endl;
127 /** Dump class hierarchy to std::cout. */
128 static void dump_hierarchy(bool verbose = false)
132 // Create tree nodes for all class_infos
133 std::vector<tree_node> tree;
134 for (class_info *p = first; p; p = p->next)
135 tree.push_back(tree_node(p));
137 // Identify children for all nodes and find the root
138 tree_node *root = NULL;
139 for (typename std::vector<tree_node>::iterator i = tree.begin(); i != tree.end(); ++i) {
140 class_info *p = i->info->get_parent();
142 for (typename std::vector<tree_node>::iterator j = tree.begin(); j != tree.end(); ++j) {
152 // Print hierarchy tree starting at the root
153 dump_tree(root, "", verbose);
159 static void identify_parents()
161 if (!parents_identified) {
162 for (class_info *p = first; p; p = p->next) {
163 const char *parent_name = p->options.get_parent_name();
164 for (class_info *q = first; q; q = q->next) {
165 if (strcmp(q->options.get_name(), parent_name) == 0) {
171 parents_identified = true;
175 static class_info *first;
177 mutable class_info *parent;
179 static bool parents_identified;
182 template <class OPT> class_info<OPT> *class_info<OPT>::first = NULL;
183 template <class OPT> bool class_info<OPT>::parents_identified = false;
187 #endif // ndef __GINAC_CLASS_INFO_H__