mirror of
				https://github.com/red0124/ssp.git
				synced 2025-11-03 22:36:44 +01:00 
			
		
		
		
	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:
		
							parent
							
								
									457defadaa
								
							
						
					
					
						commit
						69875c238e
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,7 +1,7 @@
 | 
			
		||||
compile_commands.json
 | 
			
		||||
.clang-format
 | 
			
		||||
.clang-tidy
 | 
			
		||||
.ccls-cache/*
 | 
			
		||||
.ccls-cache/
 | 
			
		||||
.cache/
 | 
			
		||||
experiment/
 | 
			
		||||
build/
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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 */
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@
 | 
			
		||||
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <tuple>
 | 
			
		||||
 | 
			
		||||
namespace ss {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								ssp.hpp
									
									
									
									
									
								
							@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								test/test_single_header_main.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/test_single_header_main.txt
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user