78 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			78 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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
 |