(svn r27985) -Codechange: Convert VA2 switches into ones with non-overlapping ranges...
[openttd.git] / src / misc / dbg_helpers.h
blobacc1437d097f73ae11edd727d8307484e1b1829f
1 /* $Id$ */
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 */
10 /** @file dbg_helpers.h Functions to be used for debug printings. */
12 #ifndef DBG_HELPERS_H
13 #define DBG_HELPERS_H
15 #include <map>
16 #include <stack>
18 #include "str.hpp"
20 #include "../direction_type.h"
21 #include "../signal_type.h"
22 #include "../tile_type.h"
23 #include "../track_type.h"
25 /** Helper template class that provides C array length and item type */
26 template <typename T> struct ArrayT;
28 /** Helper template class that provides C array length and item type */
29 template <typename T, size_t N> struct ArrayT<T[N]> {
30 static const size_t length = N;
31 typedef T item_t;
35 /**
36 * Helper template function that returns item of array at given index
37 * or t_unk when index is out of bounds.
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)
42 if ((size_t)idx >= ArrayT<T>::length) {
43 return t_unk;
45 return t[idx];
48 /**
49 * Helper template function that returns item of array at given index
50 * or t_inv when index == idx_inv
51 * or t_unk when index is out of bounds.
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)
56 if ((size_t)idx < ArrayT<T>::length) {
57 return t[idx];
59 if (idx == idx_inv) {
60 return t_inv;
62 return t_unk;
65 /**
66 * Helper template function that returns compound bitfield name that is
67 * concatenation of names of each set bit in the given value
68 * or t_inv when index == idx_inv
69 * or t_unk when index is out of bounds.
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)
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);
85 if (value != 0) out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), t_unk);
87 return out.Transfer();
90 CStrA ValueStr(Trackdir td);
91 CStrA ValueStr(TrackdirBits td_bits);
92 CStrA ValueStr(DiagDirection dd);
93 CStrA ValueStr(SignalType t);
95 /** Class that represents the dump-into-string target. */
96 struct DumpTarget {
98 /** Used as a key into map of known object instances. */
99 struct KnownStructKey {
100 size_t m_type_id;
101 const void *m_ptr;
103 KnownStructKey(size_t type_id, const void *ptr)
104 : m_type_id(type_id)
105 , m_ptr(ptr)
108 KnownStructKey(const KnownStructKey &src)
110 m_type_id = src.m_type_id;
111 m_ptr = src.m_ptr;
114 bool operator<(const KnownStructKey &other) const
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;
123 typedef std::map<KnownStructKey, CStrA> KNOWN_NAMES;
125 CStrA m_out; ///< the output string
126 int m_indent; ///< current indent/nesting level
127 std::stack<CStrA> m_cur_struct; ///< here we will track the current structure name
128 KNOWN_NAMES m_known_names; ///< map of known object instances and their structured names
130 DumpTarget()
131 : m_indent(0)
134 static size_t& LastTypeId();
135 CStrA GetCurrentStructName();
136 bool FindKnownName(size_t type_id, const void *ptr, CStrA &name);
138 void WriteIndent();
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);
144 /** Dump given enum value (as a number and as named value) */
145 template <typename E> void WriteEnumT(const char *name, E e)
147 WriteValue(name, ValueStr(e).Data());
150 void BeginStruct(size_t type_id, const char *name, const void *ptr);
151 void EndStruct();
153 /** Dump nested object (or only its name if this instance is already known). */
154 template <typename S> void WriteStructT(const char *name, const S *s)
156 static size_t type_id = ++LastTypeId();
158 if (s == NULL) {
159 /* No need to dump NULL struct. */
160 WriteLine("%s = <null>", name);
161 return;
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();
176 #endif /* DBG_HELPERS_H */