OpenTTD
dbg_helpers.h
Go to the documentation of this file.
1 /* $Id: dbg_helpers.h 27362 2015-08-08 10:06:24Z alberth $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #ifndef DBG_HELPERS_H
13 #define DBG_HELPERS_H
14 
15 #include <map>
16 #include <stack>
17 
18 #include "str.hpp"
19 
20 #include "../direction_type.h"
21 #include "../signal_type.h"
22 #include "../tile_type.h"
23 #include "../track_type.h"
24 
26 template <typename T> struct ArrayT;
27 
29 template <typename T, size_t N> struct ArrayT<T[N]> {
30  static const size_t length = N;
31  typedef T item_t;
32 };
33 
34 
39 template <typename E, typename T>
40 inline typename ArrayT<T>::item_t ItemAtT(E idx, const T &t, typename ArrayT<T>::item_t t_unk)
41 {
42  if ((size_t)idx >= ArrayT<T>::length) {
43  return t_unk;
44  }
45  return t[idx];
46 }
47 
53 template <typename E, typename T>
54 inline typename ArrayT<T>::item_t ItemAtT(E idx, const T &t, typename ArrayT<T>::item_t t_unk, E idx_inv, typename ArrayT<T>::item_t t_inv)
55 {
56  if ((size_t)idx < ArrayT<T>::length) {
57  return t[idx];
58  }
59  if (idx == idx_inv) {
60  return t_inv;
61  }
62  return t_unk;
63 }
64 
71 template <typename E, typename T>
72 inline CStrA ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
73 {
74  CStrA out;
75  if (value == val_inv) {
76  out = name_inv;
77  } else if (value == 0) {
78  out = "<none>";
79  } else {
80  for (size_t i = 0; i < ArrayT<T>::length; i++) {
81  if ((value & (1 << i)) == 0) continue;
82  out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), (const char*)t[i]);
83  value &= ~(E)(1 << i);
84  }
85  if (value != 0) out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), t_unk);
86  }
87  return out.Transfer();
88 }
89 
91 CStrA ValueStr(TrackdirBits td_bits);
94 
96 struct DumpTarget {
97 
99  struct KnownStructKey {
100  size_t m_type_id;
101  const void *m_ptr;
102 
103  KnownStructKey(size_t type_id, const void *ptr)
104  : m_type_id(type_id)
105  , m_ptr(ptr)
106  {}
107 
108  KnownStructKey(const KnownStructKey &src)
109  {
110  m_type_id = src.m_type_id;
111  m_ptr = src.m_ptr;
112  }
113 
114  bool operator<(const KnownStructKey &other) const
115  {
116  if ((size_t)m_ptr < (size_t)other.m_ptr) return true;
117  if ((size_t)m_ptr > (size_t)other.m_ptr) return false;
118  if (m_type_id < other.m_type_id) return true;
119  return false;
120  }
121  };
122 
123  typedef std::map<KnownStructKey, CStrA> KNOWN_NAMES;
124 
126  int m_indent;
127  std::stack<CStrA> m_cur_struct;
128  KNOWN_NAMES m_known_names;
129 
130  DumpTarget()
131  : m_indent(0)
132  {}
133 
134  static size_t& LastTypeId();
136  bool FindKnownName(size_t type_id, const void *ptr, CStrA &name);
137 
138  void WriteIndent();
139 
140  void CDECL WriteLine(const char *format, ...) WARN_FORMAT(2, 3);
141  void WriteValue(const char *name, const char *value_str);
142  void WriteTile(const char *name, TileIndex t);
143 
145  template <typename E> void WriteEnumT(const char *name, E e)
146  {
147  WriteValue(name, ValueStr(e).Data());
148  }
149 
150  void BeginStruct(size_t type_id, const char *name, const void *ptr);
151  void EndStruct();
152 
154  template <typename S> void WriteStructT(const char *name, const S *s)
155  {
156  static size_t type_id = ++LastTypeId();
157 
158  if (s == NULL) {
159  /* No need to dump NULL struct. */
160  WriteLine("%s = <null>", name);
161  return;
162  }
163  CStrA known_as;
164  if (FindKnownName(type_id, s, known_as)) {
165  /* We already know this one, no need to dump it. */
166  WriteLine("%s = known_as.%s", name, known_as.Data());
167  } else {
168  /* Still unknown, dump it */
169  BeginStruct(type_id, name, s);
170  s->Dump(*this);
171  EndStruct();
172  }
173  }
174 };
175 
176 #endif /* DBG_HELPERS_H */