Skip to content

Commit b16db81

Browse files
committed
iterator: move distance method into input iterator
1 parent 34ccc8c commit b16db81

File tree

4 files changed

+35
-70
lines changed

4 files changed

+35
-70
lines changed

include/chen/base/iterator.hpp

Lines changed: 28 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ namespace chen
7474
virtual Reference operator*() const = 0;
7575
virtual void operator++() = 0;
7676
virtual bool operator==(const base &o) const = 0;
77+
virtual Distance distance() const = 0;
7778
};
7879

7980
/**
@@ -90,6 +91,12 @@ namespace chen
9091
virtual Reference operator*() const = 0;
9192
virtual void operator++() = 0;
9293
virtual bool operator==(const base &o) const = 0;
94+
virtual Distance distance() const
95+
{
96+
// only valid in input iterator
97+
// use std::distance in other iterators
98+
return 0;
99+
}
93100

94101
public:
95102
virtual void operator--() = 0;
@@ -109,6 +116,12 @@ namespace chen
109116
virtual Reference operator*() const = 0;
110117
virtual void operator++() = 0;
111118
virtual bool operator==(const base &o) const = 0;
119+
virtual Distance distance() const
120+
{
121+
// only valid in input iterator
122+
// use std::distance in other iterators
123+
return 0;
124+
}
112125

113126
public:
114127
virtual void operator--() = 0;
@@ -157,6 +170,7 @@ namespace chen
157170
virtual void operator++() override
158171
{
159172
++this->_it;
173+
++this->_distance;
160174
}
161175

162176
virtual bool operator==(const super_class &o) const override
@@ -165,8 +179,14 @@ namespace chen
165179
return this->_it == tmp._it;
166180
}
167181

182+
virtual Distance distance() const override
183+
{
184+
return this->_distance;
185+
}
186+
168187
protected:
169188
Iterator _it;
189+
Distance _distance = 0;
170190
};
171191

172192
/**
@@ -371,6 +391,14 @@ namespace chen
371391
return !(*this == o);
372392
}
373393

394+
Distance distance() const
395+
{
396+
// since input iterator is single-pass, we can't use std::distance on it
397+
// however, in some cases we want to know input iterator's position, so I add this method
398+
// @caution don't use this method if your category is not input iterator
399+
return this->_ptr->distance();
400+
}
401+
374402
/**
375403
* Bidirectional iterator
376404
*/
@@ -459,67 +487,4 @@ namespace chen
459487

460488
template<typename Value, typename Reference = Value&, typename Pointer = Value*, typename Distance = std::ptrdiff_t>
461489
using random_iterator = iterator<std::random_access_iterator_tag, Value, Reference, Pointer, Distance>;
462-
463-
/**
464-
* Position iterator
465-
* since input iterator is single-pass, we can't use std::distance on it
466-
* however, in some cases we want to know input iterator's position, so I add this iterator
467-
*/
468-
template <typename Value, typename Reference = Value&, typename Pointer = Value*, typename Distance = std::ptrdiff_t>
469-
class position_iterator : public input_iterator<Value, Reference, Pointer, Distance>
470-
{
471-
public:
472-
typedef input_iterator<Value, Reference, Pointer, Distance> super_class;
473-
474-
using typename super_class::value_type;
475-
using typename super_class::difference_type;
476-
using typename super_class::pointer;
477-
using typename super_class::reference;
478-
using typename super_class::iterator_category;
479-
using typename super_class::data_type;
480-
481-
public:
482-
/**
483-
* Construct by proxy
484-
*/
485-
position_iterator(const iterator_helper::proxy<Value, data_type> &p) : super_class(p)
486-
{
487-
}
488-
489-
/**
490-
* Wrap another iterator
491-
*/
492-
template <typename Iterator>
493-
position_iterator(Iterator it) : super_class(it)
494-
{
495-
}
496-
497-
public:
498-
/**
499-
* Current position after increment
500-
*/
501-
Distance distance() const
502-
{
503-
return this->_distance;
504-
}
505-
506-
public:
507-
/**
508-
* Input & Forward iterator
509-
*/
510-
super_class& operator++()
511-
{
512-
++this->_distance;
513-
return super_class::operator++();
514-
}
515-
516-
iterator_helper::proxy<Value, data_type> operator++(int)
517-
{
518-
++this->_distance; // don't effect on proxy
519-
return super_class::operator++(0);
520-
}
521-
522-
private:
523-
Distance _distance = 0;
524-
};
525490
}

include/chen/data/ini.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace chen
3131
class ini
3232
{
3333
public:
34-
typedef chen::position_iterator<const char, const char> iterator; // it's a input iterator
34+
typedef chen::input_iterator<const char, const char> iterator; // it's an input iterator
3535

3636
typedef std::unordered_map<std::string, std::string> property_type; // k/v pair
3737
typedef std::pair<std::string, property_type> section_type; // each section

include/chen/data/json.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace chen
3333
class json
3434
{
3535
public:
36-
typedef chen::input_iterator<const char, const char> iterator;
36+
typedef chen::input_iterator<const char, const char> iterator; // it's an input iterator
3737

3838
typedef std::unordered_map<std::string, chen::json> object;
3939
typedef std::vector<chen::json> array;

src/data/json.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ void chen::json::exception(const iterator &beg, iterator &cur, iterator &end)
799799
}
800800
else
801801
{
802-
auto pos = chen::num::str(std::distance(beg, cur));
802+
auto pos = chen::num::str(cur.distance());
803803
auto tok = std::isprint(*cur) ? std::string(1, *cur) : chen::str::format("\\x%02x", static_cast<int>(*cur));
804804

805805
throw chen::json::error(chen::str::format("json: unexpected token '%s' at position %s", tok.c_str(), pos.c_str()));
@@ -1076,12 +1076,12 @@ void chen::json::decode(double &out, const iterator &beg, iterator &cur, iterato
10761076

10771077
if (std::isinf(d))
10781078
{
1079-
auto pos = chen::num::str(std::distance(beg, cur) - str.size());
1079+
auto pos = chen::num::str(cur.distance() - str.size());
10801080
throw chen::json::error(chen::str::format("json: number '%s' is overflow at position %s", str.c_str(), pos.c_str()));
10811081
}
10821082
else if (std::isnan(d))
10831083
{
1084-
auto pos = chen::num::str(std::distance(beg, cur) - str.size());
1084+
auto pos = chen::num::str(cur.distance() - str.size());
10851085
throw chen::json::error(chen::str::format("json: number '%s' is invalid at position %s", str.c_str(), pos.c_str()));
10861086
}
10871087

@@ -1100,7 +1100,7 @@ void chen::json::decode(std::string &out, const iterator &beg, iterator &cur, it
11001100
// control characters must use escape
11011101
if ((ch >= 0) && (ch <= 31)) // see ASCII
11021102
{
1103-
auto pos = chen::num::str(std::distance(beg, cur));
1103+
auto pos = chen::num::str(cur.distance());
11041104
throw chen::json::error(chen::str::format("json: control character code '%d' is not escaped at position %s", static_cast<int>(ch), pos.c_str()));
11051105
}
11061106

@@ -1167,7 +1167,7 @@ void chen::json::decode(std::string &out, const iterator &beg, iterator &cur, it
11671167
catch (...)
11681168
{
11691169
// e.g: \uD83D\uDE00, it's a emoji character
1170-
auto pos = chen::num::str(std::distance(beg, cur) - 4);
1170+
auto pos = chen::num::str(cur.distance() - 4);
11711171
throw chen::json::error(chen::str::format("json: invalid unicode char '\\u%s' at position %s", unicode, pos.c_str()));
11721172
}
11731173
}

0 commit comments

Comments
 (0)