# dbg_helpers.h

Go to the documentation of this file.

    00001 /* $Id: dbg_helpers.h 20603 2010-08-23 22:03:36Z rubidium $ */
    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 <map>
    00016 #include <stack>
    00017
    00018 #include "str.hpp"
    00019
    00020 #include "../direction_type.h"
    00021 #include "../signal_type.h"
    00022 #include "../tile_type.h"
    00023 #include "../track_type.h"
    00024
    00026 template <typename T> struct ArrayT;
    00027
    00029 template <typename T, size_t N> struct ArrayT<T[N]> {
    00030   static const size_t length = N;
    00031   typedef T item_t;
    00032 };
    00033
    00034
    00039 template <typename E, typename T>
    00040 inline typename ArrayT<T>::item_t ItemAtT(E idx, const T &t, typename ArrayT<T>::item_t t_unk)
    00041 {
    00042   if ((size_t)idx >= ArrayT<T>::length) {
    00043     return t_unk;
    00044   }
    00045   return t[idx];
    00046 }
    00047
    00053 template <typename E, typename T>
    00054 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)
    00055 {
    00056   if ((size_t)idx < ArrayT<T>::length) {
    00057     return t[idx];
    00058   }
    00059   if (idx == idx_inv) {
    00060     return t_inv;
    00061   }
    00062   return t_unk;
    00063 }
    00064
    00071 template <typename E, typename T>
    00072 inline CStrA ComposeNameT(E value, T &t, const char *t_unk, E val_inv, const char *name_inv)
    00073 {
    00074   CStrA out;
    00075   if (value == val_inv) {
    00076     out = name_inv;
    00077   } else if (value == 0) {
    00078     out = "<none>";
    00079   } else {
    00080     for (size_t i = 0; i < ArrayT<T>::length; i++) {
    00081       if ((value & (1 << i)) == 0) continue;
    00082       out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), (const char*)t[i]);
    00083       value &= ~(E)(1 << i);
    00084     }
    00085     if (value != 0) out.AddFormat("%s%s", (out.Size() > 0 ? "+" : ""), t_unk);
    00086   }
    00087   return out.Transfer();
    00088 }
    00089
    00090 CStrA ValueStr(Trackdir td);
    00091 CStrA ValueStr(TrackdirBits td_bits);
    00092 CStrA ValueStr(DiagDirection dd);
    00093 CStrA ValueStr(SignalType t);
    00094
    00096 struct DumpTarget {
    00097
    00099   struct KnownStructKey {
    00100     size_t      m_type_id;
    00101     const void *m_ptr;
    00102
    00103     KnownStructKey(size_t type_id, const void *ptr)
    00104       : m_type_id(type_id)
    00105       , m_ptr(ptr)
    00106     {}
    00107
    00108     KnownStructKey(const KnownStructKey &src)
    00109     {
    00110       m_type_id = src.m_type_id;
    00111       m_ptr = src.m_ptr;
    00112     }
    00113
    00114     bool operator < (const KnownStructKey &other) const
    00115     {
    00116       if ((size_t)m_ptr < (size_t)other.m_ptr) return true;
    00117       if ((size_t)m_ptr > (size_t)other.m_ptr) return false;
    00118       if (m_type_id < other.m_type_id) return true;
    00119       return false;
    00120     }
    00121   };
    00122
    00123   typedef std::map<KnownStructKey, CStrA> KNOWN_NAMES;
    00124
    00125   CStrA              m_out;
    00126   int                m_indent;
    00127   std::stack<CStrA>  m_cur_struct;
    00128   KNOWN_NAMES        m_known_names;
    00129
    00130   DumpTarget()
    00131     : m_indent(0)
    00132   {}
    00133
    00134   static size_t& LastTypeId();
    00135   CStrA GetCurrentStructName();
    00136   bool FindKnownName(size_t type_id, const void *ptr, CStrA &name);
    00137
    00138   void WriteIndent();
    00139
    00140   void CDECL WriteLine(const char *format, ...) WARN_FORMAT(2, 3);
    00141   void WriteValue(const char *name, const char *value_str);
    00142   void WriteTile(const char *name, TileIndex t);
    00143
    00145   template <typename E> void WriteEnumT(const char *name, E e)
    00146   {
    00147     WriteValue(name, ValueStr(e).Data());
    00148   }
    00149
    00150   void BeginStruct(size_t type_id, const char *name, const void *ptr);
    00151   void EndStruct();
    00152
    00154   template <typename S> void WriteStructT(const char *name, const S *s)
    00155   {
    00156     static size_t type_id = ++LastTypeId();
    00157
    00158     if (s == NULL) {
    00159       /* No need to dump NULL struct. */
    00160       WriteLine("%s = <null>", name);
    00161       return;
    00162     }
    00163     CStrA known_as;
    00164     if (FindKnownName(type_id, s, known_as)) {
    00165       /* We already know this one, no need to dump it. */
    00166       WriteLine("%s = known_as.%s", name, known_as.Data());
    00167     } else {
    00168       /* Still unknown, dump it */
    00169       BeginStruct(type_id, name, s);
    00170       s->Dump(*this);
    00171       EndStruct();
    00172     }
    00173   }
    00174 };
    00175
    00176 #endif /* DBG_HELPERS_H */