mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-18 19:10:11 +08:00
152 lines
4.6 KiB
C++
152 lines
4.6 KiB
C++
#ifndef TOML11_REGION_IMPL_HPP
|
|
#define TOML11_REGION_IMPL_HPP
|
|
|
|
#include "../fwd/region_fwd.hpp"
|
|
#include "../utility.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <cassert>
|
|
|
|
namespace toml
|
|
{
|
|
namespace detail
|
|
{
|
|
|
|
// a value defined in [first, last).
|
|
// Those source must be the same. Instread, `region` does not make sense.
|
|
TOML11_INLINE region::region(const location& first, const location& last)
|
|
: source_(first.source()), source_name_(first.source_name()),
|
|
length_(last.get_location() - first.get_location()),
|
|
first_(first.get_location()),
|
|
first_line_(first.line_number()),
|
|
first_column_(first.column_number()),
|
|
last_(last.get_location()),
|
|
last_line_(last.line_number()),
|
|
last_column_(last.column_number())
|
|
{
|
|
assert(first.source() == last.source());
|
|
assert(first.source_name() == last.source_name());
|
|
}
|
|
|
|
// shorthand of [loc, loc+1)
|
|
TOML11_INLINE region::region(const location& loc)
|
|
: source_(loc.source()), source_name_(loc.source_name()), length_(0),
|
|
first_line_(0), first_column_(0), last_line_(0), last_column_(0)
|
|
{
|
|
// if the file ends with LF, the resulting region points no char.
|
|
if(loc.eof())
|
|
{
|
|
if(loc.get_location() == 0)
|
|
{
|
|
this->length_ = 0;
|
|
this->first_ = 0;
|
|
this->first_line_ = 0;
|
|
this->first_column_ = 0;
|
|
this->last_ = 0;
|
|
this->last_line_ = 0;
|
|
this->last_column_ = 0;
|
|
}
|
|
else
|
|
{
|
|
const auto first = prev(loc);
|
|
this->first_ = first.get_location();
|
|
this->first_line_ = first.line_number();
|
|
this->first_column_ = first.column_number();
|
|
this->last_ = loc.get_location();
|
|
this->last_line_ = loc.line_number();
|
|
this->last_column_ = loc.column_number();
|
|
this->length_ = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->first_ = loc.get_location();
|
|
this->first_line_ = loc.line_number();
|
|
this->first_column_ = loc.column_number();
|
|
this->last_ = loc.get_location() + 1;
|
|
this->last_line_ = loc.line_number();
|
|
this->last_column_ = loc.column_number() + 1;
|
|
this->length_ = 1;
|
|
}
|
|
}
|
|
|
|
TOML11_INLINE region::char_type region::at(std::size_t i) const
|
|
{
|
|
if(this->last_ <= this->first_ + i)
|
|
{
|
|
throw std::out_of_range("range::at: index " + std::to_string(i) +
|
|
" exceeds length " + std::to_string(this->length_));
|
|
}
|
|
const auto iter = std::next(this->source_->cbegin(),
|
|
static_cast<difference_type>(this->first_ + i));
|
|
return *iter;
|
|
}
|
|
|
|
TOML11_INLINE region::const_iterator region::begin() const noexcept
|
|
{
|
|
return std::next(this->source_->cbegin(),
|
|
static_cast<difference_type>(this->first_));
|
|
}
|
|
TOML11_INLINE region::const_iterator region::end() const noexcept
|
|
{
|
|
return std::next(this->source_->cbegin(),
|
|
static_cast<difference_type>(this->last_));
|
|
}
|
|
TOML11_INLINE region::const_iterator region::cbegin() const noexcept
|
|
{
|
|
return std::next(this->source_->cbegin(),
|
|
static_cast<difference_type>(this->first_));
|
|
}
|
|
TOML11_INLINE region::const_iterator region::cend() const noexcept
|
|
{
|
|
return std::next(this->source_->cbegin(),
|
|
static_cast<difference_type>(this->last_));
|
|
}
|
|
|
|
TOML11_INLINE std::string region::as_string() const
|
|
{
|
|
if(this->is_ok())
|
|
{
|
|
const auto begin = std::next(this->source_->cbegin(), static_cast<difference_type>(this->first_));
|
|
const auto end = std::next(this->source_->cbegin(), static_cast<difference_type>(this->last_ ));
|
|
return ::toml::detail::make_string(begin, end);
|
|
}
|
|
else
|
|
{
|
|
return std::string("");
|
|
}
|
|
}
|
|
|
|
TOML11_INLINE std::vector<std::string> region::as_lines() const
|
|
{
|
|
assert(this->is_ok());
|
|
if(this->length_ == 0)
|
|
{
|
|
return {""};
|
|
}
|
|
|
|
const auto begin = std::next(this->source_->cbegin(), static_cast<difference_type>(this->first_));
|
|
const auto end = std::next(this->source_->cbegin(), static_cast<difference_type>(this->last_ ));
|
|
|
|
const auto line_begin = std::find(cxx::make_reverse_iterator(begin), this->source_->crend(), char_type('\n'));
|
|
const auto line_end = std::find(end, this->source_->cend(), char_type('\n'));
|
|
|
|
std::istringstream iss(make_string(line_begin.base(), line_end));
|
|
|
|
std::vector<std::string> lines;
|
|
std::string line;
|
|
while(std::getline(iss, line))
|
|
{
|
|
lines.push_back(line);
|
|
}
|
|
return lines;
|
|
}
|
|
|
|
} // namespace detail
|
|
} // namespace toml
|
|
#endif // TOML11_REGION_IMPL_HPP
|