Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<iterator>: reduced parsing time #355

Merged
merged 1 commit into from
Dec 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 172 additions & 1 deletion stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define _ITERATOR_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <istream>
#include <iosfwd>
#include <xutility>

#pragma pack(push, _CRT_PACKING)
Expand Down Expand Up @@ -235,6 +235,177 @@ protected:
const _Elem* _Mydelim; // pointer to delimiter string (NB: not freed)
ostream_type* _Myostr; // pointer to output stream
};

// CLASS TEMPLATE istreambuf_iterator
template <class _Elem, class _Traits>
class istreambuf_iterator { // wrap stream buffer as input iterator
public:
using iterator_category = input_iterator_tag;
using value_type = _Elem;
using difference_type = typename _Traits::off_type;
using pointer = const _Elem*;
using reference = _Elem;

using char_type = _Elem;
using traits_type = _Traits;
using streambuf_type = basic_streambuf<_Elem, _Traits>;
using istream_type = basic_istream<_Elem, _Traits>;

using int_type = typename traits_type::int_type;

constexpr istreambuf_iterator() noexcept : _Strbuf(nullptr), _Got(true), _Val() {}

istreambuf_iterator(streambuf_type* _Sb) noexcept : _Strbuf(_Sb), _Got(!_Sb), _Val() {}

istreambuf_iterator(istream_type& _Istr) noexcept : _Strbuf(_Istr.rdbuf()), _Got(!_Strbuf), _Val() {}

private:
class _Istreambuf_proxy {
public:
_NODISCARD _Elem operator*() const {
return _Keep;
}

private:
friend istreambuf_iterator;
_Istreambuf_proxy(streambuf_type* _Strbuf_, _Elem _Keep_) : _Strbuf(_Strbuf_), _Keep(_Keep_) {}

streambuf_type* _Strbuf;
_Elem _Keep;
};

public:
istreambuf_iterator(const _Istreambuf_proxy& _Px) noexcept : _Strbuf(_Px._Strbuf), _Got(!_Strbuf), _Val() {}

_NODISCARD _Elem operator*() const {
if (!_Got) {
_Peek();
}

#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Strbuf, "istreambuf_iterator is not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

return _Val;
}

istreambuf_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Strbuf, "istreambuf_iterator is not incrementable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

_Inc();
return *this;
}

_Istreambuf_proxy operator++(int) {
if (!_Got) {
_Peek();
}

_Istreambuf_proxy _Tmp{_Strbuf, _Val};
++*this;
return _Tmp;
}

_NODISCARD bool equal(const istreambuf_iterator& _Right) const {
if (!_Got) {
_Peek();
}

if (!_Right._Got) {
_Right._Peek();
}

return (!_Strbuf && !_Right._Strbuf) || (_Strbuf && _Right._Strbuf);
}

private:
void _Inc() { // skip to next input element
if (!_Strbuf || traits_type::eq_int_type(traits_type::eof(), _Strbuf->sbumpc())) {
_Strbuf = nullptr;
_Got = true;
} else {
_Got = false;
}
}

_Elem _Peek() const { // peek at next input element
int_type _Meta;
if (!_Strbuf || traits_type::eq_int_type(traits_type::eof(), _Meta = _Strbuf->sgetc())) {
_Strbuf = nullptr;
} else {
_Val = traits_type::to_char_type(_Meta);
}

_Got = true;
return _Val;
}

mutable streambuf_type* _Strbuf; // the wrapped stream buffer
mutable bool _Got; // true if _Val is valid
mutable _Elem _Val; // next element to deliver
};

template <class _Elem, class _Traits>
_NODISCARD bool operator==(
const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) {
return _Left.equal(_Right);
}

template <class _Elem, class _Traits>
_NODISCARD bool operator!=(
const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) {
return !(_Left == _Right);
}

// CLASS TEMPLATE ostreambuf_iterator
template <class _Elem, class _Traits>
class ostreambuf_iterator { // wrap stream buffer as output iterator
public:
using iterator_category = output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;

using char_type = _Elem;
using traits_type = _Traits;
using streambuf_type = basic_streambuf<_Elem, _Traits>;
using ostream_type = basic_ostream<_Elem, _Traits>;

ostreambuf_iterator(streambuf_type* _Sb) noexcept : _Failed(false), _Strbuf(_Sb) {}

ostreambuf_iterator(ostream_type& _Ostr) noexcept : _Failed(false), _Strbuf(_Ostr.rdbuf()) {}

ostreambuf_iterator& operator=(_Elem _Right) { // store element and increment
if (!_Strbuf || traits_type::eq_int_type(_Traits::eof(), _Strbuf->sputc(_Right))) {
_Failed = true;
}

return *this;
}

_NODISCARD ostreambuf_iterator& operator*() { // pretend to get designated element
return *this;
}

ostreambuf_iterator& operator++() { // pretend to preincrement
return *this;
}

ostreambuf_iterator& operator++(int) { // pretend to postincrement
return *this;
}

_NODISCARD bool failed() const noexcept {
return _Failed;
}

private:
bool _Failed; // true if any stores have failed
streambuf_type* _Strbuf; // the wrapped stream buffer
};
_STD_END

_STDEXT_BEGIN
Expand Down
171 changes: 0 additions & 171 deletions stl/inc/streambuf
Original file line number Diff line number Diff line change
Expand Up @@ -409,177 +409,6 @@ template class _CRTIMP2_PURE_IMPORT basic_streambuf<wchar_t, char_traits<wchar_t
template class _CRTIMP2_PURE_IMPORT basic_streambuf<unsigned short, char_traits<unsigned short>>;
#endif // __FORCE_INSTANCE
#endif // defined(_DLL_CPPLIB)

// CLASS TEMPLATE istreambuf_iterator
template <class _Elem, class _Traits>
class istreambuf_iterator { // wrap stream buffer as input iterator
public:
using iterator_category = input_iterator_tag;
using value_type = _Elem;
using difference_type = typename _Traits::off_type;
using pointer = const _Elem*;
using reference = _Elem;

using char_type = _Elem;
using traits_type = _Traits;
using streambuf_type = basic_streambuf<_Elem, _Traits>;
using istream_type = basic_istream<_Elem, _Traits>;

using int_type = typename traits_type::int_type;

constexpr istreambuf_iterator() noexcept : _Strbuf(nullptr), _Got(true), _Val() {}

istreambuf_iterator(streambuf_type* _Sb) noexcept : _Strbuf(_Sb), _Got(!_Sb), _Val() {}

istreambuf_iterator(istream_type& _Istr) noexcept : _Strbuf(_Istr.rdbuf()), _Got(!_Strbuf), _Val() {}

private:
class _Istreambuf_proxy {
public:
_NODISCARD _Elem operator*() const {
return _Keep;
}

private:
friend istreambuf_iterator;
_Istreambuf_proxy(streambuf_type* _Strbuf_, _Elem _Keep_) : _Strbuf(_Strbuf_), _Keep(_Keep_) {}

streambuf_type* _Strbuf;
_Elem _Keep;
};

public:
istreambuf_iterator(const _Istreambuf_proxy& _Px) noexcept : _Strbuf(_Px._Strbuf), _Got(!_Strbuf), _Val() {}

_NODISCARD _Elem operator*() const {
if (!_Got) {
_Peek();
}

#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Strbuf, "istreambuf_iterator is not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

return _Val;
}

istreambuf_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Strbuf, "istreambuf_iterator is not incrementable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

_Inc();
return *this;
}

_Istreambuf_proxy operator++(int) {
if (!_Got) {
_Peek();
}

_Istreambuf_proxy _Tmp{_Strbuf, _Val};
++*this;
return _Tmp;
}

_NODISCARD bool equal(const istreambuf_iterator& _Right) const {
if (!_Got) {
_Peek();
}

if (!_Right._Got) {
_Right._Peek();
}

return (!_Strbuf && !_Right._Strbuf) || (_Strbuf && _Right._Strbuf);
}

private:
void _Inc() { // skip to next input element
if (!_Strbuf || traits_type::eq_int_type(traits_type::eof(), _Strbuf->sbumpc())) {
_Strbuf = nullptr;
_Got = true;
} else {
_Got = false;
}
}

_Elem _Peek() const { // peek at next input element
int_type _Meta;
if (!_Strbuf || traits_type::eq_int_type(traits_type::eof(), _Meta = _Strbuf->sgetc())) {
_Strbuf = nullptr;
} else {
_Val = traits_type::to_char_type(_Meta);
}

_Got = true;
return _Val;
}

mutable streambuf_type* _Strbuf; // the wrapped stream buffer
mutable bool _Got; // true if _Val is valid
mutable _Elem _Val; // next element to deliver
};

template <class _Elem, class _Traits>
_NODISCARD bool operator==(
const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) {
return _Left.equal(_Right);
}

template <class _Elem, class _Traits>
_NODISCARD bool operator!=(
const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) {
return !(_Left == _Right);
}

// CLASS TEMPLATE ostreambuf_iterator
template <class _Elem, class _Traits>
class ostreambuf_iterator { // wrap stream buffer as output iterator
public:
using iterator_category = output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;

using char_type = _Elem;
using traits_type = _Traits;
using streambuf_type = basic_streambuf<_Elem, _Traits>;
using ostream_type = basic_ostream<_Elem, _Traits>;

ostreambuf_iterator(streambuf_type* _Sb) noexcept : _Failed(false), _Strbuf(_Sb) {}

ostreambuf_iterator(ostream_type& _Ostr) noexcept : _Failed(false), _Strbuf(_Ostr.rdbuf()) {}

ostreambuf_iterator& operator=(_Elem _Right) { // store element and increment
if (!_Strbuf || traits_type::eq_int_type(_Traits::eof(), _Strbuf->sputc(_Right))) {
_Failed = true;
}

return *this;
}

_NODISCARD ostreambuf_iterator& operator*() { // pretend to get designated element
return *this;
}

ostreambuf_iterator& operator++() { // pretend to preincrement
return *this;
}

ostreambuf_iterator& operator++(int) { // pretend to postincrement
return *this;
}

_NODISCARD bool failed() const noexcept {
return _Failed;
}

private:
bool _Failed; // true if any stores have failed
streambuf_type* _Strbuf; // the wrapped stream buffer
};
_STD_END

#pragma pop_macro("new")
Expand Down
1 change: 1 addition & 0 deletions stl/inc/xlocmon
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define _XLOCMON_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <iterator>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including <iterator> is unnecessary in <xlocmon> and <xloctime>, and it's slightly inconsistent with the existing code that appears to treat <xlocnum> as central. However, I'm fine with this change. (STL headers are wildly inconsistent about assuming transitive inclusion, although we try to be very clean in our tests.)

#include <xlocnum>

#pragma pack(push, _CRT_PACKING)
Expand Down
1 change: 1 addition & 0 deletions stl/inc/xlocnum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iterator>
#include <streambuf>

#pragma pack(push, _CRT_PACKING)
Expand Down
1 change: 1 addition & 0 deletions stl/inc/xloctime
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <ctime>
#include <iterator>
#include <xlocnum>

#pragma pack(push, _CRT_PACKING)
Expand Down