Vince's CSV Parser
Loading...
Searching...
No Matches
common.hpp
Go to the documentation of this file.
1
5#pragma once
6#include <algorithm>
7#include <array>
8#include <cmath>
9#include <cstdlib>
10#include <deque>
11
12#if defined(_WIN32)
13# ifndef WIN32_LEAN_AND_MEAN
14# define WIN32_LEAN_AND_MEAN
15# endif
16# include <windows.h>
17# undef max
18# undef min
19#elif defined(__linux__)
20# include <unistd.h>
21#endif
22
26#define CSV_INLINE
27
28#pragma once
29#include <type_traits>
30
31// Minimal portability macros (Hedley subset) with CSV_ prefix.
32#if defined(__clang__) || defined(__GNUC__)
33 #define CSV_CONST __attribute__((__const__))
34 #define CSV_PURE __attribute__((__pure__))
35 #define CSV_PRIVATE __attribute__((__visibility__("hidden")))
36 #define CSV_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
37#elif defined(_MSC_VER)
38 #define CSV_CONST
39 #define CSV_PURE
40 #define CSV_PRIVATE
41 #define CSV_NON_NULL(...)
42#else
43 #define CSV_CONST
44 #define CSV_PURE
45 #define CSV_PRIVATE
46 #define CSV_NON_NULL(...)
47#endif
48
49#if defined(__GNUC__) || defined(__clang__)
50 #define CSV_UNREACHABLE() __builtin_unreachable()
51#elif defined(_MSC_VER)
52 #define CSV_UNREACHABLE() __assume(0)
53#else
54 #define CSV_UNREACHABLE() abort()
55#endif
56
57// This library uses C++ exceptions for error reporting in public APIs.
58#if defined(__cpp_exceptions) || defined(_CPPUNWIND) || defined(__EXCEPTIONS)
59 #define CSV_EXCEPTIONS_ENABLED 1
60#else
61 #define CSV_EXCEPTIONS_ENABLED 0
62#endif
63
64#if !CSV_EXCEPTIONS_ENABLED
65 #error "csv-parser requires C++ exceptions. Enable exception handling (for example, remove -fno-exceptions or use /EHsc)."
66#endif
67
68// Detect C++ standard version BEFORE namespace to properly include string_view
69// MSVC: __cplusplus == 199711L unless /Zc:__cplusplus is set; use _MSVC_LANG instead.
70#if defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus
71# define CSV_CPLUSPLUS _MSVC_LANG
72#else
73# define CSV_CPLUSPLUS __cplusplus
74#endif
75
76#if (defined(CMAKE_CXX_STANDARD) && CMAKE_CXX_STANDARD == 20) || CSV_CPLUSPLUS >= 202002L
77#define CSV_HAS_CXX20
78#endif
79
80#if (defined(CMAKE_CXX_STANDARD) && CMAKE_CXX_STANDARD == 17) || CSV_CPLUSPLUS >= 201703L
81#define CSV_HAS_CXX17
82#endif
83
84#if (defined(CMAKE_CXX_STANDARD) && CMAKE_CXX_STANDARD >= 14) || CSV_CPLUSPLUS >= 201402L
85#define CSV_HAS_CXX14
86#endif
87
88// Include string_view BEFORE csv namespace to avoid namespace pollution issues
89#ifdef CSV_HAS_CXX17
90#include <string_view>
91#else
92#include "../external/string_view.hpp"
93#endif
94
95namespace csv {
96#ifdef _MSC_VER
97#pragma region Compatibility Macros
98#endif
112#define STATIC_ASSERT(x) static_assert(x, "Assertion failed")
113
114#ifdef CSV_HAS_CXX17
118 using string_view = std::string_view;
119#else
123 using string_view = nonstd::string_view;
124#endif
125
126#ifdef CSV_HAS_CXX17
127 #define IF_CONSTEXPR if constexpr
128 #define CONSTEXPR_VALUE constexpr
129
130 #define CONSTEXPR_17 constexpr
131#else
132 #define IF_CONSTEXPR if
133 #define CONSTEXPR_VALUE const
134
135 #define CONSTEXPR_17 inline
136#endif
137
138#ifdef CSV_HAS_CXX14
139 template<bool B, class T = void>
140 using enable_if_t = std::enable_if_t<B, T>;
141
142 #define CONSTEXPR_14 constexpr
143 #define CONSTEXPR_VALUE_14 constexpr
144#else
145 template<bool B, class T = void>
146 using enable_if_t = typename std::enable_if<B, T>::type;
147
148 #define CONSTEXPR_14 inline
149 #define CONSTEXPR_VALUE_14 const
150#endif
151
152#ifdef CSV_HAS_CXX17
153 template<typename F, typename... Args>
154 using invoke_result_t = typename std::invoke_result<F, Args...>::type;
155#else
156 template<typename F, typename... Args>
157 using invoke_result_t = typename std::result_of<F(Args...)>::type;
158#endif
159
160 // Resolves g++ bug with regard to constexpr methods
161 // See: https://stackoverflow.com/questions/36489369/constexpr-non-static-member-function-with-non-constexpr-constructor-gcc-clang-d
162#if defined __GNUC__ && !defined __clang__
163 #if (__GNUC__ >= 7 &&__GNUC_MINOR__ >= 2) || (__GNUC__ >= 8)
164 #define CONSTEXPR constexpr
165 #endif
166 #else
167 #ifdef CSV_HAS_CXX17
168 #define CONSTEXPR constexpr
169 #endif
170#endif
171
172#ifndef CONSTEXPR
173#define CONSTEXPR inline
174#endif
175
176#ifdef _MSC_VER
177#pragma endregion
178#endif
179
180 namespace internals {
181 // PAGE_SIZE macro could be already defined by the host system.
182#if defined(PAGE_SIZE)
183#undef PAGE_SIZE
184#endif
185
186// Get operating system specific details
187#if defined(_WIN32)
188 inline int getpagesize() {
191 return std::max(sys_info.dwPageSize, sys_info.dwAllocationGranularity);
192 }
193
194 const int PAGE_SIZE = getpagesize();
195#elif defined(__linux__)
196 const int PAGE_SIZE = getpagesize();
197#else
201 const int PAGE_SIZE = 4096;
202#endif
203
214 constexpr size_t ITERATION_CHUNK_SIZE = 10000000; // 10MB
215
216 template<typename T>
217 inline bool is_equal(T a, T b, T epsilon = 0.001) {
219 static_assert(std::is_floating_point<T>::value, "T must be a floating point type.");
220 return std::abs(a - b) < epsilon;
221 }
222
229 enum class ParseFlags {
231 QUOTE = 2 | 1,
232 NOT_SPECIAL = 4,
233 DELIMITER = 4 | 2,
234 NEWLINE = 4 | 2 | 1
235 };
236
239 constexpr ParseFlags quote_escape_flag(ParseFlags flag, bool quote_escape) noexcept {
240 return (ParseFlags)((int)flag & ~((int)ParseFlags::QUOTE * quote_escape));
241 }
242
243 // Assumed to be true by parsing functions: allows for testing
244 // if an item is DELIMITER or NEWLINE with a >= statement
246
253 STATIC_ASSERT(quote_escape_flag(ParseFlags::QUOTE, false) == ParseFlags::QUOTE);
256
261
263 using ParseFlagMap = std::array<ParseFlags, 256>;
264
266 using WhitespaceMap = std::array<bool, 256>;
267 }
268
270 constexpr int CSV_NOT_FOUND = -1;
271
273 constexpr unsigned CHAR_OFFSET = std::numeric_limits<char>::is_signed ? 128 : 0;
274}
std::array< ParseFlags, 256 > ParseFlagMap
An array which maps ASCII chars to a parsing flag.
Definition common.hpp:263
std::array< bool, 256 > WhitespaceMap
An array which maps ASCII chars to a flag indicating if it is whitespace.
Definition common.hpp:266
constexpr size_t ITERATION_CHUNK_SIZE
Chunk size for lazy-loading large CSV files.
Definition common.hpp:214
bool is_equal(T a, T b, T epsilon=0.001)
Definition common.hpp:217
const int PAGE_SIZE
Size of a memory page in bytes.
Definition common.hpp:201
ParseFlags
An enum used for describing the significance of each character with respect to CSV parsing.
Definition common.hpp:229
@ QUOTE_ESCAPE_QUOTE
A quote inside or terminating a quote_escaped field.
@ NOT_SPECIAL
Characters with no special meaning or escaped delimiters and newlines.
@ NEWLINE
Characters which signify a new row.
@ QUOTE
Characters which may signify a quote escape.
@ DELIMITER
Characters which signify a new field.
constexpr ParseFlags quote_escape_flag(ParseFlags flag, bool quote_escape) noexcept
Transform the ParseFlags given the context of whether or not the current field is quote escaped.
Definition common.hpp:239
CSV_CONST CONSTEXPR_17 OutArray arrayToDefault(T &&value)
Helper constexpr function to initialize an array with all the elements set to value.
The all encompassing namespace.
constexpr int CSV_NOT_FOUND
Integer indicating a requested column wasn't found.
Definition common.hpp:270
constexpr unsigned CHAR_OFFSET
Offset to convert char into array index.
Definition common.hpp:273
nonstd::string_view string_view
The string_view class used by this library.
Definition common.hpp:123