#ifndef TOML11_REGION_H #define TOML11_REGION_H #include #include #include #include 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 struct location { using const_iterator = typename Container::const_iterator; location(Container cont) : source(std::make_shared(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 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 struct region { using const_iterator = typename Container::const_iterator; region(const location& loc) : first(loc.iter), last(loc.iter), source(loc.source) {} region(location&& 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 source; }; // to show a better error message. template std::string 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.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 std::string format_underline(const region& reg, typename Container::const_iterator pos, 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.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