|
@@ -12,8 +12,7 @@
|
|
|
|
|
|
#include <map>
|
|
|
#include <stack>
|
|
|
|
|
|
#include "str.hpp"
|
|
|
#include <string>
|
|
|
|
|
|
#include "../direction_type.h"
|
|
|
#include "../signal_type.h"
|
|
@@ -67,9 +66,9 @@ inline typename ArrayT<T>::item_t ItemAt
|
|
|
* or t_unk when index is out of bounds.
|
|
|
*/
|
|
|
template <typename E, typename T>
|
|
|
inline CStrA ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
|
|
|
inline std::string ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
|
|
|
{
|
|
|
CStrA out;
|
|
|
std::string out;
|
|
|
if (value == val_inv) {
|
|
|
out = name_inv;
|
|
|
} else if (value == 0) {
|
|
@@ -77,18 +76,22 @@ inline CStrA ComposeNameT(E value, T &t,
|
|
|
} else {
|
|
|
for (size_t i = 0; i < ArrayT<T>::length; i++) {
|
|
|
if ((value & (1 << i)) == 0) continue;
|
|
|
out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), (const char*)t[i]);
|
|
|
out += (!out.empty() ? "+" : "");
|
|
|
out += t[i];
|
|
|
value &= ~(E)(1 << i);
|
|
|
}
|
|
|
if (value != 0) out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), t_unk);
|
|
|
if (value != 0) {
|
|
|
out += (!out.empty() ? "+" : "");
|
|
|
out += t_unk;
|
|
|
}
|
|
|
}
|
|
|
return out.Transfer();
|
|
|
return out;
|
|
|
}
|
|
|
|
|
|
CStrA ValueStr(Trackdir td);
|
|
|
CStrA ValueStr(TrackdirBits td_bits);
|
|
|
CStrA ValueStr(DiagDirection dd);
|
|
|
CStrA ValueStr(SignalType t);
|
|
|
std::string ValueStr(Trackdir td);
|
|
|
std::string ValueStr(TrackdirBits td_bits);
|
|
|
std::string ValueStr(DiagDirection dd);
|
|
|
std::string ValueStr(SignalType t);
|
|
|
|
|
|
/** Class that represents the dump-into-string target. */
|
|
|
struct DumpTarget {
|
|
@@ -118,31 +121,31 @@ struct DumpTarget {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
typedef std::map<KnownStructKey, CStrA> KNOWN_NAMES;
|
|
|
typedef std::map<KnownStructKey, std::string> KNOWN_NAMES;
|
|
|
|
|
|
CStrA m_out; ///< the output string
|
|
|
int m_indent; ///< current indent/nesting level
|
|
|
std::stack<CStrA> m_cur_struct; ///< here we will track the current structure name
|
|
|
KNOWN_NAMES m_known_names; ///< map of known object instances and their structured names
|
|
|
std::string m_out; ///< the output string
|
|
|
int m_indent; ///< current indent/nesting level
|
|
|
std::stack<std::string> m_cur_struct; ///< here we will track the current structure name
|
|
|
KNOWN_NAMES m_known_names; ///< map of known object instances and their structured names
|
|
|
|
|
|
DumpTarget()
|
|
|
: m_indent(0)
|
|
|
{}
|
|
|
|
|
|
static size_t& LastTypeId();
|
|
|
CStrA GetCurrentStructName();
|
|
|
bool FindKnownName(size_t type_id, const void *ptr, CStrA &name);
|
|
|
std::string GetCurrentStructName();
|
|
|
bool FindKnownName(size_t type_id, const void *ptr, std::string &name);
|
|
|
|
|
|
void WriteIndent();
|
|
|
|
|
|
void CDECL WriteLine(const char *format, ...) WARN_FORMAT(2, 3);
|
|
|
void WriteValue(const char *name, int value);
|
|
|
void WriteValue(const char *name, const char *value_str);
|
|
|
void WriteTile(const char *name, TileIndex t);
|
|
|
|
|
|
/** Dump given enum value (as a number and as named value) */
|
|
|
template <typename E> void WriteEnumT(const char *name, E e)
|
|
|
{
|
|
|
WriteValue(name, ValueStr(e).Data());
|
|
|
WriteValue(name, ValueStr(e).c_str());
|
|
|
}
|
|
|
|
|
|
void BeginStruct(size_t type_id, const char *name, const void *ptr);
|
|
@@ -155,13 +158,14 @@ struct DumpTarget {
|
|
|
|
|
|
if (s == nullptr) {
|
|
|
/* No need to dump nullptr struct. */
|
|
|
WriteLine("%s = <null>", name);
|
|
|
WriteValue(name, "<null>");
|
|
|
return;
|
|
|
}
|
|
|
CStrA known_as;
|
|
|
std::string known_as;
|
|
|
if (FindKnownName(type_id, s, known_as)) {
|
|
|
/* We already know this one, no need to dump it. */
|
|
|
WriteLine("%s = known_as.%s", name, known_as.Data());
|
|
|
std::string known_as_str = std::string("known_as.") + name;
|
|
|
WriteValue(name, known_as_str.c_str());
|
|
|
} else {
|
|
|
/* Still unknown, dump it */
|
|
|
BeginStruct(type_id, name, s);
|