213 lines
5.4 KiB
C++
213 lines
5.4 KiB
C++
#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<difference_type>(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<difference_type>(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::size_t>(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<difference_type>(this->location_));
|
|
|
|
for(std::size_t i=0; i<n; ++i)
|
|
{
|
|
const auto c = *iter;
|
|
if(c == char_type('\n'))
|
|
{
|
|
this->line_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<difference_type>(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<location::char_type>(c);
|
|
});
|
|
return location(std::make_shared<const location::container_type>(
|
|
std::move(cont)), "internal temporary");
|
|
}
|
|
|
|
TOML11_INLINE result<location, none_t>
|
|
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<location, none_t>
|
|
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
|