OpenTTD Source  20241120-master-g6d3adc6169
dbg_helpers.h
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #ifndef DBG_HELPERS_H
11 #define DBG_HELPERS_H
12 
13 #include <stack>
14 
15 #include "../direction_type.h"
16 #include "../signal_type.h"
17 #include "../tile_type.h"
18 #include "../track_type.h"
19 
21 template <typename T> struct ArrayT;
22 
24 template <typename T, size_t N> struct ArrayT<T[N]> {
25  static const size_t length = N;
26  using Item = T;
27 };
28 
29 
34 template <typename E, typename T>
35 inline typename ArrayT<T>::Item ItemAtT(E idx, const T &t, typename ArrayT<T>::Item t_unk)
36 {
37  if (static_cast<size_t>(idx) >= ArrayT<T>::length) {
38  return t_unk;
39  }
40  return t[idx];
41 }
42 
48 template <typename E, typename T>
49 inline typename ArrayT<T>::Item ItemAtT(E idx, const T &t, typename ArrayT<T>::Item t_unk, E idx_inv, typename ArrayT<T>::Item t_inv)
50 {
51  if (static_cast<size_t>(idx) < ArrayT<T>::length) {
52  return t[idx];
53  }
54  if (idx == idx_inv) {
55  return t_inv;
56  }
57  return t_unk;
58 }
59 
66 template <typename E, typename T>
67 inline std::string ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
68 {
69  std::string out;
70  if (value == val_inv) {
71  out = name_inv;
72  } else if (value == 0) {
73  out = "<none>";
74  } else {
75  for (size_t i = 0; i < ArrayT<T>::length; i++) {
76  if ((value & (1 << i)) == 0) continue;
77  out += (!out.empty() ? "+" : "");
78  out += t[i];
79  value &= ~(E)(1 << i);
80  }
81  if (value != 0) {
82  out += (!out.empty() ? "+" : "");
83  out += t_unk;
84  }
85  }
86  return out;
87 }
88 
89 std::string ValueStr(Trackdir td);
90 std::string ValueStr(TrackdirBits td_bits);
91 std::string ValueStr(DiagDirection dd);
92 std::string ValueStr(SignalType t);
93 
95 struct DumpTarget {
96 
98  struct KnownStructKey {
99  size_t m_type_id;
100  const void *m_ptr;
101 
102  KnownStructKey(size_t type_id, const void *ptr)
103  : m_type_id(type_id)
104  , m_ptr(ptr)
105  {}
106 
107  bool operator<(const KnownStructKey &other) const
108  {
109  if ((size_t)m_ptr < (size_t)other.m_ptr) return true;
110  if ((size_t)m_ptr > (size_t)other.m_ptr) return false;
111  if (m_type_id < other.m_type_id) return true;
112  return false;
113  }
114  };
115 
116  typedef std::map<KnownStructKey, std::string> KNOWN_NAMES;
117 
118  std::string m_out;
119  int m_indent;
120  std::stack<std::string> m_cur_struct;
121  KNOWN_NAMES m_known_names;
122 
123  DumpTarget()
124  : m_indent(0)
125  {}
126 
127  static size_t &LastTypeId();
128  std::string GetCurrentStructName();
129  bool FindKnownName(size_t type_id, const void *ptr, std::string &name);
130 
131  void WriteIndent();
132 
133  void WriteValue(const std::string &name, int value);
134  void WriteValue(const std::string &name, const std::string &value_str);
135  void WriteTile(const std::string &name, TileIndex t);
136 
138  template <typename E> void WriteEnumT(const std::string &name, E e)
139  {
140  WriteValue(name, ValueStr(e));
141  }
142 
143  void BeginStruct(size_t type_id, const std::string &name, const void *ptr);
144  void EndStruct();
145 
147  template <typename S> void WriteStructT(const std::string &name, const S *s)
148  {
149  static size_t type_id = ++LastTypeId();
150 
151  if (s == nullptr) {
152  /* No need to dump nullptr struct. */
153  WriteValue(name, "<null>");
154  return;
155  }
156  std::string known_as;
157  if (FindKnownName(type_id, s, known_as)) {
158  /* We already know this one, no need to dump it. */
159  std::string known_as_str = std::string("known_as.") + known_as;
160  WriteValue(name, known_as_str);
161  } else {
162  /* Still unknown, dump it */
163  BeginStruct(type_id, name, s);
164  s->Dump(*this);
165  EndStruct();
166  }
167  }
168 
170  template <typename S> void WriteStructT(const std::string &name, const std::deque<S> *s)
171  {
172  static size_t type_id = ++LastTypeId();
173 
174  if (s == nullptr) {
175  /* No need to dump nullptr struct. */
176  WriteValue(name, "<null>");
177  return;
178  }
179  std::string known_as;
180  if (FindKnownName(type_id, s, known_as)) {
181  /* We already know this one, no need to dump it. */
182  std::string known_as_str = std::string("known_as.") + known_as;
183  WriteValue(name, known_as_str);
184  } else {
185  /* Still unknown, dump it */
186  BeginStruct(type_id, name, s);
187  size_t num_items = s->size();
188  this->WriteValue("num_items", std::to_string(num_items));
189  for (size_t i = 0; i < num_items; i++) {
190  const auto &item = (*s)[i];
191  this->WriteStructT(fmt::format("item[{}]", i), &item);
192  }
193  EndStruct();
194  }
195  }
196 };
197 
198 #endif /* DBG_HELPERS_H */
ArrayT< T >::Item ItemAtT(E idx, const T &t, typename ArrayT< T >::Item t_unk)
Helper template function that returns item of array at given index or t_unk when index is out of boun...
Definition: dbg_helpers.h:35
std::string ValueStr(Trackdir td)
Return name of given Trackdir.
Definition: dbg_helpers.cpp:26
std::string ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
Helper template function that returns compound bitfield name that is concatenation of names of each s...
Definition: dbg_helpers.h:67
DiagDirection
Enumeration for diagonal directions.
SignalType
Type of signal, i.e.
Definition: signal_type.h:23
Helper template class that provides C array length and item type.
Definition: dbg_helpers.h:21
Used as a key into map of known object instances.
Definition: dbg_helpers.h:98
Class that represents the dump-into-string target.
Definition: dbg_helpers.h:95
int m_indent
current indent/nesting level
Definition: dbg_helpers.h:119
void WriteEnumT(const std::string &name, E e)
Dump given enum value (as a number and as named value)
Definition: dbg_helpers.h:138
std::string m_out
the output string
Definition: dbg_helpers.h:118
void WriteValue(const std::string &name, int value)
Write 'name = value' with indent and new-line.
std::stack< std::string > m_cur_struct
here we will track the current structure name
Definition: dbg_helpers.h:120
void BeginStruct(size_t type_id, const std::string &name, const void *ptr)
Open new structure (one level deeper than the current one) 'name = {<LF>'.
std::string GetCurrentStructName()
Return structured name of the current class/structure.
Definition: dbg_helpers.cpp:80
KNOWN_NAMES m_known_names
map of known object instances and their structured names
Definition: dbg_helpers.h:121
bool FindKnownName(size_t type_id, const void *ptr, std::string &name)
Find the given instance in our anti-recursion repository.
Definition: dbg_helpers.cpp:94
void WriteTile(const std::string &name, TileIndex t)
Write name & TileIndex to the output.
void WriteIndent()
Write some leading spaces into the output.
static size_t & LastTypeId()
Keep track of the last assigned type_id.
Definition: dbg_helpers.cpp:73
void EndStruct()
Close structure '}<LF>'.
void WriteStructT(const std::string &name, const S *s)
Dump nested object (or only its name if this instance is already known).
Definition: dbg_helpers.h:147
void WriteStructT(const std::string &name, const std::deque< S > *s)
Dump nested object (or only its name if this instance is already known).
Definition: dbg_helpers.h:170
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:67
TrackdirBits
Allow incrementing of Trackdir variables.
Definition: track_type.h:98