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
12namespace simdjson {
13
14class 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 */
21struct 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
116private:
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 */
132inline 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 */
144inline 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
150inline simdjson::padded_string operator "" _padded(const char *str, size_t len) {
151 return simdjson::padded_string(str, len);
152}
153
154namespace simdjson {
155namespace 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[] (...)).
163inline char *allocate_padded_buffer(size_t length) noexcept;
164
165} // namespace internal
166} // namespace simdjson
167
168#endif // SIMDJSON_PADDED_STRING_H
169