|  | #ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 | 
|  | #define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 | 
|  |  | 
|  | #if defined(_MSC_VER) ||                                            \ | 
|  | (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ | 
|  | (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4 | 
|  | #pragma once | 
|  | #endif | 
|  |  | 
|  | #include "exceptions.h" | 
|  |  | 
|  | namespace YAML { | 
|  |  | 
|  | /** | 
|  | * @brief The DeepRecursion class | 
|  | *  An exception class which is thrown by DepthGuard. Ideally it should be | 
|  | * a member of DepthGuard. However, DepthGuard is a templated class which means | 
|  | * that any catch points would then need to know the template parameters. It is | 
|  | * simpler for clients to not have to know at the catch point what was the | 
|  | * maximum depth. | 
|  | */ | 
|  | class DeepRecursion : public ParserException { | 
|  | public: | 
|  | virtual ~DeepRecursion() = default; | 
|  |  | 
|  | DeepRecursion(int depth, const Mark& mark_, const std::string& msg_); | 
|  |  | 
|  | // Returns the recursion depth when the exception was thrown | 
|  | int depth() const { | 
|  | return m_depth; | 
|  | } | 
|  |  | 
|  | private: | 
|  | int m_depth = 0; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief The DepthGuard class | 
|  | *  DepthGuard takes a reference to an integer. It increments the integer upon | 
|  | * construction of DepthGuard and decrements the integer upon destruction. | 
|  | * | 
|  | * If the integer would be incremented past max_depth, then an exception is | 
|  | * thrown. This is ideally geared toward guarding against deep recursion. | 
|  | * | 
|  | * @param max_depth | 
|  | *  compile-time configurable maximum depth. | 
|  | */ | 
|  | template <int max_depth = 2000> | 
|  | class DepthGuard final { | 
|  | public: | 
|  | DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) { | 
|  | ++m_depth; | 
|  | if ( max_depth <= m_depth ) { | 
|  | throw DeepRecursion{m_depth, mark_, msg_}; | 
|  | } | 
|  | } | 
|  |  | 
|  | DepthGuard(const DepthGuard & copy_ctor) = delete; | 
|  | DepthGuard(DepthGuard && move_ctor) = delete; | 
|  | DepthGuard & operator=(const DepthGuard & copy_assign) = delete; | 
|  | DepthGuard & operator=(DepthGuard && move_assign) = delete; | 
|  |  | 
|  | ~DepthGuard() { | 
|  | --m_depth; | 
|  | } | 
|  |  | 
|  | int current_depth() const { | 
|  | return m_depth; | 
|  | } | 
|  |  | 
|  | private: | 
|  | int & m_depth; | 
|  | }; | 
|  |  | 
|  | } // namespace YAML | 
|  |  | 
|  | #endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 |