mirror of
https://github.com/ToruNiina/toml11.git
synced 2024-11-23 04:40:06 +00:00
add region and location to represent tokens
location is almost same as an Iterator, but having shared_ptr that points the content. region is almost same as a range. by adding pointer to the content source, utility function to show the error message can be implemented easier. it is expected that this also makes easy to show error messages after parse (e.g., in the case of bad_get)
This commit is contained in:
parent
4791088106
commit
c38b9b7dc7
136
toml/region.hpp
Normal file
136
toml/region.hpp
Normal file
@ -0,0 +1,136 @@
|
||||
#ifndef TOML11_REGION_H
|
||||
#define TOML11_REGION_H
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace toml
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// location in a container, normally in a file content.
|
||||
// shared_ptr points the resource that the iter points.
|
||||
// it can be used not only for resource handling, but also error message.
|
||||
template<typename Container>
|
||||
struct location
|
||||
{
|
||||
using const_iterator = typename Container::const_iterator;
|
||||
|
||||
location(Container cont)
|
||||
: source(std::make_shared<Container>(std::move(cont))),
|
||||
iter(source->begin())
|
||||
{}
|
||||
location(const location&) = default;
|
||||
location(location&&) = default;
|
||||
location& operator=(const location&) = default;
|
||||
location& operator=(location&&) = default;
|
||||
~location() = default;
|
||||
|
||||
std::shared_ptr<Container> source;
|
||||
const_iterator iter;
|
||||
};
|
||||
|
||||
// region in a container, normally in a file content.
|
||||
// shared_ptr points the resource that the iter points.
|
||||
// combinators returns this.
|
||||
// it can be used not only for resource handling, but also error message.
|
||||
template<typename Container>
|
||||
struct region
|
||||
{
|
||||
using const_iterator = typename Container::const_iterator;
|
||||
|
||||
region(const location<Container>& loc)
|
||||
: first(loc.iter), last(loc.iter), source(loc.source)
|
||||
{}
|
||||
region(location<Container>&& loc)
|
||||
: first(loc.iter), last(loc.iter), source(std::move(loc.source))
|
||||
{}
|
||||
|
||||
region(const region&) = default;
|
||||
region(region&&) = default;
|
||||
region& operator=(const region&) = default;
|
||||
region& operator=(region&&) = default;
|
||||
~region() = default;
|
||||
|
||||
const_iterator first, last;
|
||||
std::shared_ptr<Container> source;
|
||||
};
|
||||
|
||||
// to show a better error message.
|
||||
template<typename Container>
|
||||
std::string
|
||||
format_underline(const region<Container>& reg, const std::string& msg)
|
||||
{
|
||||
using const_iterator = typename region<Container>::const_iterator;
|
||||
using reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
const auto line_begin = std::find(
|
||||
reverse_iterator(reg.first),
|
||||
reverse_iterator(reg.source->cbegin()),
|
||||
'\n').base();
|
||||
const auto line_end = std::find(reg.last, reg.source->cend(), '\n');
|
||||
|
||||
const auto line_number = std::to_string(
|
||||
1 + std::count(reg.source->cbegin(), reg.first, '\n'));
|
||||
|
||||
std::string retval;
|
||||
retval += ' ';
|
||||
retval += line_number;
|
||||
retval += " | ";
|
||||
retval += std::string(line_begin, line_end);
|
||||
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 += ' ';
|
||||
retval += msg;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// to show a better error message.
|
||||
template<typename Container>
|
||||
std::string format_underline(const region<Container>& reg,
|
||||
typename Container::const_iterator pos,
|
||||
const std::string& msg)
|
||||
{
|
||||
using const_iterator = typename region<Container>::const_iterator;
|
||||
using reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
const auto line_begin = std::find(
|
||||
reverse_iterator(reg.first),
|
||||
reverse_iterator(reg.source->cbegin()),
|
||||
'\n').base();
|
||||
const auto line_end = std::find(reg.last, reg.source->cend(), '\n');
|
||||
|
||||
const auto line_number = std::to_string(
|
||||
1 + std::count(reg.source->cbegin(), reg.first, '\n'));
|
||||
|
||||
std::string retval;
|
||||
retval += ' ';
|
||||
retval += line_number;
|
||||
retval += " | ";
|
||||
retval += std::string(line_begin, line_end);
|
||||
retval += '\n';
|
||||
retval += std::string(line_number.size() + 1, ' ');
|
||||
retval += " | ";
|
||||
retval += std::string(std::distance(line_begin, reg.first), ' ');
|
||||
|
||||
if(std::distance(reg.first, std::prev(pos)) > 0)
|
||||
{
|
||||
retval += std::string(std::distance(reg.first, std::prev(pos)), '-');
|
||||
}
|
||||
retval += '^';
|
||||
if(std::distance(pos, reg.last) > 0)
|
||||
{
|
||||
retval += std::string(std::distance(std::next(pos), reg.last), '-');
|
||||
}
|
||||
|
||||
retval += ' ';
|
||||
retval += msg;
|
||||
return retval;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // toml
|
||||
#endif// TOML11_REGION_H
|
Loading…
Reference in New Issue
Block a user