1 | #ifndef SIMDJSON_PADDED_STRING_H |
2 | #define SIMDJSON_PADDED_STRING_H |
3 | |
4 | #include "simdjson/portability.h" |
5 | #include "simdjson/common_defs.h" // for SIMDJSON_PADDING |
6 | #include "simdjson/error.h" |
7 | #include <cstring> |
8 | #include <memory> |
9 | #include <string> |
10 | #include <ostream> |
11 | |
12 | namespace simdjson { |
13 | |
14 | class padded_string_view; |
15 | |
16 | /** |
17 | * String with extra allocation for ease of use with parser::parse() |
18 | * |
19 | * This is a move-only class, it cannot be copied. |
20 | */ |
21 | struct padded_string final { |
22 | |
23 | /** |
24 | * Create a new, empty padded string. |
25 | */ |
26 | explicit inline padded_string() noexcept; |
27 | /** |
28 | * Create a new padded string buffer. |
29 | * |
30 | * @param length the size of the string. |
31 | */ |
32 | explicit inline padded_string(size_t length) noexcept; |
33 | /** |
34 | * Create a new padded string by copying the given input. |
35 | * |
36 | * @param data the buffer to copy |
37 | * @param length the number of bytes to copy |
38 | */ |
39 | explicit inline padded_string(const char *data, size_t length) noexcept; |
40 | /** |
41 | * Create a new padded string by copying the given input. |
42 | * |
43 | * @param str_ the string to copy |
44 | */ |
45 | inline padded_string(const std::string & str_ ) noexcept; |
46 | /** |
47 | * Create a new padded string by copying the given input. |
48 | * |
49 | * @param sv_ the string to copy |
50 | */ |
51 | inline padded_string(std::string_view sv_) noexcept; |
52 | /** |
53 | * Move one padded string into another. |
54 | * |
55 | * The original padded string will be reduced to zero capacity. |
56 | * |
57 | * @param o the string to move. |
58 | */ |
59 | inline padded_string(padded_string &&o) noexcept; |
60 | /** |
61 | * Move one padded string into another. |
62 | * |
63 | * The original padded string will be reduced to zero capacity. |
64 | * |
65 | * @param o the string to move. |
66 | */ |
67 | inline padded_string &operator=(padded_string &&o) noexcept; |
68 | inline void swap(padded_string &o) noexcept; |
69 | ~padded_string() noexcept; |
70 | |
71 | /** |
72 | * The length of the string. |
73 | * |
74 | * Does not include padding. |
75 | */ |
76 | size_t size() const noexcept; |
77 | |
78 | /** |
79 | * The length of the string. |
80 | * |
81 | * Does not include padding. |
82 | */ |
83 | size_t length() const noexcept; |
84 | |
85 | /** |
86 | * The string data. |
87 | **/ |
88 | const char *data() const noexcept; |
89 | const uint8_t *u8data() const noexcept { return static_cast<const uint8_t*>(static_cast<const void*>(data_ptr));} |
90 | |
91 | /** |
92 | * The string data. |
93 | **/ |
94 | char *data() noexcept; |
95 | |
96 | /** |
97 | * Create a std::string_view with the same content. |
98 | */ |
99 | operator std::string_view() const; |
100 | |
101 | /** |
102 | * Create a padded_string_view with the same content. |
103 | */ |
104 | operator padded_string_view() const noexcept; |
105 | |
106 | /** |
107 | * Load this padded string from a file. |
108 | * |
109 | * @return IO_ERROR on error. Be mindful that on some 32-bit systems, |
110 | * the file size might be limited to 2 GB. |
111 | * |
112 | * @param path the path to the file. |
113 | **/ |
114 | inline static simdjson_result<padded_string> load(std::string_view path) noexcept; |
115 | |
116 | private: |
117 | padded_string &operator=(const padded_string &o) = delete; |
118 | padded_string(const padded_string &o) = delete; |
119 | |
120 | size_t viable_size{0}; |
121 | char *data_ptr{nullptr}; |
122 | |
123 | }; // padded_string |
124 | |
125 | /** |
126 | * Send padded_string instance to an output stream. |
127 | * |
128 | * @param out The output stream. |
129 | * @param s The padded_string instance. |
130 | * @throw if there is an error with the underlying output stream. simdjson itself will not throw. |
131 | */ |
132 | inline std::ostream& operator<<(std::ostream& out, const padded_string& s) { return out << s.data(); } |
133 | |
134 | #if SIMDJSON_EXCEPTIONS |
135 | /** |
136 | * Send padded_string instance to an output stream. |
137 | * |
138 | * @param out The output stream. |
139 | * @param s The padded_string instance. |
140 | * @throw simdjson_error if the result being printed has an error. If there is an error with the |
141 | * underlying output stream, that error will be propagated (simdjson_error will not be |
142 | * thrown). |
143 | */ |
144 | inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string> &s) noexcept(false) { return out << s.value(); } |
145 | #endif |
146 | |
147 | } // namespace simdjson |
148 | |
149 | // This is deliberately outside of simdjson so that people get it without having to use the namespace |
150 | inline simdjson::padded_string operator "" _padded(const char *str, size_t len) { |
151 | return simdjson::padded_string(str, len); |
152 | } |
153 | |
154 | namespace simdjson { |
155 | namespace internal { |
156 | |
157 | // The allocate_padded_buffer function is a low-level function to allocate memory |
158 | // with padding so we can read past the "length" bytes safely. It is used by |
159 | // the padded_string class automatically. It returns nullptr in case |
160 | // of error: the caller should check for a null pointer. |
161 | // The length parameter is the maximum size in bytes of the string. |
162 | // The caller is responsible to free the memory (e.g., delete[] (...)). |
163 | inline char *allocate_padded_buffer(size_t length) noexcept; |
164 | |
165 | } // namespace internal |
166 | } // namespace simdjson |
167 | |
168 | #endif // SIMDJSON_PADDED_STRING_H |
169 | |