# dbg_helpers.h

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #ifndef DBG_HELPERS_H
    00013 #define DBG_HELPERS_H
    00014
    00015 #include <new>
    00016 #include <map>
    00017 #include <stack>
    00018
    00019 #include "blob.hpp"
    00020 #include "str.hpp"
    00021
    00023 template <typename T> struct ArrayT;
    00024
    00026 template <typename T, size_t N> struct ArrayT<T[N]> {
    00027   static const size_t length = N;
    00028   typedef T item_t;
    00029 };
    00030
    00031
    00036 template <typename E, typename T>
    00037 inline typename ArrayT<T>::item_t ItemAtT(E idx, const T &t, typename ArrayT<T>::item_t t_unk)
    00038 {
    00039   if ((size_t)idx >= ArrayT<T>::length) {
    00040     return t_unk;
    00041   }
    00042   return t[idx];
    00043 }
    00044
    00050 template <typename E, typename T>
    00051 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)
    00052 {
    00053   if ((size_t)idx < ArrayT<T>::length) {
    00054     return t[idx];
    00055   }
    00056   if (idx == idx_inv) {
    00057     return t_inv;
    00058   }
    00059   return t_unk;
    00060 }
    00061
    00068 template <typename E, typename T>
    00069 inline CStrA ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
    00070 {
    00071   CStrA out;
    00072   if (value == val_inv) {
    00073     out = name_inv;
    00074   } else if (value == 0) {
    00075     out = "<none>";
    00076   } else {
    00077     for (size_t i = 0; i < ArrayT<T>::length; i++) {
    00078       if ((value & (1 << i)) == 0) continue;
    00079       out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), t[i]);
    00080       value &= ~(E)(1 << i);
    00081     }
    00082     if (value != 0) out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), t_unk);
    00083   }
    00084   return out.Transfer();
    00085 }
    00086
    00087 CStrA ValueStr(Trackdir td);
    00088 CStrA ValueStr(TrackdirBits td_bits);
    00089 CStrA ValueStr(DiagDirection dd);
    00090 CStrA ValueStr(SignalType t);
    00091
    00093 struct DumpTarget {
    00094
    00096   struct KnownStructKey {
    00097     size_t      m_type_id;
    00098     const void *m_ptr;
    00099
    00100     KnownStructKey(size_t type_id, const void *ptr)
    00101       : m_type_id(type_id)
    00102       , m_ptr(ptr)
    00103     {}
    00104
    00105     KnownStructKey(const KnownStructKey &src)
    00106     {
    00107       m_type_id = src.m_type_id;
    00108       m_ptr = src.m_ptr;
    00109     }
    00110
    00111     bool operator < (const KnownStructKey &other) const
    00112     {
    00113       if ((size_t)m_ptr < (size_t)other.m_ptr) return true;
    00114       if ((size_t)m_ptr > (size_t)other.m_ptr) return false;
    00115       if (m_type_id < other.m_type_id) return true;
    00116       return false;
    00117     }
    00118   };
    00119
    00120   typedef std::map<KnownStructKey, CStrA> KNOWN_NAMES;
    00121
    00122   CStrA              m_out;
    00123   int                m_indent;
    00124   std::stack<CStrA>  m_cur_struct;
    00125   KNOWN_NAMES        m_known_names;
    00126
    00127   DumpTarget()
    00128     : m_indent(0)
    00129   {}
    00130
    00131   static size_t& LastTypeId();
    00132   CStrA GetCurrentStructName();
    00133   bool FindKnownName(size_t type_id, const void *ptr, CStrA &name);
    00134
    00135   void WriteIndent();
    00136
    00137   void WriteLine(const char *format, ...);
    00138   void WriteValue(const char *name, const char *value_str);
    00139   void WriteTile(const char *name, TileIndex t);
    00140
    00142   template <typename E> void WriteEnumT(const char *name, E e)
    00143   {
    00144     WriteValue(name, ValueStr(e).Data());
    00145   }
    00146
    00147   void BeginStruct(size_t type_id, const char *name, const void *ptr);
    00148   void EndStruct();
    00149
    00151   template <typename S> void WriteStructT(const char *name, const S *s)
    00152   {
    00153     static size_t type_id = ++LastTypeId();
    00154
    00155     if (s == NULL) {
    00156       /* No need to dump NULL struct. */
    00157       WriteLine("%s = <null>", name);
    00158       return;
    00159     }
    00160     CStrA known_as;
    00161     if (FindKnownName(type_id, s, known_as)) {
    00162       /* We already know this one, no need to dump it. */
    00163       WriteLine("%s = known_as.%s", name, known_as.Data());
    00164     } else {
    00165       /* Still unknown, dump it */
    00166       BeginStruct(type_id, name, s);
    00167       s->Dump(*this);
    00168       EndStruct();
    00169     }
    00170   }
    00171 };
    00172
    00173 #endif /* DBG_HELPERS_H */