diff --git a/toml/region.hpp b/toml/region.hpp index 355c785..20bdda8 100644 --- a/toml/region.hpp +++ b/toml/region.hpp @@ -1,9 +1,9 @@ #ifndef TOML11_REGION_H #define TOML11_REGION_H +#include "exception.hpp" #include #include #include -#include namespace toml { @@ -18,19 +18,32 @@ struct location { static_assert(std::is_same::value,""); using const_iterator = typename Container::const_iterator; + using source_ptr = std::shared_ptr; location(Container cont) - : source(std::make_shared(std::move(cont))), - begin(source->cbegin()), iter(source->cbegin()), end(source->cend()) + : source_(std::make_shared(std::move(cont))), + begin_(source_->cbegin()), iter_(source_->cbegin()), + end_(source_->cend()) {} location(const location&) = default; location(location&&) = default; location& operator=(const location&) = default; location& operator=(location&&) = default; - ~location() = default; + ~location() = default; - std::shared_ptr source; - const_iterator begin, iter, end; + const_iterator& iter() noexcept {return iter_;} + const_iterator iter() const noexcept {return iter_;} + + const_iterator begin() const noexcept {return begin_;} + const_iterator end() const noexcept {return end_;} + + source_ptr const& source() const& noexcept {return source_;} + source_ptr&& source() && noexcept {return std::move(source_);} + + private: + + source_ptr source_; + const_iterator begin_, iter_, end_; }; // region in a container, normally in a file content. @@ -42,23 +55,24 @@ struct region { static_assert(std::is_same::value,""); using const_iterator = typename Container::const_iterator; + using source_ptr = std::shared_ptr; region(const location& loc) - : begin(loc.begin), first(loc.iter), last(loc.iter), end(loc.end), - source(loc.source) + : begin_(loc.begin()), first_(loc.iter()), + last_(loc.iter()), end_(loc.end()), source_(loc.source()) {} region(location&& loc) - : begin(loc.begin), first(loc.iter), last(loc.iter), end(loc.end), - source(std::move(loc.source)) + : begin_(loc.begin()), first_(loc.iter()), + last_(loc.iter()), end_(loc.end()), source_(std::move(loc.source())) {} region(const location& loc, const_iterator f, const_iterator l) - : begin(loc.begin), first(f), last(l), end(loc.end), - source(loc.source) + : begin_(loc.begin()), first_(f), last_(l), end_(loc.end()), + source_(loc.source()) {} region(location&& loc, const_iterator f, const_iterator l) - : begin(loc.begin), first(f), last(l), end(loc.end), - source(std::move(loc.source)) + : begin_(loc.begin()), first_(f), last_(l), end_(loc.end()), + source_(std::move(loc.source())) {} region(const region&) = default; @@ -67,11 +81,32 @@ struct region region& operator=(region&&) = default; ~region() = default; - std::string str() const {return std::string(first, last);} - std::size_t size() const {return std::distance(first, last);} + region& operator+=(const region& other) + { + if(this->begin_ != other.begin_ || this->end_ != other.end_ || + this->last_ != other.first_) + { + throw internal_error("invalid region concatenation"); + } + this->last_ = other.last_; + return *this; + } - const_iterator begin, first, last, end; - std::shared_ptr source; + std::string str() const {return std::string(first_, last_);} + std::size_t size() const {return std::distance(first_, last_);} + + const_iterator begin() const noexcept {return begin_;} + const_iterator end() const noexcept {return end_;} + const_iterator first() const noexcept {return first_;} + const_iterator last() const noexcept {return last_;} + + source_ptr const& source() const& noexcept {return source_;} + source_ptr&& source() && noexcept {return std::move(source_);} + + private: + + const_iterator begin_, first_, last_, end_; + source_ptr source_; }; // to show a better error message. @@ -82,13 +117,13 @@ format_underline(const region& reg, const std::string& msg) using const_iterator = typename region::const_iterator; using reverse_iterator = std::reverse_iterator; const auto line_begin = std::find( - reverse_iterator(reg.first), - reverse_iterator(reg.begin), + reverse_iterator(reg.first()), + reverse_iterator(reg.begin()), '\n').base(); - const auto line_end = std::find(reg.last, reg.end, '\n'); + const auto line_end = std::find(reg.last(), reg.end(), '\n'); const auto line_number = std::to_string( - 1 + std::count(reg.begin, reg.first, '\n')); + 1 + std::count(reg.begin(), reg.first(), '\n')); std::string retval; retval += ' '; @@ -98,8 +133,8 @@ format_underline(const region& reg, const std::string& msg) retval += '\n'; retval += std::string(line_number.size() + 1, ' '); retval += " | "; - retval += std::string(std::distance(line_begin, reg.first), ' '); - retval += std::string(std::distance(reg.first, reg.last), '~'); + retval += std::string(std::distance(line_begin, reg.first()), ' '); + retval += std::string(std::distance(reg.first(), reg.last()), '~'); retval += ' '; retval += msg; return retval; @@ -114,13 +149,13 @@ std::string format_underline(const region& reg, using const_iterator = typename region::const_iterator; using reverse_iterator = std::reverse_iterator; const auto line_begin = std::find( - reverse_iterator(reg.first), - reverse_iterator(reg.begin), + reverse_iterator(reg.first()), + reverse_iterator(reg.begin()), '\n').base(); - const auto line_end = std::find(reg.last, reg.end, '\n'); + const auto line_end = std::find(reg.last(), reg.end(), '\n'); const auto line_number = std::to_string( - 1 + std::count(reg.begin, reg.first, '\n')); + 1 + std::count(reg.begin(), reg.first(), '\n')); std::string retval; retval += ' '; @@ -130,16 +165,16 @@ std::string format_underline(const region& reg, retval += '\n'; retval += std::string(line_number.size() + 1, ' '); retval += " | "; - retval += std::string(std::distance(line_begin, reg.first), ' '); + retval += std::string(std::distance(line_begin, reg.first()), ' '); - if(std::distance(reg.first, std::prev(pos)) > 0) + if(std::distance(reg.first(), std::prev(pos)) > 0) { - retval += std::string(std::distance(reg.first, std::prev(pos)), '-'); + retval += std::string(std::distance(reg.first(), std::prev(pos)), '-'); } retval += '^'; - if(std::distance(pos, reg.last) > 0) + if(std::distance(pos, reg.last()) > 0) { - retval += std::string(std::distance(std::next(pos), reg.last), '-'); + retval += std::string(std::distance(std::next(pos), reg.last()), '-'); } retval += ' ';