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/>.
10 /** @file dbg_helpers.h Functions to be used for debug printings. */
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
;
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
) {
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
) {
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
)
75 if (value
== val_inv
) {
77 } else if (value
== 0) {
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. */
98 /** Used as a key into map of known object instances. */
99 struct KnownStructKey
{
103 KnownStructKey(size_t type_id
, const void *ptr
)
108 KnownStructKey(const KnownStructKey
&src
)
110 m_type_id
= src
.m_type_id
;
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;
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
134 static size_t& LastTypeId();
135 CStrA
GetCurrentStructName();
136 bool FindKnownName(size_t type_id
, const void *ptr
, CStrA
&name
);
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
);
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();
159 /* No need to dump NULL struct. */
160 WriteLine("%s = <null>", name
);
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());
168 /* Still unknown, dump it */
169 BeginStruct(type_id
, name
, s
);
176 #endif /* DBG_HELPERS_H */