GiNaC  1.8.0
class_info.h
Go to the documentation of this file.
1 
5 /*
6  * GiNaC Copyright (C) 1999-2020 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 
35 namespace 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 
40 template <class OPT>
41 class class_info {
42 public:
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 
62  OPT options;
63 
64 private:
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 
76  static class_info *first;
78  mutable class_info *parent;
79 
80  static bool parents_identified;
81 };
82 
83 template <class OPT>
84 const 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 
110 template <class OPT>
111 void 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 
147 template <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 
176 template <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 
193 template <class OPT> class_info<OPT> *class_info<OPT>::first = nullptr;
194 template <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
static void dump_tree(tree_node *n, const std::string &prefix, bool verbose)
Definition: class_info.h:111
Definition: add.cpp:38
std::ostream & tree(std::ostream &os)
Definition: operators.cpp:468
static const class_info * find(const std::string &class_name)
Find class_info by name.
Definition: class_info.h:84
std::vector< tree_node * > children
Definition: class_info.h:69
static void dump_hierarchy(bool verbose=false)
Dump class hierarchy to std::cout.
Definition: class_info.h:148
static bool parents_identified
Definition: class_info.h:80
size_t n
Definition: factor.cpp:1463
tree_node(class_info *i)
Definition: class_info.h:66
class_info(const OPT &o)
Definition: class_info.h:43
class_info * get_parent() const
Get pointer to class_info of parent class (or nullptr).
Definition: class_info.h:50
static class_info * first
Definition: class_info.h:76
void add_child(tree_node *n)
Definition: class_info.h:67
static void identify_parents()
Definition: class_info.h:177

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