OpenTTD Source 20260208-master-g43af8e94d0
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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#include "../core/format.hpp"
20
25template <typename E>
26inline std::string_view ItemAt(E idx, std::span<const std::string_view> t, std::string_view t_unk)
27{
28 if (static_cast<size_t>(idx) >= std::size(t)) {
29 return t_unk;
30 }
31 return t[idx];
32}
33
39template <typename E>
40inline std::string_view ItemAt(E idx, std::span<const std::string_view> t, std::string_view t_unk, E idx_inv, std::string_view t_inv)
41{
42 if (idx == idx_inv) {
43 return t_inv;
44 }
45 return ItemAt(idx, t, t_unk);
46}
47
54template <typename E>
55inline std::string ComposeName(E value, std::span<const std::string_view> t, std::string_view t_unk, E val_inv, std::string_view name_inv)
56{
57 std::string out;
58 if (value == val_inv) {
59 out = name_inv;
60 } else if (value == 0) {
61 out = "<none>";
62 } else {
63 for (size_t i = 0; i < std::size(t); i++) {
64 if ((value & (1 << i)) == 0) continue;
65 out += (!out.empty() ? "+" : "");
66 out += t[i];
67 value &= ~(E)(1 << i);
68 }
69 if (value != 0) {
70 out += (!out.empty() ? "+" : "");
71 out += t_unk;
72 }
73 }
74 return out;
75}
76
82template <typename E>
83inline std::string ComposeName(E value, std::span<const std::string_view> names, std::string_view unknown_name)
84{
85 std::string out;
86 if (value.base() == 0) {
87 out = "<none>";
88 } else {
89 for (size_t i = 0; i < std::size(names); ++i) {
90 if (!value.Test(static_cast<E::EnumType>(i))) continue;
91 out += (!out.empty() ? "+" : "");
92 out += names[i];
93 value.Reset(static_cast<E::EnumType>(i));
94 }
95 if (value.base() != 0) {
96 out += (!out.empty() ? "+" : "");
97 out += unknown_name;
98 }
99 }
100 return out;
101}
102
103std::string ValueStr(Trackdir td);
104std::string ValueStr(TrackdirBits td_bits);
105std::string ValueStr(DiagDirection dd);
106std::string ValueStr(SignalType t);
107
109struct DumpTarget {
110
112 struct KnownStructKey {
113 size_t m_type_id;
114 const void *m_ptr;
115
116 KnownStructKey(size_t type_id, const void *ptr)
117 : m_type_id(type_id)
118 , m_ptr(ptr)
119 {}
120
121 bool operator<(const KnownStructKey &other) const
122 {
123 if ((size_t)m_ptr < (size_t)other.m_ptr) return true;
124 if ((size_t)m_ptr > (size_t)other.m_ptr) return false;
125 if (m_type_id < other.m_type_id) return true;
126 return false;
127 }
128 };
129
130 typedef std::map<KnownStructKey, std::string> KNOWN_NAMES;
131
132 std::string m_out;
134 std::stack<std::string> m_cur_struct;
135 KNOWN_NAMES m_known_names;
136
137 DumpTarget()
138 : m_indent(0)
139 {}
140
141 static size_t &LastTypeId();
142 std::string GetCurrentStructName();
143 bool FindKnownName(size_t type_id, const void *ptr, std::string &name);
144
145 void WriteIndent();
146
148 void WriteValue(std::string_view name, const auto &value)
149 {
150 WriteIndent();
151 format_append(m_out, "{} = {}\n", name, value);
152 }
153
154 void WriteTile(std::string_view name, TileIndex t);
155
157 template <typename E> void WriteEnumT(std::string_view name, E e)
158 {
159 WriteValue(name, ValueStr(e));
160 }
161
162 void BeginStruct(size_t type_id, std::string_view name, const void *ptr);
163 void EndStruct();
164
166 template <typename S> void WriteStructT(std::string_view name, const S *s)
167 {
168 static const size_t type_id = ++LastTypeId();
169
170 if (s == nullptr) {
171 /* No need to dump nullptr struct. */
172 WriteValue(name, "<null>");
173 return;
174 }
175 std::string known_as;
176 if (FindKnownName(type_id, s, known_as)) {
177 /* We already know this one, no need to dump it. */
178 std::string known_as_str = std::string("known_as.") + known_as;
179 WriteValue(name, known_as_str);
180 } else {
181 /* Still unknown, dump it */
182 BeginStruct(type_id, name, s);
183 s->Dump(*this);
184 EndStruct();
185 }
186 }
187
189 template <typename S> void WriteStructT(std::string_view name, const std::deque<S> *s)
190 {
191 static const size_t type_id = ++LastTypeId();
192
193 if (s == nullptr) {
194 /* No need to dump nullptr struct. */
195 WriteValue(name, "<null>");
196 return;
197 }
198 std::string known_as;
199 if (FindKnownName(type_id, s, known_as)) {
200 /* We already know this one, no need to dump it. */
201 std::string known_as_str = std::string("known_as.") + known_as;
202 WriteValue(name, known_as_str);
203 } else {
204 /* Still unknown, dump it */
205 BeginStruct(type_id, name, s);
206 size_t num_items = s->size();
207 this->WriteValue("num_items", num_items);
208 for (size_t i = 0; i < num_items; i++) {
209 const auto &item = (*s)[i];
210 this->WriteStructT(fmt::format("item[{}]", i), &item);
211 }
212 EndStruct();
213 }
214 }
215};
216
217#endif /* DBG_HELPERS_H */
std::string ComposeName(E value, std::span< const std::string_view > t, std::string_view t_unk, E val_inv, std::string_view name_inv)
Helper template function that returns compound bitfield name that is concatenation of names of each s...
Definition dbg_helpers.h:55
std::string_view ItemAt(E idx, std::span< const std::string_view > t, std::string_view 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:26
std::string ValueStr(Trackdir td)
Return name of given Trackdir.
Different types to 'show' directions.
DiagDirection
Enumeration for diagonal directions.
String formatting functions and helpers.
Types and classes related to signals.
SignalType
Type of signal, i.e.
Definition signal_type.h:23
int m_indent
current indent/nesting level
std::string m_out
the output string
void WriteTile(std::string_view name, TileIndex t)
Write name & TileIndex to the output.
std::stack< std::string > m_cur_struct
here we will track the current structure name
void BeginStruct(size_t type_id, std::string_view name, const void *ptr)
Open new structure (one level deeper than the current one) 'name = {<LF>'.
void WriteStructT(std::string_view name, const std::deque< S > *s)
Dump nested object (or only its name if this instance is already known).
std::string GetCurrentStructName()
Return structured name of the current class/structure.
void WriteStructT(std::string_view name, const S *s)
Dump nested object (or only its name if this instance is already known).
KNOWN_NAMES m_known_names
map of known object instances and their structured names
bool FindKnownName(size_t type_id, const void *ptr, std::string &name)
Find the given instance in our anti-recursion repository.
void WriteEnumT(std::string_view name, E e)
Dump given enum value (as a number and as named value).
void WriteIndent()
Write some leading spaces into the output.
static size_t & LastTypeId()
Keep track of the last assigned type_id.
void EndStruct()
Close structure '}<LF>'.
void WriteValue(std::string_view name, const auto &value)
Write 'name = value' with indent and new-line.
Types related to tiles.
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
All types related to tracks.
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:66
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:97