5
5
#include < memory>
6
6
#include < string>
7
7
8
+ // padded buffer can be made with length < 1
9
+ #define SIMDJSON_OK_EMPTY_PADDED_BUFFER 1
10
+
8
11
namespace simdjson {
9
12
// low-level function to allocate memory with padding so we can read passed the
10
13
// "length" bytes safely. if you must provide a pointer to some data, create it
11
14
// with this function: length is the max. size in bytes of the string caller is
12
15
// responsible to free the memory (free(...))
13
- char *allocate_padded_buffer (size_t length);
16
+ inline char *allocate_padded_buffer (size_t length) noexcept {
17
+
18
+ #ifndef NDEBUG
19
+ #ifndef SIMDJSON_OK_EMPTY_PADDED_BUFFER
20
+ if (length < 1 ) {
21
+ errno = EINVAL;
22
+ perror (" simdjson::allocate_padded_buffer() length argument is less than 1" );
23
+ return nullptr ;
24
+ }
25
+ #endif // SIMDJSON_OK_EMPTY_PADDED_STRING
26
+ #endif // NDEBUG
27
+
28
+ // we could do a simple malloc
29
+ // return (char *) malloc(length + SIMDJSON_PADDING);
30
+ // However, we might as well align to cache lines...
31
+ size_t totalpaddedlength = length + SIMDJSON_PADDING;
32
+ char *padded_buffer = aligned_malloc_char (64 , totalpaddedlength);
33
+
34
+ #ifndef NDEBUG
35
+ if (padded_buffer == nullptr ) {
36
+ errno = EINVAL;
37
+ perror (" simdjson::allocate_padded_buffer() aligned_malloc_char() failed" );
38
+ return nullptr ;
39
+ }
40
+ #endif // NDEBUG
41
+
42
+ memset (padded_buffer + length, 0 , totalpaddedlength - length);
43
+ return padded_buffer;
44
+ } // allocate_padded_buffer
14
45
15
46
// Simple string with padded allocation.
16
47
// We deliberately forbid copies, users should rely on swap or move
17
48
// constructors.
18
- class padded_string {
19
- public:
49
+ struct padded_string final {
50
+
20
51
explicit padded_string () noexcept : viable_size(0 ), data_ptr(nullptr ) {}
52
+
21
53
explicit padded_string (size_t length) noexcept
22
54
: viable_size(length), data_ptr(allocate_padded_buffer(length)) {
23
55
24
56
if (data_ptr != nullptr )
25
57
data_ptr[length] = ' \0 ' ; // easier when you need a c_str
26
58
}
59
+
27
60
explicit padded_string (char *data, size_t length) noexcept
28
61
: viable_size(length), data_ptr(allocate_padded_buffer(length)) {
29
- if (data_ptr != nullptr ) {
62
+ if (data != nullptr ) {
30
63
memcpy (data_ptr, data, length);
31
64
data_ptr[length] = ' \0 ' ; // easier when you need a c_str
32
65
}
33
66
}
34
- padded_string (std::string s) noexcept
35
- : viable_size(s.size()), data_ptr(allocate_padded_buffer(s.size())) {
67
+
68
+ // note: do not pass std::string arguments by value
69
+ padded_string (const std::string & str_ ) noexcept
70
+ : viable_size(str_.size()), data_ptr(allocate_padded_buffer(str_.size())) {
71
+ if (data_ptr != nullptr ) {
72
+ memcpy (data_ptr, str_.data (), str_.size ());
73
+ data_ptr[str_.size ()] = ' \0 ' ; // easier when you need a c_str
74
+ }
75
+ }
76
+
77
+ // note: do pass std::string_view arguments by value
78
+ padded_string (std::string_view sv_) noexcept
79
+ : viable_size(sv_.size()), data_ptr(allocate_padded_buffer(sv_.size())) {
36
80
if (data_ptr != nullptr ) {
37
- memcpy (data_ptr, s .data (), s .size ());
38
- data_ptr[s .size ()] = ' \0 ' ; // easier when you need a c_str
81
+ memcpy (data_ptr, sv_ .data (), sv_ .size ());
82
+ data_ptr[sv_ .size ()] = ' \0 ' ; // easier when you need a c_str
39
83
}
40
84
}
85
+
41
86
padded_string (padded_string &&o) noexcept
42
87
: viable_size(o.viable_size), data_ptr(o.data_ptr) {
43
88
o.data_ptr = nullptr ; // we take ownership
@@ -60,21 +105,26 @@ class padded_string {
60
105
o.viable_size = tmp_viable_size;
61
106
}
62
107
63
- ~padded_string () { aligned_free_char (data_ptr); }
108
+ ~padded_string () {
109
+ aligned_free_char (data_ptr);
110
+ this ->data_ptr = nullptr ;
111
+ }
64
112
65
- size_t size () const { return viable_size; }
113
+ size_t size () const { return viable_size; }
66
114
67
- size_t length () const { return viable_size; }
115
+ size_t length () const { return viable_size; }
68
116
69
- char *data () const { return data_ptr; }
117
+ char *data () const { return data_ptr; }
70
118
71
119
private:
72
120
padded_string &operator =(const padded_string &o) = delete ;
73
121
padded_string (const padded_string &o) = delete ;
74
122
75
- size_t viable_size;
76
- char *data_ptr;
77
- };
123
+ size_t viable_size ;
124
+ char *data_ptr{nullptr };
125
+
126
+ }; // padded_string
127
+
78
128
} // namespace simdjson
79
129
80
130
#endif
0 commit comments