GiNaC 1.8.7
class_info.h
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2023 Johannes Gutenberg University Mainz, Germany
7 *
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.
12 *
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.
17 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#ifndef GINAC_CLASS_INFO_H
24#define GINAC_CLASS_INFO_H
25
26#include <cstddef> // for size_t
27#include <cstring>
28#include <iomanip>
29#include <iostream>
30#include <map>
31#include <stdexcept>
32#include <string>
33#include <vector>
34
35namespace GiNaC {
36
37// OPT is the class that stores the actual per-class data. It must provide
38// get_name(), get_parent_name() and get_id() members.
39
40template <class OPT>
42public:
43 class_info(const OPT & o) : options(o), next(first), parent(nullptr)
44 {
45 first = this;
46 parents_identified = false;
47 }
48
51 {
53 return parent;
54 }
55
57 static const class_info *find(const std::string &class_name);
58
60 static void dump_hierarchy(bool verbose = false);
61
63
64private:
65 struct tree_node {
67 void add_child(tree_node *n) { children.push_back(n); }
68
69 std::vector<tree_node *> children;
71 };
72
73 static void dump_tree(tree_node *n, const std::string & prefix, bool verbose);
74 static void identify_parents();
75
79
80 static bool parents_identified;
81};
82
83template <class OPT>
84const class_info<OPT> *class_info<OPT>::find(const std::string &class_name)
85{
86 // Use a map for faster lookup. The registered_class_info list doesn't
87 // change at run-time, so it's sufficient to construct the map once
88 // on the first trip through this function.
89 typedef std::map<std::string, const class_info *> name_map_type;
90 static name_map_type name_map;
91 static bool name_map_initialized = false;
92
93 if (!name_map_initialized) {
94 // Construct map
95 const class_info *p = first;
96 while (p) {
97 name_map[p->options.get_name()] = p;
98 p = p->next;
99 }
100 name_map_initialized = true;
101 }
102
103 typename name_map_type::const_iterator it = name_map.find(class_name);
104 if (it == name_map.end())
105 throw (std::runtime_error("class '" + class_name + "' not registered"));
106 else
107 return it->second;
108}
109
110template <class OPT>
111void class_info<OPT>::dump_tree(tree_node *n, const std::string & prefix, bool verbose)
112{
113 std::string name = n->info->options.get_name();
114 std::cout << name;
115 if (verbose)
116 std::cout << " [ID 0x" << std::hex << std::setw(8) << std::setfill('0') << n->info->options.get_id() << std::dec << "]" << std::endl;
117
118 size_t num_children = n->children.size();
119 if (num_children) {
120 for (size_t i = 0; i < num_children; ++i) {
121 if (verbose) {
122 std::cout << prefix << " +- ";
123 if (i == num_children - 1)
124 dump_tree(n->children[i], prefix + " ", verbose);
125 else
126 dump_tree(n->children[i], prefix + " | ", verbose);
127 } else {
128 std::string spaces(name.size(), ' ');
129 if (i > 0)
130 std::cout << prefix << spaces;
131 if (num_children == 1)
132 std::cout << " --- ";
133 else if (i > 0)
134 std::cout << " +- ";
135 else
136 std::cout << " -+- ";
137 if (i == num_children - 1)
138 dump_tree(n->children[i], prefix + spaces + " ", verbose);
139 else
140 dump_tree(n->children[i], prefix + spaces + " | ", verbose);
141 }
142 }
143 } else if (!verbose)
144 std::cout << std::endl;
145}
146
147template <class OPT>
149{
150 identify_parents();
151
152 // Create tree nodes for all class_infos
153 std::vector<tree_node> tree;
154 for (class_info *p = first; p; p = p->next)
155 tree.push_back(tree_node(p));
156
157 // Identify children for all nodes and find the root
158 tree_node *root = nullptr;
159 for (typename std::vector<tree_node>::iterator i = tree.begin(); i != tree.end(); ++i) {
160 class_info *p = i->info->get_parent();
161 if (p) {
162 for (typename std::vector<tree_node>::iterator j = tree.begin(); j != tree.end(); ++j) {
163 if (j->info == p) {
164 j->add_child(&*i);
165 break;
166 }
167 }
168 } else
169 root = &*i;
170 }
171
172 // Print hierarchy tree starting at the root
173 dump_tree(root, "", verbose);
174}
175
176template <class OPT>
178{
179 if (!parents_identified) {
180 for (class_info *p = first; p; p = p->next) {
181 const char *parent_name = p->options.get_parent_name();
182 for (class_info *q = first; q; q = q->next) {
183 if (std::strcmp(q->options.get_name(), parent_name) == 0) {
184 p->parent = q;
185 break;
186 }
187 }
188 }
189 parents_identified = true;
190 }
191}
192
193template <class OPT> class_info<OPT> *class_info<OPT>::first = nullptr;
194template <class OPT> bool class_info<OPT>::parents_identified = false;
195
196} // namespace GiNaC
197
198#endif // ndef GINAC_CLASS_INFO_H
class_info * parent
Definition: class_info.h:78
class_info * next
Definition: class_info.h:77
class_info * get_parent() const
Get pointer to class_info of parent class (or nullptr).
Definition: class_info.h:50
class_info(const OPT &o)
Definition: class_info.h:43
static bool parents_identified
Definition: class_info.h:80
static const class_info * find(const std::string &class_name)
Find class_info by name.
Definition: class_info.h:84
static void dump_hierarchy(bool verbose=false)
Dump class hierarchy to std::cout.
Definition: class_info.h:148
static void identify_parents()
Definition: class_info.h:177
static class_info * first
Definition: class_info.h:76
static void dump_tree(tree_node *n, const std::string &prefix, bool verbose)
Definition: class_info.h:111
size_t n
Definition: factor.cpp:1432
Definition: add.cpp:38
std::ostream & tree(std::ostream &os)
Definition: operators.cpp:468
std::vector< tree_node * > children
Definition: class_info.h:69
void add_child(tree_node *n)
Definition: class_info.h:67
tree_node(class_info *i)
Definition: class_info.h:66

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.