diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ef5eed5..903272d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,13 +33,16 @@ set(TEST_NAMES test_extended_conversions ) -CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL) +CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL) +CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA) CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC) if(COMPILER_SUPPORTS_WALL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") endif() - +if(COMPILER_SUPPORTS_WEXTRA) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") +endif() if(COMPILER_SUPPORTS_WPEDANTIC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic") endif() diff --git a/tests/test_parse_file.cpp b/tests/test_parse_file.cpp index e2d499b..518a98c 100644 --- a/tests/test_parse_file.cpp +++ b/tests/test_parse_file.cpp @@ -453,7 +453,7 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM) // value will be "\r\r\n". To avoid the additional "\r", use binary // mode. std::ofstream ofs("tmp.toml", std::ios_base::binary); - ofs.write(table.data(), table.size()); + ofs.write(table.data(), static_cast(table.size())); } const auto data = toml::parse("tmp.toml"); diff --git a/toml/datetime.hpp b/toml/datetime.hpp index f0ae405..dc52396 100644 --- a/toml/datetime.hpp +++ b/toml/datetime.hpp @@ -46,7 +46,7 @@ inline std::tm localtime_s(const std::time_t* src) #endif } // detail -enum class month_t : std::int8_t +enum class month_t : std::uint8_t { Jan = 0, Feb = 1, @@ -98,9 +98,9 @@ struct local_date t.tm_sec = 0; t.tm_min = 0; t.tm_hour = 0; - t.tm_mday = this->day; - t.tm_mon = this->month; - t.tm_year = this->year - 1900; + t.tm_mday = static_cast(this->day); + t.tm_mon = static_cast(this->month); + t.tm_year = static_cast(this->year) - 1900; t.tm_wday = 0; // the value will be ignored t.tm_yday = 0; // the value will be ignored t.tm_isdst = -1; @@ -188,22 +188,22 @@ struct local_time explicit local_time(const std::chrono::duration& t) { const auto h = std::chrono::duration_cast(t); - this->hour = h.count(); + this->hour = static_cast(h.count()); const auto t2 = t - h; const auto m = std::chrono::duration_cast(t2); - this->minute = m.count(); + this->minute = static_cast(m.count()); const auto t3 = t2 - m; const auto s = std::chrono::duration_cast(t3); - this->second = s.count(); + this->second = static_cast(s.count()); const auto t4 = t3 - s; const auto ms = std::chrono::duration_cast(t4); - this->millisecond = ms.count(); + this->millisecond = static_cast(ms.count()); const auto t5 = t4 - ms; const auto us = std::chrono::duration_cast(t5); - this->microsecond = us.count(); + this->microsecond = static_cast(us.count()); const auto t6 = t5 - us; const auto ns = std::chrono::duration_cast(t6); - this->nanosecond = ns.count(); + this->nanosecond = static_cast(ns.count()); } operator std::chrono::nanoseconds() const diff --git a/toml/parser.hpp b/toml/parser.hpp index 2d1d283..a7cf57e 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -253,6 +253,11 @@ std::string read_utf8_codepoint(const region& reg, std::istringstream iss(str); iss >> std::hex >> codepoint; + const auto to_char = [](const int i) noexcept -> char { + const auto uc = static_cast(i); + return *reinterpret_cast(std::addressof(uc)); + }; + std::string character; if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII. { @@ -261,8 +266,8 @@ std::string read_utf8_codepoint(const region& reg, else if(codepoint < 0x800) //U+0080 ... U+07FF { // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111 - character += static_cast(0xC0| codepoint >> 6); - character += static_cast(0x80|(codepoint & 0x3F)); + character += to_char(0xC0| codepoint >> 6); + character += to_char(0x80|(codepoint & 0x3F)); } else if(codepoint < 0x10000) // U+0800...U+FFFF { @@ -276,17 +281,17 @@ std::string read_utf8_codepoint(const region& reg, } assert(codepoint < 0xD800 || 0xDFFF < codepoint); // 1110yyyy 10yxxxxx 10xxxxxx - character += static_cast(0xE0| codepoint >> 12); - character += static_cast(0x80|(codepoint >> 6 & 0x3F)); - character += static_cast(0x80|(codepoint & 0x3F)); + character += to_char(0xE0| codepoint >> 12); + character += to_char(0x80|(codepoint >> 6 & 0x3F)); + character += to_char(0x80|(codepoint & 0x3F)); } else if(codepoint < 0x110000) // U+010000 ... U+10FFFF { // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx - character += static_cast(0xF0| codepoint >> 18); - character += static_cast(0x80|(codepoint >> 12 & 0x3F)); - character += static_cast(0x80|(codepoint >> 6 & 0x3F)); - character += static_cast(0x80|(codepoint & 0x3F)); + character += to_char(0xF0| codepoint >> 18); + character += to_char(0x80|(codepoint >> 12 & 0x3F)); + character += to_char(0x80|(codepoint >> 6 & 0x3F)); + character += to_char(0x80|(codepoint & 0x3F)); } else // out of UTF-8 region { @@ -655,9 +660,9 @@ parse_local_time(location& loc) {{std::addressof(inner_loc), "here"}})); } local_time time( - static_cast(from_string(h.unwrap().str(), 0)), - static_cast(from_string(m.unwrap().str(), 0)), - static_cast(from_string(s.unwrap().str(), 0)), 0, 0); + from_string(h.unwrap().str(), 0), + from_string(m.unwrap().str(), 0), + from_string(s.unwrap().str(), 0), 0, 0); const auto before_secfrac = inner_loc.iter(); if(const auto secfrac = lex_time_secfrac::invoke(inner_loc)) @@ -673,13 +678,13 @@ parse_local_time(location& loc) } if(sf.size() >= 6) { - time.millisecond = from_string(sf.substr(0, 3), 0); - time.microsecond = from_string(sf.substr(3, 3), 0); + time.millisecond = from_string(sf.substr(0, 3), 0u); + time.microsecond = from_string(sf.substr(3, 3), 0u); } else if(sf.size() >= 3) { - time.millisecond = from_string(sf, 0); - time.microsecond = 0; + time.millisecond = from_string(sf, 0u); + time.microsecond = 0u; } } else @@ -1934,7 +1939,8 @@ parse(std::istream& is, const std::string& fname = "unknown file") is.seekg(beg); // read whole file as a sequence of char - std::vector letters(fsize); + assert(fsize >= 0); + std::vector letters(static_cast(fsize)); is.read(letters.data(), fsize); detail::location> diff --git a/toml/region.hpp b/toml/region.hpp index b6ac6e8..e5ed659 100644 --- a/toml/region.hpp +++ b/toml/region.hpp @@ -69,8 +69,9 @@ struct region_base template struct location final : public region_base { - using const_iterator = typename Container::const_iterator; - using source_ptr = std::shared_ptr; + using const_iterator = typename Container::const_iterator; + using difference_type = typename const_iterator::difference_type; + using source_ptr = std::shared_ptr; static_assert(std::is_same::value,""); static_assert(std::is_sameline_number_ += std::count(this->iter_, this->iter_ + n, '\n'); + this->line_number_ += static_cast( + std::count(this->iter_, std::next(this->iter_, n), '\n')); this->iter_ += n; return; } - void retrace(std::size_t n = 1) noexcept + void retrace(difference_type n = 1) noexcept { - this->line_number_ -= std::count(this->iter_ - n, this->iter_, '\n'); + this->line_number_ -= static_cast( + std::count(std::prev(this->iter_, n), this->iter_, '\n')); this->iter_ -= n; return; } @@ -121,11 +124,13 @@ struct location final : public region_base // iterators and returns a negative value if `first > last`. if(0 <= std::distance(rollback, this->iter_)) // rollback < iter { - this->line_number_ -= std::count(rollback, this->iter_, '\n'); + this->line_number_ -= static_cast( + std::count(rollback, this->iter_, '\n')); } else // iter < rollback [[unlikely]] { - this->line_number_ += std::count(this->iter_, rollback, '\n'); + this->line_number_ += static_cast( + std::count(this->iter_, rollback, '\n')); } this->iter_ = rollback; return; @@ -162,11 +167,15 @@ struct location final : public region_base } std::size_t before() const noexcept override { - return std::distance(this->line_begin(), this->iter()); + const auto sz = std::distance(this->line_begin(), this->iter()); + assert(sz >= 0); + return static_cast(sz); } std::size_t after() const noexcept override { - return std::distance(this->iter(), this->line_end()); + const auto sz = std::distance(this->iter(), this->line_end()); + assert(sz >= 0); + return static_cast(sz); } source_ptr const& source() const& noexcept {return source_;} @@ -250,15 +259,21 @@ struct region final : public region_base std::size_t size() const noexcept override { - return std::distance(first_, last_); + const auto sz = std::distance(first_, last_); + assert(sz >= 0); + return static_cast(sz); } std::size_t before() const noexcept override { - return std::distance(this->line_begin(), this->first()); + const auto sz = std::distance(this->line_begin(), this->first()); + assert(sz >= 0); + return static_cast(sz); } std::size_t after() const noexcept override { - return std::distance(this->last(), this->line_end()); + const auto sz = std::distance(this->last(), this->line_end()); + assert(sz >= 0); + return static_cast(sz); } bool contain_newline() const noexcept @@ -409,13 +424,14 @@ inline std::string format_underline(const std::string& message, { assert(!reg_com.empty()); - const auto line_num_width = std::max_element(reg_com.begin(), reg_com.end(), + const auto line_num_width = static_cast(std::max_element( + reg_com.begin(), reg_com.end(), [](std::pair const& lhs, std::pair const& rhs) { return lhs.first->line_num().size() < rhs.first->line_num().size(); } - )->first->line_num().size(); + )->first->line_num().size()); std::ostringstream retval; retval << message << '\n'; @@ -438,7 +454,7 @@ inline std::string format_underline(const std::string& message, retval << ' ' << std::setw(line_num_width) << reg->line_num(); retval << " | " << reg->line() << '\n'; - retval << make_string(line_num_width + 1, ' '); + retval << make_string(static_cast(line_num_width + 1), ' '); retval << " | " << make_string(reg->before(), ' '); if(reg->size() == 1) @@ -462,7 +478,7 @@ inline std::string format_underline(const std::string& message, if(!helps.empty()) { retval << '\n'; - retval << make_string(line_num_width + 1, ' '); + retval << make_string(static_cast(line_num_width + 1), ' '); retval << " | "; for(const auto help : helps) { diff --git a/toml/serializer.hpp b/toml/serializer.hpp index cba2923..4711236 100644 --- a/toml/serializer.hpp +++ b/toml/serializer.hpp @@ -29,7 +29,7 @@ struct serializer using array_type = typename value_type::array_type ; using table_type = typename value_type::table_type ; - serializer(const std::size_t w = 80, + serializer(const std::size_t w = 80u, const int float_prec = std::numeric_limits::max_digits10, const bool can_be_inlined = false, std::vector ks = {}) @@ -50,7 +50,8 @@ struct serializer { const auto fmt = "%.*g"; const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f); - std::vector buf(bsz + 1, '\0'); // +1 for null character(\0) + // +1 for null character(\0) + std::vector buf(static_cast(bsz + 1), '\0'); std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f); std::string token(buf.begin(), std::prev(buf.end())); @@ -58,16 +59,27 @@ struct serializer { token += '0'; } - const auto e = std::find_if(token.cbegin(), token.cend(), - [](const char c) -> bool { - return c == 'E' || c == 'e'; + + const auto e = std::find_if( + token.cbegin(), token.cend(), [](const char c) noexcept -> bool { + return c == 'e' || c == 'E'; }); - if(e == token.cend()) + const auto has_exponent = (token.cend() != e); + const auto has_fraction = (token.cend() != std::find( + token.cbegin(), token.cend(), '.')); + + if(!has_exponent && !has_fraction) + { + // the resulting value does not have any float specific part! + token += ".0"; + return token; + } + if(!has_exponent) { return token; // there is no exponent part. just return it. } - // zero-prefix in an exponent is not allowed in TOML. + // zero-prefix in an exponent is NOT allowed in TOML. // remove it if it exists. bool sign_exists = false; std::size_t zero_prefix = 0; @@ -81,7 +93,8 @@ struct serializer { const auto offset = std::distance(token.cbegin(), e) + (sign_exists ? 2 : 1); - token.erase(offset, zero_prefix); + token.erase(static_cast(offset), + zero_prefix); } return token; } @@ -609,7 +622,7 @@ struct serializer template class M, template class V> std::string -format(const basic_value& v, std::size_t w = 80, +format(const basic_value& v, std::size_t w = 80u, int fprec = std::numeric_limits::max_digits10, bool force_inline = false) { @@ -638,8 +651,8 @@ std::basic_ostream& operator<<(std::basic_ostream& os, const basic_value& v) { // get status of std::setw(). - const std::size_t w = os.width(); - const int fprec = os.precision(); + const auto w = static_cast(os.width()); + const int fprec = static_cast(os.precision()); os.width(0); if(!v.comments().empty()) diff --git a/toml/source_location.hpp b/toml/source_location.hpp index 48396a0..051f4e5 100644 --- a/toml/source_location.hpp +++ b/toml/source_location.hpp @@ -48,9 +48,9 @@ struct source_location { if(reg) { - line_num_ = std::stoul(reg->line_num()); - column_num_ = reg->before() + 1; - region_size_ = reg->size(); + line_num_ = static_cast(std::stoul(reg->line_num())); + column_num_ = static_cast(reg->before() + 1); + region_size_ = static_cast(reg->size()); file_name_ = reg->name(); line_str_ = reg->line(); } diff --git a/toml/value.hpp b/toml/value.hpp index 86fc51d..56bb948 100644 --- a/toml/value.hpp +++ b/toml/value.hpp @@ -601,7 +601,7 @@ class basic_value : type_(value_t::floating), region_info_(std::make_shared(region_base{})) { - assigner(this->floating_, f); + assigner(this->floating_, static_cast(f)); } template>(std::move(reg))), comments_(region_info_->comments()) { - assigner(this->floating_, f); + assigner(this->floating_, static_cast(f)); } templatecleanup(); this->type_ = value_t::floating; this->region_info_ = std::make_shared(region_base{}); - assigner(this->floating_, f); + assigner(this->floating_, static_cast(f)); return *this; }