depthguard.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
  2. #define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
  3. #if defined(_MSC_VER) || \
  4. (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
  5. (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
  6. #pragma once
  7. #endif
  8. #include "exceptions.h"
  9. namespace YAML {
  10. /**
  11. * @brief The DeepRecursion class
  12. * An exception class which is thrown by DepthGuard. Ideally it should be
  13. * a member of DepthGuard. However, DepthGuard is a templated class which means
  14. * that any catch points would then need to know the template parameters. It is
  15. * simpler for clients to not have to know at the catch point what was the
  16. * maximum depth.
  17. */
  18. class DeepRecursion : public ParserException {
  19. public:
  20. virtual ~DeepRecursion() = default;
  21. DeepRecursion(int depth, const Mark& mark_, const std::string& msg_);
  22. // Returns the recursion depth when the exception was thrown
  23. int depth() const {
  24. return m_depth;
  25. }
  26. private:
  27. int m_depth = 0;
  28. };
  29. /**
  30. * @brief The DepthGuard class
  31. * DepthGuard takes a reference to an integer. It increments the integer upon
  32. * construction of DepthGuard and decrements the integer upon destruction.
  33. *
  34. * If the integer would be incremented past max_depth, then an exception is
  35. * thrown. This is ideally geared toward guarding against deep recursion.
  36. *
  37. * @param max_depth
  38. * compile-time configurable maximum depth.
  39. */
  40. template <int max_depth = 2000>
  41. class DepthGuard final {
  42. public:
  43. DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) {
  44. ++m_depth;
  45. if ( max_depth <= m_depth ) {
  46. throw DeepRecursion{m_depth, mark_, msg_};
  47. }
  48. }
  49. DepthGuard(const DepthGuard & copy_ctor) = delete;
  50. DepthGuard(DepthGuard && move_ctor) = delete;
  51. DepthGuard & operator=(const DepthGuard & copy_assign) = delete;
  52. DepthGuard & operator=(DepthGuard && move_assign) = delete;
  53. ~DepthGuard() {
  54. --m_depth;
  55. }
  56. int current_depth() const {
  57. return m_depth;
  58. }
  59. private:
  60. int & m_depth;
  61. };
  62. } // namespace YAML
  63. #endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000