Mercurial > minori
view dep/toml11/toml/source_location.hpp @ 337:a7d4e5107531
dep/animone: REFACTOR ALL THE THINGS
1: animone now has its own syntax divergent from anisthesia,
making different platforms actually have their own sections
2: process names in animone are now called `comm' (this will
probably break things). this is what its called in bsd/linux
so I'm just going to use it everywhere
3: the X11 code now checks for the existence of a UTF-8 window title
and passes it if available
4: ANYTHING THATS NOT LINUX IS 100% UNTESTED AND CAN AND WILL BREAK!
I still actually need to test the bsd code. to be honest I'm probably
going to move all of the bsds into separate files because they're
all essentially different operating systems at this point
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 19 Jun 2024 12:51:15 -0400 |
parents | 3b355fa948c7 |
children |
line wrap: on
line source
// Copyright Toru Niina 2019. // Distributed under the MIT License. #ifndef TOML11_SOURCE_LOCATION_HPP #define TOML11_SOURCE_LOCATION_HPP #include <cstdint> #include <sstream> #include "region.hpp" namespace toml { // A struct to contain location in a toml file. // The interface imitates std::experimental::source_location, // but not completely the same. // // It would be constructed by toml::value. It can be used to generate // user-defined error messages. // // - std::uint_least32_t line() const noexcept // - returns the line number where the region is on. // - std::uint_least32_t column() const noexcept // - returns the column number where the region starts. // - std::uint_least32_t region() const noexcept // - returns the size of the region. // // +-- line() +-- region of interest (region() == 9) // v .---+---. // 12 | value = "foo bar" // ^ // +-- column() // // - std::string const& file_name() const noexcept; // - name of the file. // - std::string const& line_str() const noexcept; // - the whole line that contains the region of interest. // struct source_location { public: source_location() : line_num_(1), column_num_(1), region_size_(1), file_name_("unknown file"), line_str_("") {} explicit source_location(const detail::region_base* reg) : line_num_(1), column_num_(1), region_size_(1), file_name_("unknown file"), line_str_("") { if(reg) { if(reg->line_num() != detail::region_base().line_num()) { line_num_ = static_cast<std::uint_least32_t>( std::stoul(reg->line_num())); } column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1); region_size_ = static_cast<std::uint_least32_t>(reg->size()); file_name_ = reg->name(); line_str_ = reg->line(); } } explicit source_location(const detail::region& reg) : line_num_(static_cast<std::uint_least32_t>(std::stoul(reg.line_num()))), column_num_(static_cast<std::uint_least32_t>(reg.before() + 1)), region_size_(static_cast<std::uint_least32_t>(reg.size())), file_name_(reg.name()), line_str_ (reg.line()) {} explicit source_location(const detail::location& loc) : line_num_(static_cast<std::uint_least32_t>(std::stoul(loc.line_num()))), column_num_(static_cast<std::uint_least32_t>(loc.before() + 1)), region_size_(static_cast<std::uint_least32_t>(loc.size())), file_name_(loc.name()), line_str_ (loc.line()) {} ~source_location() = default; source_location(source_location const&) = default; source_location(source_location &&) = default; source_location& operator=(source_location const&) = default; source_location& operator=(source_location &&) = default; std::uint_least32_t line() const noexcept {return line_num_;} std::uint_least32_t column() const noexcept {return column_num_;} std::uint_least32_t region() const noexcept {return region_size_;} std::string const& file_name() const noexcept {return file_name_;} std::string const& line_str() const noexcept {return line_str_;} private: std::uint_least32_t line_num_; std::uint_least32_t column_num_; std::uint_least32_t region_size_; std::string file_name_; std::string line_str_; }; namespace detail { // internal error message generation. inline std::string format_underline(const std::string& message, const std::vector<std::pair<source_location, std::string>>& loc_com, const std::vector<std::string>& helps = {}, const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED) { std::size_t line_num_width = 0; for(const auto& lc : loc_com) { std::uint_least32_t line = lc.first.line(); std::size_t digit = 0; while(line != 0) { line /= 10; digit += 1; } line_num_width = (std::max)(line_num_width, digit); } // 1 is the minimum width line_num_width = std::max<std::size_t>(line_num_width, 1); std::ostringstream retval; if(color::should_color() || colorize) { retval << color::colorize; // turn on ANSI color } // XXX // Here, before `colorize` support, it does not output `[error]` prefix // automatically. So some user may output it manually and this change may // duplicate the prefix. To avoid it, check the first 7 characters and // if it is "[error]", it removes that part from the message shown. if(message.size() > 7 && message.substr(0, 7) == "[error]") { retval #ifndef TOML11_NO_ERROR_PREFIX << color::bold << color::red << "[error]" << color::reset #endif << color::bold << message.substr(7) << color::reset << '\n'; } else { retval #ifndef TOML11_NO_ERROR_PREFIX << color::bold << color::red << "[error] " << color::reset #endif << color::bold << message << color::reset << '\n'; } const auto format_one_location = [line_num_width] (std::ostringstream& oss, const source_location& loc, const std::string& comment) -> void { oss << ' ' << color::bold << color::blue << std::setw(static_cast<int>(line_num_width)) << std::right << loc.line() << " | " << color::reset << loc.line_str() << '\n'; oss << make_string(line_num_width + 1, ' ') << color::bold << color::blue << " | " << color::reset << make_string(loc.column()-1 /*1-origin*/, ' '); if(loc.region() == 1) { // invalid // ^------ oss << color::bold << color::red << "^---" << color::reset; } else { // invalid // ~~~~~~~ const auto underline_len = (std::min)( static_cast<std::size_t>(loc.region()), loc.line_str().size()); oss << color::bold << color::red << make_string(underline_len, '~') << color::reset; } oss << ' '; oss << comment; return; }; assert(!loc_com.empty()); // --> example.toml // | retval << color::bold << color::blue << " --> " << color::reset << loc_com.front().first.file_name() << '\n'; retval << make_string(line_num_width + 1, ' ') << color::bold << color::blue << " |\n" << color::reset; // 1 | key value // | ^--- missing = format_one_location(retval, loc_com.front().first, loc_com.front().second); // process the rest of the locations for(std::size_t i=1; i<loc_com.size(); ++i) { const auto& prev = loc_com.at(i-1); const auto& curr = loc_com.at(i); retval << '\n'; // if the filenames are the same, print "..." if(prev.first.file_name() == curr.first.file_name()) { retval << color::bold << color::blue << " ...\n" << color::reset; } else // if filename differs, print " --> filename.toml" again { retval << color::bold << color::blue << " --> " << color::reset << curr.first.file_name() << '\n'; retval << make_string(line_num_width + 1, ' ') << color::bold << color::blue << " |\n" << color::reset; } format_one_location(retval, curr.first, curr.second); } if(!helps.empty()) { retval << '\n'; retval << make_string(line_num_width + 1, ' '); retval << color::bold << color::blue << " |" << color::reset; for(const auto& help : helps) { retval << color::bold << "\nHint: " << color::reset; retval << help; } } return retval.str(); } } // detail } // toml #endif// TOML11_SOURCE_LOCATION_HPP