1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
3 | |
4 | #pragma once |
5 | #include <string_view> |
6 | #include "slint_string_internal.h" |
7 | |
8 | namespace slint { |
9 | |
10 | /// A string type used by the Slint run-time. |
11 | /// |
12 | /// SharedString uses implicit data sharing to make it efficient to pass around copies. When |
13 | /// copying, a reference to the data is cloned, not the data itself. |
14 | /// |
15 | /// The class provides constructors from std::string_view as well as the automatic conversion to |
16 | /// a std::string_view. |
17 | /// |
18 | /// For convenience, it's also possible to convert a number to a string using |
19 | /// SharedString::from_number(double). |
20 | /// |
21 | /// Under the hood the string data is UTF-8 encoded and it is always terminated with a null |
22 | /// character. |
23 | struct SharedString |
24 | { |
25 | /// Creates an empty default constructed string. |
26 | SharedString() { cbindgen_private::slint_shared_string_from_bytes(out: this, bytes: "" , len: 0); } |
27 | /// Creates a new SharedString from the string view \a s. The underlying string data |
28 | /// is copied. |
29 | SharedString(std::string_view s) |
30 | { |
31 | cbindgen_private::slint_shared_string_from_bytes(out: this, bytes: s.data(), len: s.size()); |
32 | } |
33 | /// Creates a new SharedString from the null-terminated string pointer \a s. The underlying |
34 | /// string data is copied. It is assumed that the string is UTF-8 encoded. |
35 | SharedString(const char *s) : SharedString(std::string_view(s)) { } |
36 | /// Creates a new SharedString from the null-terminated string pointer \a s. The underlying |
37 | /// string data is copied. |
38 | SharedString(const char8_t *s) : SharedString(reinterpret_cast<const char *>(s)) { } |
39 | /// Creates a new SharedString from the string view \a s. The underlying string data is copied. |
40 | SharedString(std::u8string_view s) |
41 | { |
42 | cbindgen_private::slint_shared_string_from_bytes( |
43 | out: this, bytes: reinterpret_cast<const char *>(s.data()), len: s.size()); |
44 | } |
45 | /// Creates a new SharedString from \a other. |
46 | SharedString(const SharedString &other) |
47 | { |
48 | cbindgen_private::slint_shared_string_clone(out: this, ss: &other); |
49 | } |
50 | /// Destroys this SharedString and frees the memory if this is the last instance |
51 | /// referencing it. |
52 | ~SharedString() { cbindgen_private::slint_shared_string_drop(ss: this); } |
53 | /// Assigns \a other to this string and returns a reference to this string. |
54 | SharedString &operator=(const SharedString &other) |
55 | { |
56 | cbindgen_private::slint_shared_string_drop(ss: this); |
57 | cbindgen_private::slint_shared_string_clone(out: this, ss: &other); |
58 | return *this; |
59 | } |
60 | /// Assigns the string view \a s to this string and returns a reference to this string. |
61 | /// The underlying string data is copied. It is assumed that the string is UTF-8 encoded. |
62 | SharedString &operator=(std::string_view s) |
63 | { |
64 | cbindgen_private::slint_shared_string_drop(ss: this); |
65 | cbindgen_private::slint_shared_string_from_bytes(out: this, bytes: s.data(), len: s.size()); |
66 | return *this; |
67 | } |
68 | /// Assigns null-terminated string pointer \a s to this string and returns a reference |
69 | /// to this string. The underlying string data is copied. It is assumed that the string |
70 | /// is UTF-8 encoded. |
71 | SharedString &operator=(const char *s) { return *this = std::string_view(s); } |
72 | |
73 | /// Move-assigns \a other to this SharedString instance. |
74 | SharedString &operator=(SharedString &&other) |
75 | { |
76 | std::swap(a&: inner, b&: other.inner); |
77 | return *this; |
78 | } |
79 | |
80 | /// Provides a view to the string data. The returned view is only valid as long as at |
81 | /// least this SharedString exists. |
82 | operator std::string_view() const { return cbindgen_private::slint_shared_string_bytes(ss: this); } |
83 | /// Provides a raw pointer to the string data. The returned pointer is only valid as long as at |
84 | /// least this SharedString exists. |
85 | auto data() const -> const char * { return cbindgen_private::slint_shared_string_bytes(ss: this); } |
86 | /// Size of the string, in bytes. This excludes the terminating null character. |
87 | std::size_t size() const { return std::string_view(*this).size(); } |
88 | |
89 | /// Returns a pointer to the first character. It is only safe to dereference the pointer if the |
90 | /// string contains at least one character. |
91 | const char *begin() const { return data(); } |
92 | /// Returns a point past the last character of the string. It is not safe to dereference the |
93 | /// pointer, but it is suitable for comparison. |
94 | const char *end() const |
95 | { |
96 | std::string_view view(*this); |
97 | return view.data() + view.size(); |
98 | } |
99 | |
100 | /// \return true if the string contains no characters; false otherwise. |
101 | bool empty() const { return std::string_view(*this).empty(); } |
102 | |
103 | /// \return true if the string starts with the specified prefix string; false otherwise |
104 | bool starts_with(std::string_view prefix) const |
105 | { |
106 | return std::string_view(*this).substr(pos: 0, n: prefix.size()) == prefix; |
107 | } |
108 | |
109 | /// \return true if the string ends with the specified prefix string; false otherwise |
110 | bool ends_with(std::string_view prefix) const |
111 | { |
112 | std::string_view self_view(*this); |
113 | return self_view.size() >= prefix.size() |
114 | && self_view.compare(pos1: self_view.size() - prefix.size(), n1: std::string_view::npos, |
115 | str: prefix) |
116 | == 0; |
117 | } |
118 | |
119 | /// Creates a new SharedString from the given number \a n. The string representation of the |
120 | /// number uses a minimal formatting scheme: If \a n has no fractional part, the number will be |
121 | /// formatted as an integer. |
122 | /// |
123 | /// For example: |
124 | /// \code |
125 | /// auto str = slint::SharedString::from_number(42); // creates "42" |
126 | /// auto str2 = slint::SharedString::from_number(100.5) // creates "100.5" |
127 | /// \endcode |
128 | static SharedString from_number(double n) { return SharedString(n); } |
129 | |
130 | /// Returns the lowercase equivalent of this string, as a new SharedString. |
131 | /// |
132 | /// For example: |
133 | /// \code |
134 | /// auto str = slint::SharedString("Hello"); |
135 | /// auto str2 = str.to_lowercase(); // creates "hello" |
136 | /// \endcode |
137 | SharedString to_lowercase() const |
138 | { |
139 | auto out = SharedString(); |
140 | cbindgen_private::slint_shared_string_to_lowercase(out: &out, ss: this); |
141 | return out; |
142 | } |
143 | |
144 | /// Returns the uppercase equivalent of this string, as a new SharedString. |
145 | /// |
146 | /// For example: |
147 | /// \code |
148 | /// auto str = slint::SharedString("Hello"); |
149 | /// auto str2 = str.to_uppercase(); // creates "HELLO" |
150 | /// \endcode |
151 | SharedString to_uppercase() const |
152 | { |
153 | auto out = SharedString(); |
154 | cbindgen_private::slint_shared_string_to_uppercase(out: &out, ss: this); |
155 | return out; |
156 | } |
157 | |
158 | /// Returns true if \a a is equal to \a b; otherwise returns false. |
159 | friend bool operator==(const SharedString &a, const SharedString &b) |
160 | { |
161 | return std::string_view(a) == std::string_view(b); |
162 | } |
163 | /// Returns true if \a a is not equal to \a b; otherwise returns false. |
164 | friend bool operator!=(const SharedString &a, const SharedString &b) |
165 | { |
166 | return std::string_view(a) != std::string_view(b); |
167 | } |
168 | |
169 | /// Returns true if \a a is lexicographically less than \a b; false otherwise. |
170 | friend bool operator<(const SharedString &a, const SharedString &b) |
171 | { |
172 | return std::string_view(a) < std::string_view(b); |
173 | } |
174 | /// Returns true if \a a is lexicographically less or equal than \a b; false otherwise. |
175 | friend bool operator<=(const SharedString &a, const SharedString &b) |
176 | { |
177 | return std::string_view(a) <= std::string_view(b); |
178 | } |
179 | /// Returns true if \a a is lexicographically greater than \a b; false otherwise. |
180 | friend bool operator>(const SharedString &a, const SharedString &b) |
181 | { |
182 | return std::string_view(a) > std::string_view(b); |
183 | } |
184 | /// Returns true if \a a is lexicographically greater or equal than \a b; false otherwise. |
185 | friend bool operator>=(const SharedString &a, const SharedString &b) |
186 | { |
187 | return std::string_view(a) >= std::string_view(b); |
188 | } |
189 | |
190 | /// Writes the \a shared_string to the specified \a stream and returns a reference to the |
191 | /// stream. |
192 | friend std::ostream &operator<<(std::ostream &stream, const SharedString &shared_string) |
193 | { |
194 | return stream << std::string_view(shared_string); |
195 | } |
196 | |
197 | /// Concatenates \a a and \a and returns the result as a new SharedString. |
198 | friend SharedString operator+(const SharedString &a, std::string_view b) |
199 | { |
200 | SharedString a2 = a; |
201 | return a2 += b; |
202 | } |
203 | /// Move-concatenates \a b to \a and returns a reference to \a a. |
204 | friend SharedString operator+(SharedString &&a, std::string_view b) |
205 | { |
206 | a += b; |
207 | return a; |
208 | } |
209 | /// Appends \a other to this string and returns a reference to this. |
210 | SharedString &operator+=(std::string_view other) |
211 | { |
212 | cbindgen_private::slint_shared_string_append(self_: this, bytes: other.data(), len: other.size()); |
213 | return *this; |
214 | } |
215 | |
216 | private: |
217 | /// Use SharedString::from_number |
218 | explicit SharedString(double n) { cbindgen_private::slint_shared_string_from_number(out: this, n); } |
219 | void *inner; // opaque |
220 | }; |
221 | |
222 | namespace private_api { |
223 | inline cbindgen_private::Slice<uint8_t> string_to_slice(std::string_view str) |
224 | { |
225 | return cbindgen_private::Slice<uint8_t> { |
226 | const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(str.data())), str.size() |
227 | }; |
228 | } |
229 | } |
230 | |
231 | } |
232 | |