From bbf510d6cc7fe803f35fc354b6d218031c37dae3 Mon Sep 17 00:00:00 2001 From: jbeder Date: Thu, 12 Nov 2009 17:00:12 +0000 Subject: [PATCH] Refactored the traits a bit, and added displaying the key to string and numeric key not found errors --- include/conversion.h | 29 ++----------------------- include/exceptions.h | 30 ++++++++++++++++++++------ include/traits.h | 50 ++++++++++++++++++++++++++++++++++++++++++++ test/parsertests.cpp | 35 ++++++++++++++++++++++++++++++- 4 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 include/traits.h diff --git a/include/conversion.h b/include/conversion.h index 4cb0803..13add1c 100644 --- a/include/conversion.h +++ b/include/conversion.h @@ -5,6 +5,7 @@ #include "null.h" +#include "traits.h" #include #include @@ -18,34 +19,8 @@ namespace YAML bool Convert(const std::string& input, bool& output); bool Convert(const std::string& input, _Null& output); - template - struct is_numeric { enum { value = false }; }; - - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - template <> struct is_numeric { enum { value = true }; }; - - - template - struct enable_if; - - template - struct enable_if { - typedef R type; - }; - template - inline bool Convert(const std::string& input, T& output, typename enable_if, T>::type * = 0) { + inline bool Convert(const std::string& input, T& output, typename enable_if >::type * = 0) { std::stringstream stream(input); stream.unsetf(std::ios::dec); return stream >> output; diff --git a/include/exceptions.h b/include/exceptions.h index 2a9c1d1..f81db59 100644 --- a/include/exceptions.h +++ b/include/exceptions.h @@ -5,6 +5,7 @@ #include "mark.h" +#include "traits.h" #include #include #include @@ -67,6 +68,22 @@ namespace YAML const std::string EXPECTED_VALUE_TOKEN = "expected value token"; const std::string UNEXPECTED_KEY_TOKEN = "unexpected key token"; const std::string UNEXPECTED_VALUE_TOKEN = "unexpected value token"; + + template + inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if >::type * = 0) { + return KEY_NOT_FOUND; + } + + inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { + return KEY_NOT_FOUND + ": " + key; + } + + template + inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if >::type * = 0) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); + } } class Exception: public std::exception { @@ -108,22 +125,23 @@ namespace YAML class KeyNotFound: public RepresentationException { public: - KeyNotFound(const Mark& mark_) - : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND) {} + template + KeyNotFound(const Mark& mark_, const T& key_) + : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {} }; - + template class TypedKeyNotFound: public KeyNotFound { public: TypedKeyNotFound(const Mark& mark_, const T& key_) - : KeyNotFound(mark_), key(key_) {} - ~TypedKeyNotFound() throw() {} + : KeyNotFound(mark_, key_), key(key_) {} + virtual ~TypedKeyNotFound() throw() {} T key; }; template - TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, const T& key) { + inline TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, const T& key) { return TypedKeyNotFound (mark, key); } diff --git a/include/traits.h b/include/traits.h new file mode 100644 index 0000000..46db01b --- /dev/null +++ b/include/traits.h @@ -0,0 +1,50 @@ +#pragma once + +#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + + +namespace YAML +{ + template + struct is_numeric { enum { value = false }; }; + + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + template <> struct is_numeric { enum { value = true }; }; + + template + struct enable_if_c { + typedef T type; + }; + + template + struct enable_if_c {}; + + template + struct enable_if : public enable_if_c {}; + + template + struct disable_if_c { + typedef T type; + }; + + template + struct disable_if_c {}; + + template + struct disable_if : public disable_if_c {}; +} + +#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/test/parsertests.cpp b/test/parsertests.cpp index 6bf8642..d30ed02 100644 --- a/test/parsertests.cpp +++ b/test/parsertests.cpp @@ -657,6 +657,38 @@ namespace Test return false; return true; } + + bool KeyNotFound() + { + std::string input = "key: value"; + std::stringstream stream(input); + YAML::Parser parser(stream); + YAML::Node doc; + parser.GetNextDocument(doc); + + try { + doc["bad key"]; + } catch(const YAML::Exception& e) { + if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": bad key") + throw; + } + + try { + doc[5]; + } catch(const YAML::Exception& e) { + if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": 5") + throw; + } + + try { + doc[2.5]; + } catch(const YAML::Exception& e) { + if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": 2.5") + throw; + } + + return true; + } } namespace { @@ -674,7 +706,7 @@ namespace Test doc >> output; } catch(const YAML::Exception& e) { ok = false; - error = e.msg; + error = e.what(); } if(ok && output == desiredOutput) { passed++; @@ -918,6 +950,7 @@ namespace Test RunParserTest(&Parser::MultipleDocsWithSomeExplicitIndicators, "multiple docs with some explicit indicators", passed, total); RunParserTest(&Parser::BlockKeyWithNullValue, "block key with null value", passed, total); RunParserTest(&Parser::Bases, "bases", passed, total); + RunParserTest(&Parser::KeyNotFound, "key not found", passed, total); RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed, total); RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed, total);