// file : libbutl/char-scanner.ixx -*- C++ -*- // license : MIT; see accompanying LICENSE file namespace butl { template inline char_scanner:: char_scanner (std::istream& is, bool crlf, std::uint64_t l, std::uint64_t c, std::uint64_t p) : char_scanner (is, validator_type (), crlf, l, c, p) { } template inline auto char_scanner:: peek (std::string& what) -> xchar { return peek (&what); } template inline auto char_scanner:: peek () -> xchar { return peek (nullptr /* what */); } template inline auto char_scanner:: get (std::string* what) -> xchar { if (ungetn_ != 0) return ungetb_[--ungetn_]; else { xchar c (peek (what)); get (c); return c; } } template inline auto char_scanner:: get (std::string& what) -> xchar { return get (&what); } template inline auto char_scanner:: get () -> xchar { return get (nullptr /* what */); } template inline void char_scanner:: unget (const xchar& c) { // Because iostream::unget cannot work once eos is reached, we have to // provide our own implementation. // assert (ungetn_ != N); // Make sure the buffer is not filled. ungetb_[ungetn_++] = c; } template inline auto char_scanner:: peek_ () -> int_type { if (gptr_ != egptr_) return *gptr_; int_type r (is_.peek ()); // Update buffer pointers for the next chunk. // if (buf_ != nullptr) { gptr_ = buf_->gptr (); egptr_ = buf_->egptr (); } return r; } template inline void char_scanner:: get_ () { int_type c; if (gptr_ != egptr_) { buf_->gbump (1); c = *gptr_++; } else c = is_.get (); // About as fast as ignore() and way faster than tellg(). validated_ = false; if (save_ != nullptr && c != xchar::traits_type::eof ()) save_->push_back (static_cast (c)); } template inline std::uint64_t char_scanner:: pos_ () const { return buf_ != nullptr ? buf_->tellg () : 0; } }