Let the user give an error checking policy for invalid ranges.

This enables the user to use std::istream_iterator as the underlying iterator.
This commit is contained in:
King_DuckZ 2014-06-03 23:20:23 +02:00
parent a377c642ff
commit 73bd06b5d6

View file

@ -30,6 +30,7 @@ DEALINGS IN THE SOFTWARE.
#include "core.h" #include "core.h"
#include <stdexcept> #include <stdexcept>
#include <cassert>
namespace utf8 namespace utf8
{ {
@ -263,8 +264,52 @@ namespace utf8
return result; return result;
} }
// Error policies for the iterator class
template <typename I>
class ErrorPolicyThrow {
public:
static void check_in_range(const I& it, const I& range_start, const I& range_end)
{
if (it < range_start || it > range_end)
throw std::out_of_range("Invalid utf-8 iterator position");
}
static void check_same_range(const I& range_start_a, const I& range_start_b, const I& range_end_a, const I& range_end_b)
{
if (range_start_a != range_start_b || range_end_a != range_end_b)
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
}
};
template <typename I>
class ErrorPolicyAssert {
public:
static void check_in_range(const I& it, const I& range_start, const I& range_end)
{
#if defined(NDEBUG)
(void)it;
(void)range_start;
(void)range_end;
#else
assert(it >= range_start && it <= range_end);
#endif
}
static void check_same_range(const I& range_start_a, const I& range_start_b, const I& range_end_a, const I& range_end_b)
{
#if defined(NDEBUG)
(void)range_start_a;
(void)range_start_b;
(void)range_end_a;
(void)range_end_b;
#else
assert(range_start_a == range_start_b && range_end_a == range_end_b);
#endif
}
};
// The iterator class // The iterator class
template <typename octet_iterator> template <
typename octet_iterator,
typename error_policy=ErrorPolicyThrow<octet_iterator>
>
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
octet_iterator it; octet_iterator it;
octet_iterator range_start; octet_iterator range_start;
@ -276,8 +321,7 @@ namespace utf8
const octet_iterator& range_end) : const octet_iterator& range_end) :
it(octet_it), range_start(range_start), range_end(range_end) it(octet_it), range_start(range_start), range_end(range_end)
{ {
if (it < range_start || it > range_end) error_policy::check_in_range(it, range_start, range_end);
throw std::out_of_range("Invalid utf-8 iterator position");
} }
// the default "big three" are OK // the default "big three" are OK
octet_iterator base () const { return it; } octet_iterator base () const { return it; }
@ -288,8 +332,7 @@ namespace utf8
} }
bool operator == (const iterator& rhs) const bool operator == (const iterator& rhs) const
{ {
if (range_start != rhs.range_start || range_end != rhs.range_end) error_policy::check_same_range(range_start, rhs.range_start, range_end, rhs.range_end);
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
return (it == rhs.it); return (it == rhs.it);
} }
bool operator != (const iterator& rhs) const bool operator != (const iterator& rhs) const
@ -323,5 +366,3 @@ namespace utf8
} // namespace utf8 } // namespace utf8
#endif //header guard #endif //header guard