#ifndef NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif


namespace RIVET_YAML
{
	template <typename T, typename U>
	struct is_same_type {
		enum { value = false };
	};
	
	template <typename T>
	struct is_same_type<T, T> {
		enum { value = true };
	};
	
	template <typename T, bool check>
	struct is_index_type_with_check {
		enum { value = false };
	};
	
	template <> struct is_index_type_with_check<std::size_t, false> { enum { value = true }; };

#define MAKE_INDEX_TYPE(Type) \
	template <> struct is_index_type_with_check<Type, is_same_type<Type, std::size_t>::value> { enum { value = true }; }
	
	MAKE_INDEX_TYPE(int);
	MAKE_INDEX_TYPE(unsigned);
	MAKE_INDEX_TYPE(short);
	MAKE_INDEX_TYPE(unsigned short);
	MAKE_INDEX_TYPE(long);
	MAKE_INDEX_TYPE(unsigned long);

#undef MAKE_INDEX_TYPE
	
	template <typename T>
	struct is_index_type: public is_index_type_with_check<T, false> {};
	
	// messing around with template stuff to get the right overload for operator [] for a sequence
	template <typename T, bool b>
	struct _FindFromNodeAtIndex {
		const Node *pRet;
		_FindFromNodeAtIndex(const Node&, const T&): pRet(0) {}
	};

	template <typename T>
	struct _FindFromNodeAtIndex<T, true> {
		const Node *pRet;
		_FindFromNodeAtIndex(const Node& node, const T& key): pRet(node.FindAtIndex(static_cast<std::size_t>(key))) {}
	};

	template <typename T>
	inline const Node *FindFromNodeAtIndex(const Node& node, const T& key) {
		return _FindFromNodeAtIndex<T, is_index_type<T>::value>(node, key).pRet;
	}
}

#endif // NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
