Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
  3.  * It is copyright by its individual contributors, as recorded in the
  4.  * project's Git history.  See COPYING.txt at the top level for license
  5.  * terms and a link to the Git history.
  6.  */
  7.  
  8. #pragma once
  9.  
  10. #include <type_traits>
  11. #include <utility>
  12. #include "dxxsconf.h"
  13.  
  14. template <bool capture_source_location = false>
  15. class location_wrapper
  16. {
  17. public:
  18.         location_wrapper() = default;
  19.         /* Allow callers to pass explicit file/line, for signature
  20.          * compatibility with `location_wrapper<true>`.
  21.          */
  22.         location_wrapper(const char *, unsigned)
  23.         {
  24.         }
  25.         /* This must be a template to be compatible with the `scratch_buffer`
  26.          * template-typedef in `location_wrapper<true>`.
  27.          */
  28.         template <std::size_t N>
  29.                 using scratch_buffer = std::false_type;
  30.         template <std::size_t N>
  31.                 static std::pair<char (&)[N], std::integral_constant<std::size_t, N>> insert_location_leader(char (&buffer)[N])
  32.                 {
  33.                         return {buffer, {}};
  34.                 }
  35.         /* Define overloads to preserve const qualification */
  36.         static std::pair<char *, std::size_t> prepare_buffer(scratch_buffer<0> &, char *const text, const std::size_t len)
  37.         {
  38.                 return {text, len};
  39.         }
  40.         static std::pair<const char *, std::size_t> prepare_buffer(scratch_buffer<0> &, const char *const text, const std::size_t len)
  41.         {
  42.                 return {text, len};
  43.         }
  44. };
  45.  
  46. #ifdef DXX_HAVE_CXX_BUILTIN_FILE_LINE
  47. #include <cstdio>
  48.  
  49. template <>
  50. class location_wrapper<true>
  51. {
  52.         const char *file;
  53.         unsigned line;
  54. public:
  55.         template <std::size_t N>
  56.                 using scratch_buffer = char[N];
  57.         location_wrapper(const char *const f = __builtin_FILE(), const unsigned l = __builtin_LINE()) :
  58.                 file(f), line(l)
  59.         {
  60.         }
  61.         template <std::size_t N>
  62.                 std::pair<char *, std::size_t> insert_location_leader(char (&buffer)[N]) const
  63.                 {
  64.                         const auto written = std::snprintf(buffer, sizeof(buffer), "%s:%u: ", file, line);
  65.                         return {buffer + written, sizeof(buffer) - written};
  66.                 }
  67.         template <std::size_t N>
  68.                 std::pair<const char *, std::size_t> prepare_buffer(char (&buffer)[N], const char *const text, const std::size_t len) const
  69.                 {
  70.                         const auto written = std::snprintf(buffer, sizeof(buffer), "%s:%u: %.*s", file, line, static_cast<int>(len), text);
  71.                         return {buffer, len + written};
  72.                 }
  73.         /* Delegate to the const-qualified version, but return a `char *` to
  74.          * match the non-const input `char *`, to preserve the choice of
  75.          * overload for the function to receive this result.
  76.          */
  77.         template <std::size_t N>
  78.                 std::pair<char *, std::size_t> prepare_buffer(char (&buffer)[N], char *const text, const std::size_t len) const
  79.                 {
  80.                         return {buffer, prepare_buffer(buffer, const_cast<const char *>(text), len).second};
  81.                 }
  82. };
  83. #endif
  84.  
  85. template <typename T, bool capture_source_location = false>
  86. class location_value_wrapper : public location_wrapper<capture_source_location>
  87. {
  88.         T value;
  89. public:
  90.         /* Allow callers to pass explicit file/line, for signature
  91.          * compatibility with `location_value_wrapper<T, true>`.
  92.          */
  93. #ifndef DXX_HAVE_CXX_BUILTIN_FILE_LINE
  94.         location_value_wrapper(const T &v) :
  95.                 value(v)
  96.         {
  97.         }
  98. #endif
  99.         location_value_wrapper(const T &v,
  100.                 const char *const f
  101. #ifdef DXX_HAVE_CXX_BUILTIN_FILE_LINE
  102.                 = __builtin_FILE()
  103. #endif
  104.                 , const unsigned l
  105. #ifdef DXX_HAVE_CXX_BUILTIN_FILE_LINE
  106.                 = __builtin_LINE()
  107. #endif
  108.                 ) :
  109.                 location_wrapper<capture_source_location>(f, l),
  110.                 value(v)
  111.         {
  112.         }
  113.         operator T() const
  114.         {
  115.                 return value;
  116.         }
  117. };
  118.