debug.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #pragma once
  2. #if !defined(NDEBUG) && defined(JVALIDATE_TRACE)
  3. #include <iostream>
  4. #include <map>
  5. #include <source_location>
  6. #include <string_view>
  7. #include <jvalidate/_macro.h>
  8. #include <jvalidate/detail/on_block_exit.h>
  9. namespace jvalidate::detail {
  10. template <typename K, typename V>
  11. std::ostream & operator<<(std::ostream & os, std::map<K, V> const & value) {
  12. os << '{';
  13. std::string_view div;
  14. for (auto const & [k, v] : value) {
  15. os << std::exchange(div, ", ") << k << ':' << ' ' << v;
  16. }
  17. return os << '}';
  18. }
  19. template <typename V> std::ostream & operator<<(std::ostream & os, std::vector<V> const & value) {
  20. os << '[';
  21. std::string_view div;
  22. for (auto const & v : value) {
  23. os << std::exchange(div, ", ") << v;
  24. }
  25. return os << ']';
  26. }
  27. template <typename V> std::ostream & operator<<(std::ostream & os, std::set<V> const & value) {
  28. os << '[';
  29. std::string_view div;
  30. for (auto const & v : value) {
  31. os << std::exchange(div, ", ") << v;
  32. }
  33. return os << ']';
  34. }
  35. }
  36. namespace jvalidate::detail {
  37. inline size_t g_debug_trace_depth = 0;
  38. }
  39. #define JVALIDATE_NAME(x) JVALIDATE_CONCAT(__, JVALIDATE_CONCAT(x, __LINE__))
  40. #define JVALIDATE_DEBUG(expression) \
  41. do { \
  42. using ::jvalidate::detail::operator<<; \
  43. auto JVALIDATE_NAME(here) = std::source_location::current(); \
  44. std::string_view JVALIDATE_NAME(fname) = JVALIDATE_NAME(here).file_name(); \
  45. JVALIDATE_NAME(fname).remove_prefix(JVALIDATE_NAME(fname).find_last_of('/') + 1); \
  46. std::cerr << std::string(2 * ::jvalidate::detail::g_depth, ' ') << JVALIDATE_NAME(fname) \
  47. << ':' << JVALIDATE_NAME(here).line() << ' ' << expression << std::endl; \
  48. } while (false)
  49. #define JVALIDATE_DEBUG_INDENTED_SCOPE() \
  50. ::jvalidate::detail::OnBlockExit JVALIDATE_NAME(indent_scope) = \
  51. (++::jvalidate::detail::g_debug_trace_depth, \
  52. []() { --::jvalidate::detail::g_debug_trace_depth; })
  53. #else
  54. #define JVALIDATE_DEBUG(...)
  55. #define JVALIDATE_DEBUG_INDENTED_SCOPE()
  56. #endif