#ifndef TOML11_LOCATION_IMPL_HPP #define TOML11_LOCATION_IMPL_HPP #include "../fwd/location_fwd.hpp" #include "../utility.hpp" #include "../version.hpp" namespace toml { inline namespace TOML11_INLINE_VERSION_NAMESPACE { namespace detail { TOML11_INLINE void location::advance(std::size_t n) noexcept { assert(this->is_ok()); if(this->location_ + n < this->source_->size()) { this->advance_impl(n); } else { this->advance_impl(this->source_->size() - this->location_); assert(this->location_ == this->source_->size()); } } TOML11_INLINE void location::retrace(/*restricted to n=1*/) noexcept { assert(this->is_ok()); if(this->location_ == 0) { this->location_ = 0; this->line_number_ = 1; this->column_number_ = 1; } else { this->retrace_impl(); } } TOML11_INLINE bool location::eof() const noexcept { assert(this->is_ok()); return this->location_ >= this->source_->size(); } TOML11_INLINE location::char_type location::current() const { assert(this->is_ok()); if(this->eof()) {return '\0';} assert(this->location_ < this->source_->size()); return this->source_->at(this->location_); } TOML11_INLINE location::char_type location::peek() { assert(this->is_ok()); if(this->location_ >= this->source_->size()) { return '\0'; } else { return this->source_->at(this->location_ + 1); } } TOML11_INLINE std::string location::get_line() const { assert(this->is_ok()); const auto iter = std::next(this->source_->cbegin(), static_cast(this->location_)); const auto riter = cxx::make_reverse_iterator(iter); const auto prev = std::find(riter, this->source_->crend(), char_type('\n')); const auto next = std::find(iter, this->source_->cend(), char_type('\n')); return make_string(std::next(prev.base()), next); } TOML11_INLINE std::size_t location::calc_column_number() const noexcept { assert(this->is_ok()); const auto iter = std::next(this->source_->cbegin(), static_cast(this->location_)); const auto riter = cxx::make_reverse_iterator(iter); const auto prev = std::find(riter, this->source_->crend(), char_type('\n')); assert(prev.base() <= iter); return static_cast(std::distance(prev.base(), iter) + 1); // 1-origin } TOML11_INLINE void location::advance_impl(const std::size_t n) { assert(this->is_ok()); assert(this->location_ + n <= this->source_->size()); auto iter = this->source_->cbegin(); std::advance(iter, static_cast(this->location_)); for(std::size_t i=0; iline_number_ += 1; this->column_number_ = 1; } else { this->column_number_ += 1; } iter++; } this->location_ += n; return; } TOML11_INLINE void location::retrace_impl(/*n == 1*/) { assert(this->is_ok()); assert(this->location_ != 0); this->location_ -= 1; auto iter = this->source_->cbegin(); std::advance(iter, static_cast(this->location_)); if(*iter == '\n') { this->line_number_ -= 1; this->column_number_ = this->calc_column_number(); } return; } TOML11_INLINE bool operator==(const location& lhs, const location& rhs) noexcept { if( ! lhs.is_ok() || ! rhs.is_ok()) { return (!lhs.is_ok()) && (!rhs.is_ok()); } return lhs.source() == rhs.source() && lhs.source_name() == rhs.source_name() && lhs.get_location() == rhs.get_location(); } TOML11_INLINE bool operator!=(const location& lhs, const location& rhs) { return !(lhs == rhs); } TOML11_INLINE location prev(const location& loc) { location p(loc); p.retrace(); return p; } TOML11_INLINE location next(const location& loc) { location p(loc); p.advance(1); return p; } TOML11_INLINE location make_temporary_location(const std::string& str) noexcept { location::container_type cont(str.size()); std::transform(str.begin(), str.end(), cont.begin(), [](const std::string::value_type& c) { return cxx::bit_cast(c); }); return location(std::make_shared( std::move(cont)), "internal temporary"); } TOML11_INLINE result find(const location& first, const location& last, const location::char_type val) { return find_if(first, last, [val](const location::char_type c) { return c == val; }); } TOML11_INLINE result rfind(const location& first, const location& last, const location::char_type val) { return rfind_if(first, last, [val](const location::char_type c) { return c == val; }); } TOML11_INLINE std::size_t count(const location& first, const location& last, const location::char_type& c) { if(first.source() != last.source()) { return 0; } if(first.get_location() >= last.get_location()) { return 0; } auto loc = first; std::size_t num = 0; while(loc.get_location() != last.get_location()) { if(loc.current() == c) { num += 1; } loc.advance(); } return num; } } // detail } // TOML11_INLINE_VERSION_NAMESPACE } // toml #endif // TOML11_LOCATION_HPP