From 2f6392f4b0c3cc6caffbfac0911dba99f5094887 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 18 Jun 2015 15:25:36 +0200 Subject: Add char-scanner to libbutl, use in libbpkg and build2 --- butl/char-scanner.cxx | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 butl/char-scanner.cxx (limited to 'butl/char-scanner.cxx') diff --git a/butl/char-scanner.cxx b/butl/char-scanner.cxx new file mode 100644 index 0000000..1561ad1 --- /dev/null +++ b/butl/char-scanner.cxx @@ -0,0 +1,78 @@ +// file : butl/char-scanner.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +using namespace std; + +namespace butl +{ + auto char_scanner:: + peek () -> xchar + { + if (unget_) + return buf_; + else + { + if (eos_) + return xchar (xchar::traits_type::eof (), line, column); + else + { + xchar::int_type v (is_.peek ()); + + if (v == xchar::traits_type::eof ()) + eos_ = true; + + return xchar (v, line, column); + } + } + } + + auto char_scanner:: + get () -> xchar + { + if (unget_) + { + unget_ = false; + return buf_; + } + else + { + // When is_.get () returns eof, the failbit is also set (stupid, + // isn't?) which may trigger an exception. To work around this + // we will call peek() first and only call get() if it is not + // eof. But we can only call peek() on eof once; any subsequent + // calls will spoil the failbit (even more stupid). + // + xchar c (peek ()); + + if (!eos (c)) + { + is_.get (); + + if (c == '\n') + { + line++; + column = 1; + } + else + column++; + } + + return c; + } + } + + void char_scanner:: + unget (const xchar& c) + { + // Because iostream::unget cannot work once eos is reached, + // we have to provide our own implementation. + // + buf_ = c; + unget_ = true; + } +} -- cgit v1.1