Resolve clang-tidy warnings (#48)

* Resolve clang-tidy warnings, update single_header_generator.py

* Update single header test, resolve additional clang-tidy warnings
This commit is contained in:
red0124 2024-03-12 18:31:24 +01:00 committed by GitHub
parent 457defadaa
commit 69875c238e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 160 additions and 92 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
compile_commands.json
.clang-format
.clang-tidy
.ccls-cache/*
.ccls-cache/
.cache/
experiment/
build/

View File

@ -1,11 +1,15 @@
#pragma once
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#if !__unix__
#include <array>
#include <cstdint>
#endif
namespace ss {
struct none {};
@ -17,13 +21,13 @@ constexpr inline auto default_delimiter = ",";
constexpr inline auto get_line_initial_buffer_size = 128;
template <bool StringError>
inline void assert_string_error_defined() {
void assert_string_error_defined() {
static_assert(StringError,
"'string_error' needs to be enabled to use 'error_msg'");
}
template <bool ThrowOnError>
inline void assert_throw_on_error_not_defined() {
void assert_throw_on_error_not_defined() {
static_assert(!ThrowOnError, "cannot handle errors manually if "
"'throw_on_error' is enabled");
}
@ -46,7 +50,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
using ssize_t = intptr_t;
inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
char buff[get_line_initial_buffer_size];
std::array<char, get_line_initial_buffer_size> buff;
if (lineptr == nullptr || n < sizeof(buff)) {
size_t new_n = sizeof(buff);
@ -57,9 +61,9 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
lineptr[0] = '\0';
size_t line_used = 0;
while (std::fgets(buff, sizeof(buff), file) != nullptr) {
while (std::fgets(buff.data(), sizeof(buff), file) != nullptr) {
line_used = std::strlen(lineptr);
size_t buff_used = std::strlen(buff);
size_t buff_used = std::strlen(buff.data());
if (n <= buff_used + line_used) {
size_t new_n = n * 2;
@ -67,7 +71,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
n = new_n;
}
std::memcpy(lineptr + line_used, buff, buff_used);
std::memcpy(lineptr + line_used, buff.data(), buff_used);
line_used += buff_used;
lineptr[line_used] = '\0';
@ -89,7 +93,7 @@ inline ssize_t get_line_buffer(char*& lineptr, size_t& n,
}
if (lineptr == nullptr || n < get_line_initial_buffer_size) {
auto new_lineptr = static_cast<char*>(
auto* new_lineptr = static_cast<char*>(
strict_realloc(lineptr, get_line_initial_buffer_size));
lineptr = new_lineptr;
n = get_line_initial_buffer_size;
@ -122,7 +126,7 @@ inline std::tuple<ssize_t, bool> get_line(char*& buffer, size_t& buffer_size,
FILE* file,
const char* const csv_data_buffer,
size_t csv_data_size, size_t& curr_char) {
ssize_t ssize;
ssize_t ssize = 0;
if (file) {
ssize = get_line_file(buffer, buffer_size, file);
curr_char += ssize;

View File

@ -224,8 +224,9 @@ private:
}
std::string error_sufix(const string_range msg, size_t pos) const {
constexpr static auto reserve_size = 32;
std::string error;
error.reserve(32);
error.reserve(reserve_size);
error.append("at column ")
.append(std::to_string(pos + 1))
.append(": \'")
@ -391,7 +392,7 @@ private:
////////////////
bool columns_mapped() const {
return column_mappings_.size() != 0;
return !column_mappings_.empty();
}
size_t column_position(size_t tuple_position) const {
@ -404,7 +405,7 @@ private:
// assumes positions are valid and the vector is not empty
void set_column_mapping(std::vector<size_t> positions,
size_t number_of_columns) {
column_mappings_ = positions;
column_mappings_ = std::move(positions);
number_of_columns_ = number_of_columns;
}
@ -490,7 +491,7 @@ private:
friend class parser;
std::vector<size_t> column_mappings_;
size_t number_of_columns_;
size_t number_of_columns_{0};
};
} /* namespace ss */

View File

@ -12,10 +12,10 @@ class exception : public std::exception {
std::string msg_;
public:
exception(const std::string& msg): msg_{msg} {
exception(std::string msg): msg_{std::move(msg)} {
}
virtual char const* what() const noexcept {
char const* what() const noexcept override {
return msg_.c_str();
}
};

View File

@ -2,8 +2,8 @@
#include "type_traits.hpp"
#include <charconv>
#include <cstdint>
#include <cstring>
#include <functional>
#include <optional>
#include <string>
#include <string_view>
@ -14,6 +14,7 @@
#else
#include <algorithm>
#include <cstdlib>
#include <array>
#endif
namespace ss {
@ -45,16 +46,17 @@ std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
"Conversion to long double is disabled");
constexpr static auto buff_max = 64;
char short_buff[buff_max];
std::array<char, buff_max> short_buff;
size_t string_range = std::distance(begin, end);
std::string long_buff;
char* buff;
char* buff = nullptr;
if (string_range > buff_max) {
long_buff = std::string{begin, end};
buff = long_buff.data();
} else {
buff = short_buff;
buff = short_buff.data();
buff[string_range] = '\0';
std::copy_n(begin, string_range, buff);
}
@ -92,6 +94,8 @@ struct numeric_wrapper {
numeric_wrapper& operator=(numeric_wrapper&&) = default;
numeric_wrapper& operator=(const numeric_wrapper&) = default;
~numeric_wrapper() = default;
numeric_wrapper(T other) : value{other} {
}
@ -215,10 +219,13 @@ inline bool extract(const char* begin, const char* end, bool& value) {
return false;
}
} else {
constexpr static auto true_size = 4;
constexpr static auto false_size = 5;
size_t size = end - begin;
if (size == 4 && std::strncmp(begin, "true", size) == 0) {
if (size == true_size && std::strncmp(begin, "true", size) == 0) {
value = true;
} else if (size == 5 && std::strncmp(begin, "false", size) == 0) {
} else if (size == false_size &&
std::strncmp(begin, "false", size) == 0) {
value = false;
} else {
return false;

View File

@ -2,7 +2,6 @@
#include <cstdlib>
#include <functional>
#include <tuple>
namespace ss {

View File

@ -5,7 +5,6 @@
#include "exception.hpp"
#include "extract.hpp"
#include "restrictions.hpp"
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <optional>
@ -33,9 +32,8 @@ class parser {
constexpr static bool ignore_empty = setup<Options...>::ignore_empty;
public:
parser(const std::string& file_name,
const std::string& delim = ss::default_delimiter)
: file_name_{file_name}, reader_{file_name_, delim} {
parser(std::string file_name, std::string delim = ss::default_delimiter)
: file_name_{std::move(file_name)}, reader_{file_name_, delim} {
if (reader_.file_) {
read_line();
if constexpr (ignore_header) {
@ -68,6 +66,7 @@ public:
parser(parser&& other) = default;
parser& operator=(parser&& other) = default;
~parser() = default;
parser() = delete;
parser(const parser& other) = delete;
@ -237,6 +236,10 @@ public:
iterator(const iterator& other) = default;
iterator(iterator&& other) = default;
~iterator() = default;
iterator& operator=(const iterator& other) = delete;
iterator& operator=(iterator&& other) = delete;
value& operator*() {
return value_;
@ -261,8 +264,10 @@ public:
return *this;
}
iterator& operator++(int) {
return ++*this;
iterator operator++(int) {
auto result = *this;
++*this;
return result;
}
friend bool operator==(const iterator& lhs, const iterator& rhs) {
@ -326,7 +331,7 @@ public:
Fun&& fun = none{}) {
using Value = no_void_validator_tup_t<Us...>;
std::optional<Value> value;
try_convert_and_invoke<Value, Us...>(value, fun);
try_convert_and_invoke<Value, Us...>(value, std::forward<Fun>(fun));
return composite_with(std::move(value));
}
@ -335,7 +340,7 @@ public:
template <typename U, typename... Us, typename Fun = none>
composite<Ts..., std::optional<U>> or_object(Fun&& fun = none{}) {
std::optional<U> value;
try_convert_and_invoke<U, Us...>(value, fun);
try_convert_and_invoke<U, Us...>(value, std::forward<Fun>(fun));
return composite_with(std::move(value));
}
@ -443,7 +448,8 @@ private:
using Ret = decltype(try_invoke_impl(arg, std::forward<Fun>(fun)));
constexpr bool returns_void = std::is_same_v<Ret, void>;
if constexpr (!returns_void) {
if (!try_invoke_impl(arg, std::forward<Fun>(fun))) {
if (!try_invoke_impl(std::forward<Arg>(arg),
std::forward<Fun>(fun))) {
handle_error_failed_check();
}
} else {
@ -478,7 +484,7 @@ private:
if (valid()) {
try_invoke(*value, std::forward<Fun>(fun));
}
return {valid() ? std::move(value) : std::nullopt, *this};
return {valid() ? std::forward<T>(value) : std::nullopt, *this};
}
////////////////
@ -674,17 +680,18 @@ private:
}
struct reader {
reader(const std::string& file_name_, const std::string& delim)
: delim_{delim}, file_{std::fopen(file_name_.c_str(), "rb")} {
reader(const std::string& file_name_, std::string delim)
: delim_{std::move(delim)},
file_{std::fopen(file_name_.c_str(), "rb")} {
}
reader(const char* const buffer, size_t csv_data_size,
const std::string& delim)
: delim_{delim}, csv_data_buffer_{buffer},
std::string delim)
: delim_{std::move(delim)}, csv_data_buffer_{buffer},
csv_data_size_{csv_data_size} {
}
reader(reader&& other)
reader(reader&& other) noexcept
: buffer_{other.buffer_},
next_line_buffer_{other.next_line_buffer_},
helper_buffer_{other.helper_buffer_},
@ -705,7 +712,7 @@ private:
other.file_ = nullptr;
}
reader& operator=(reader&& other) {
reader& operator=(reader&& other) noexcept {
if (this != &other) {
buffer_ = other.buffer_;
next_line_buffer_ = other.next_line_buffer_;
@ -853,7 +860,7 @@ private:
}
bool escaped_eol(size_t size) {
const char* curr;
const char* curr = nullptr;
for (curr = next_line_buffer_ + size - 1;
curr >= next_line_buffer_ &&
setup<Options...>::escape::match(*curr);
@ -899,7 +906,7 @@ private:
size_t& buffer_size, const char* const second,
size_t second_size) {
buffer_size = first_size + second_size + 3;
auto new_first = static_cast<char*>(
auto* new_first = static_cast<char*>(
strict_realloc(static_cast<void*>(first), buffer_size));
first = new_first;

View File

@ -2,7 +2,6 @@
#include "common.hpp"
#include "exception.hpp"
#include "setup.hpp"
#include "type_traits.hpp"
#include <algorithm>
#include <cstdlib>
#include <cstring>
@ -321,8 +320,9 @@ private:
trim_left_if_enabled(begin_);
for (done_ = false; !done_; read(delim))
;
for (done_ = false; !done_;) {
read(delim);
}
return split_data_;
}

View File

@ -34,7 +34,11 @@ struct left_of_impl;
template <size_t N, typename T, typename... Ts>
struct left_of_impl {
static_assert(N < 128, "recursion limit reached");
private:
constexpr static auto recursion_limit = 128;
public:
static_assert(N < recursion_limit, "recursion limit reached");
static_assert(N != 0, "cannot take the whole tuple");
using type = tup_cat_t<T, typename left_of_impl<N - 1, Ts...>::type>;
};

View File

@ -14,14 +14,21 @@ headers = ['type_traits.hpp',
combined_file = []
includes = []
in_pp_block = False
for header in headers:
with open(headers_dir + header) as f:
for line in f.read().splitlines():
if '#if ' in line:
in_pp_block = True
if '#endif' in line:
in_pp_block = False
if '#include "' in line or '#include <fast_float' in line:
continue
if '#include <' in line:
if '#include <' in line and not in_pp_block:
includes.append(line)
continue

105
ssp.hpp
View File

@ -49,7 +49,11 @@ struct left_of_impl;
template <size_t N, typename T, typename... Ts>
struct left_of_impl {
static_assert(N < 128, "recursion limit reached");
private:
constexpr static auto recursion_limit = 128;
public:
static_assert(N < recursion_limit, "recursion limit reached");
static_assert(N != 0, "cannot take the whole tuple");
using type = tup_cat_t<T, typename left_of_impl<N - 1, Ts...>::type>;
};
@ -405,10 +409,10 @@ class exception : public std::exception {
std::string msg_;
public:
exception(const std::string& msg): msg_{msg} {
exception(std::string msg): msg_{std::move(msg)} {
}
virtual char const* what() const noexcept {
char const* what() const noexcept override {
return msg_.c_str();
}
};
@ -617,6 +621,11 @@ struct ne {
} /* namespace ss */
#if !__unix__
#include <array>
#include <cstdint>
#endif
namespace ss {
struct none {};
@ -628,13 +637,13 @@ constexpr inline auto default_delimiter = ",";
constexpr inline auto get_line_initial_buffer_size = 128;
template <bool StringError>
inline void assert_string_error_defined() {
void assert_string_error_defined() {
static_assert(StringError,
"'string_error' needs to be enabled to use 'error_msg'");
}
template <bool ThrowOnError>
inline void assert_throw_on_error_not_defined() {
void assert_throw_on_error_not_defined() {
static_assert(!ThrowOnError, "cannot handle errors manually if "
"'throw_on_error' is enabled");
}
@ -657,7 +666,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
using ssize_t = intptr_t;
inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
char buff[get_line_initial_buffer_size];
std::array<char, get_line_initial_buffer_size> buff;
if (lineptr == nullptr || n < sizeof(buff)) {
size_t new_n = sizeof(buff);
@ -668,9 +677,9 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
lineptr[0] = '\0';
size_t line_used = 0;
while (std::fgets(buff, sizeof(buff), file) != nullptr) {
while (std::fgets(buff.data(), sizeof(buff), file) != nullptr) {
line_used = std::strlen(lineptr);
size_t buff_used = std::strlen(buff);
size_t buff_used = std::strlen(buff.data());
if (n <= buff_used + line_used) {
size_t new_n = n * 2;
@ -678,7 +687,7 @@ inline ssize_t get_line_file(char*& lineptr, size_t& n, FILE* file) {
n = new_n;
}
std::memcpy(lineptr + line_used, buff, buff_used);
std::memcpy(lineptr + line_used, buff.data(), buff_used);
line_used += buff_used;
lineptr[line_used] = '\0';
@ -700,7 +709,7 @@ inline ssize_t get_line_buffer(char*& lineptr, size_t& n,
}
if (lineptr == nullptr || n < get_line_initial_buffer_size) {
auto new_lineptr = static_cast<char*>(
auto* new_lineptr = static_cast<char*>(
strict_realloc(lineptr, get_line_initial_buffer_size));
lineptr = new_lineptr;
n = get_line_initial_buffer_size;
@ -733,7 +742,7 @@ inline std::tuple<ssize_t, bool> get_line(char*& buffer, size_t& buffer_size,
FILE* file,
const char* const csv_data_buffer,
size_t csv_data_size, size_t& curr_char) {
ssize_t ssize;
ssize_t ssize = 0;
if (file) {
ssize = get_line_file(buffer, buffer_size, file);
curr_char += ssize;
@ -1359,8 +1368,9 @@ private:
trim_left_if_enabled(begin_);
for (done_ = false; !done_; read(delim))
;
for (done_ = false; !done_;) {
read(delim);
}
return split_data_;
}
@ -1552,16 +1562,17 @@ std::enable_if_t<std::is_floating_point_v<T>, std::optional<T>> to_num(
"Conversion to long double is disabled");
constexpr static auto buff_max = 64;
char short_buff[buff_max];
std::array<char, buff_max> short_buff;
size_t string_range = std::distance(begin, end);
std::string long_buff;
char* buff;
char* buff = nullptr;
if (string_range > buff_max) {
long_buff = std::string{begin, end};
buff = long_buff.data();
} else {
buff = short_buff;
buff = short_buff.data();
buff[string_range] = '\0';
std::copy_n(begin, string_range, buff);
}
@ -1599,6 +1610,8 @@ struct numeric_wrapper {
numeric_wrapper& operator=(numeric_wrapper&&) = default;
numeric_wrapper& operator=(const numeric_wrapper&) = default;
~numeric_wrapper() = default;
numeric_wrapper(T other) : value{other} {
}
@ -1649,7 +1662,7 @@ template <typename T>
struct unsupported_type {
constexpr static bool value = false;
};
} /* namespace error */
} /* namespace errors */
template <typename T>
std::enable_if_t<!std::is_integral_v<T> && !std::is_floating_point_v<T> &&
@ -1722,10 +1735,13 @@ inline bool extract(const char* begin, const char* end, bool& value) {
return false;
}
} else {
constexpr static auto true_size = 4;
constexpr static auto false_size = 5;
size_t size = end - begin;
if (size == 4 && std::strncmp(begin, "true", size) == 0) {
if (size == true_size && std::strncmp(begin, "true", size) == 0) {
value = true;
} else if (size == 5 && std::strncmp(begin, "false", size) == 0) {
} else if (size == false_size &&
std::strncmp(begin, "false", size) == 0) {
value = false;
} else {
return false;
@ -1971,8 +1987,9 @@ private:
}
std::string error_sufix(const string_range msg, size_t pos) const {
constexpr static auto reserve_size = 32;
std::string error;
error.reserve(32);
error.reserve(reserve_size);
error.append("at column ")
.append(std::to_string(pos + 1))
.append(": \'")
@ -2138,7 +2155,7 @@ private:
////////////////
bool columns_mapped() const {
return column_mappings_.size() != 0;
return !column_mappings_.empty();
}
size_t column_position(size_t tuple_position) const {
@ -2151,7 +2168,7 @@ private:
// assumes positions are valid and the vector is not empty
void set_column_mapping(std::vector<size_t> positions,
size_t number_of_columns) {
column_mappings_ = positions;
column_mappings_ = std::move(positions);
number_of_columns_ = number_of_columns;
}
@ -2237,7 +2254,7 @@ private:
friend class parser;
std::vector<size_t> column_mappings_;
size_t number_of_columns_;
size_t number_of_columns_{0};
};
} /* namespace ss */
@ -2264,9 +2281,8 @@ class parser {
constexpr static bool ignore_empty = setup<Options...>::ignore_empty;
public:
parser(const std::string& file_name,
const std::string& delim = ss::default_delimiter)
: file_name_{file_name}, reader_{file_name_, delim} {
parser(std::string file_name, std::string delim = ss::default_delimiter)
: file_name_{std::move(file_name)}, reader_{file_name_, delim} {
if (reader_.file_) {
read_line();
if constexpr (ignore_header) {
@ -2299,6 +2315,7 @@ public:
parser(parser&& other) = default;
parser& operator=(parser&& other) = default;
~parser() = default;
parser() = delete;
parser(const parser& other) = delete;
@ -2468,6 +2485,10 @@ public:
iterator(const iterator& other) = default;
iterator(iterator&& other) = default;
~iterator() = default;
iterator& operator=(const iterator& other) = delete;
iterator& operator=(iterator&& other) = delete;
value& operator*() {
return value_;
@ -2492,8 +2513,10 @@ public:
return *this;
}
iterator& operator++(int) {
return ++*this;
iterator operator++(int) {
auto result = *this;
++*this;
return result;
}
friend bool operator==(const iterator& lhs, const iterator& rhs) {
@ -2557,7 +2580,7 @@ public:
Fun&& fun = none{}) {
using Value = no_void_validator_tup_t<Us...>;
std::optional<Value> value;
try_convert_and_invoke<Value, Us...>(value, fun);
try_convert_and_invoke<Value, Us...>(value, std::forward<Fun>(fun));
return composite_with(std::move(value));
}
@ -2566,7 +2589,7 @@ public:
template <typename U, typename... Us, typename Fun = none>
composite<Ts..., std::optional<U>> or_object(Fun&& fun = none{}) {
std::optional<U> value;
try_convert_and_invoke<U, Us...>(value, fun);
try_convert_and_invoke<U, Us...>(value, std::forward<Fun>(fun));
return composite_with(std::move(value));
}
@ -2674,7 +2697,8 @@ private:
using Ret = decltype(try_invoke_impl(arg, std::forward<Fun>(fun)));
constexpr bool returns_void = std::is_same_v<Ret, void>;
if constexpr (!returns_void) {
if (!try_invoke_impl(arg, std::forward<Fun>(fun))) {
if (!try_invoke_impl(std::forward<Arg>(arg),
std::forward<Fun>(fun))) {
handle_error_failed_check();
}
} else {
@ -2709,7 +2733,7 @@ private:
if (valid()) {
try_invoke(*value, std::forward<Fun>(fun));
}
return {valid() ? std::move(value) : std::nullopt, *this};
return {valid() ? std::forward<T>(value) : std::nullopt, *this};
}
////////////////
@ -2905,17 +2929,18 @@ private:
}
struct reader {
reader(const std::string& file_name_, const std::string& delim)
: delim_{delim}, file_{std::fopen(file_name_.c_str(), "rb")} {
reader(const std::string& file_name_, std::string delim)
: delim_{std::move(delim)},
file_{std::fopen(file_name_.c_str(), "rb")} {
}
reader(const char* const buffer, size_t csv_data_size,
const std::string& delim)
: delim_{delim}, csv_data_buffer_{buffer},
std::string delim)
: delim_{std::move(delim)}, csv_data_buffer_{buffer},
csv_data_size_{csv_data_size} {
}
reader(reader&& other)
reader(reader&& other) noexcept
: buffer_{other.buffer_},
next_line_buffer_{other.next_line_buffer_},
helper_buffer_{other.helper_buffer_},
@ -2936,7 +2961,7 @@ private:
other.file_ = nullptr;
}
reader& operator=(reader&& other) {
reader& operator=(reader&& other) noexcept {
if (this != &other) {
buffer_ = other.buffer_;
next_line_buffer_ = other.next_line_buffer_;
@ -3084,7 +3109,7 @@ private:
}
bool escaped_eol(size_t size) {
const char* curr;
const char* curr = nullptr;
for (curr = next_line_buffer_ + size - 1;
curr >= next_line_buffer_ &&
setup<Options...>::escape::match(*curr);
@ -3130,7 +3155,7 @@ private:
size_t& buffer_size, const char* const second,
size_t second_size) {
buffer_size = first_size + second_size + 3;
auto new_first = static_cast<char*>(
auto* new_first = static_cast<char*>(
strict_realloc(static_cast<void*>(first), buffer_size));
first = new_first;

View File

@ -3,12 +3,14 @@
set -x
set -e
python3 script/single_header_generator.py > ssp.cpp
TMP_HDR=test_single_header.hpp
TMP_SRC=test_single_header.cpp
TMP_BIN=test_single_header
echo 'int main(){ ss::parser p{""}; p.get_next<int, float>(); return 0; }' \
>> ssp.cpp
python3 script/single_header_generator.py > ${TMP_HDR}
cat ${TMP_HDR} test/test_single_header_main.txt > ${TMP_SRC}
g++ -std=c++17 ssp.cpp -o ssp.bin -Wall -Wextra
./ssp.bin
g++ -std=c++17 ${TMP_SRC} -o ${TMP_BIN} -Wall -Wextra
./${TMP_BIN}
rm ssp.cpp ssp.bin
rm ${TMP_HDR} ${TMP_SRC} ${TMP_BIN}

View File

@ -0,0 +1,12 @@
int main() {
using quote = ss::quote<'"'>;
using escape = ss::escape<'\\'>;
using trim = ss::trim<' '>;
std::string data = "1,string,2.34,c";
ss::parser<quote, escape, trim, ss::multiline> p{data.c_str(), data.size()};
auto tup = p.get_next<int, std::string, float, std::optional<char>>();
return 0;
}