Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
utf8_string.h
1// SPDX-FileCopyrightText: © 2018-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <cstdlib>
7#include <filesystem>
8#include <string>
9#include <utility>
10
11#include "utils/traits.h"
12
13#include <QString>
14#include <QUrl>
15
16#include <fmt/format.h>
17#include <nlohmann/json_fwd.hpp>
18
19namespace juce
20{
21class String;
22class File;
23}
24
28namespace zrythm::utils
29{
30
36class Utf8String
37{
38public:
39 constexpr Utf8String () noexcept = default;
40 constexpr Utf8String (const char8_t * str)
41 : Utf8String (std::u8string_view{ str })
42 {
43 }
44 constexpr Utf8String (std::u8string_view str)
45 : str_ (str.begin (), str.end ())
46 {
47 }
48
49 Utf8String (const Utf8String &) = default;
50 Utf8String (Utf8String &&) = default;
51 Utf8String &operator= (const Utf8String &) = default;
52 Utf8String &operator= (Utf8String &&) = default;
53 ~Utf8String () = default;
54
55 friend void to_json (nlohmann::json &j, const Utf8String &s);
56 friend void from_json (const nlohmann::json &j, Utf8String &s);
57
58 static Utf8String from_path (const std::filesystem::path &path)
59 {
60 return Utf8String{ path.generic_u8string () };
61 }
62 static Utf8String from_qstring (const QString &str)
63 {
64 Utf8String ret;
65 ret.str_ = str.toUtf8 ().toStdString ();
66 return ret;
67 }
68 static Utf8String from_qurl (const QUrl &url)
69 {
70 return from_qstring (url.toLocalFile ());
71 }
72 static Utf8String from_juce_string (const juce::String &str);
73
80 static constexpr Utf8String from_utf8_encoded_string (std::string_view str)
81 {
82 Utf8String ret;
83 ret.str_ = str;
84 return ret;
85 }
86
87 // --- Accessors ---
88 std::string_view view () const noexcept { return str_; }
89 const std::string &str () const noexcept { return str_; }
90 const char * c_str () const noexcept { return str_.c_str (); }
91 auto empty () const noexcept { return str_.empty (); }
92
93 // --- Conversions ---
94 std::filesystem::path to_path () const { return { to_u8_string () }; }
95 std::u8string to_u8_string () const { return { str_.begin (), str_.end () }; }
96 QString to_qstring () const { return QString::fromUtf8 (c_str ()); }
97 juce::String to_juce_string () const;
98 juce::File to_juce_file () const;
99
100 // --- Operators ---
101 explicit operator std::string_view () const noexcept { return view (); }
102 bool operator== (std::string_view other) const noexcept
103 {
104 return view () == other;
105 }
106 Utf8String &operator+= (const Utf8String &other)
107 {
108 str_ += other.str_;
109 return *this;
110 }
111 Utf8String operator+ (const Utf8String &other) const
112 {
113 return Utf8String::from_utf8_encoded_string (str_ + other.str_);
114 }
115
116 operator std::filesystem::path () const { return to_path (); }
117 operator QString () const { return to_qstring (); }
118 friend std::ostream &operator<< (std::ostream &os, const Utf8String &str)
119 {
120 return os << str.view ();
121 }
122
123 // --- Utils ---
124 Utf8String escape_html () const;
125 bool is_ascii () const;
126 bool contains_substr (const Utf8String &substr) const;
127 bool contains_substr_case_insensitive (const Utf8String &substr) const;
128 bool is_equal_ignore_case (const Utf8String &other) const;
129 Utf8String to_upper () const;
130 Utf8String to_lower () const;
131
137 Utf8String convert_to_filename () const;
138
144 Utf8String get_substr_before_suffix (const Utf8String &suffix) const;
145
150 Utf8String remove_until_after_first_match (const Utf8String &match) const;
151
152 Utf8String replace (const Utf8String &from, const Utf8String &to) const;
153
159 Utf8String get_regex_group (const Utf8String &regex, int group) const;
160
168 int
169 get_regex_group_as_int (const Utf8String &regex, int group, int def) const;
170
180 std::pair<int, Utf8String> get_int_after_last_space () const;
181
186 Utf8String symbolify () const;
187
191 Utf8String expand_env_vars () const;
192
193 static Utf8String
194 join (RangeOf<Utf8String> auto &&strings, const Utf8String &delimiter)
195 {
196 auto it = std::ranges::begin (strings);
197 auto end = std::ranges::end (strings);
198 if (it == end)
199 return {};
200 Utf8String result = *it;
201 for (++it; it != end; ++it)
202 {
203 result += delimiter;
204 result += *it;
205 }
206 return result;
207 }
208
209 // --- Comparisons ---
210 friend auto operator<=> (const Utf8String &, const Utf8String &) = default;
211 friend bool operator== (const Utf8String &, const Utf8String &) = default;
212
213private:
214 std::string str_;
215};
216
222class CStringRAII
223{
224public:
225 // Constructor that takes ownership of the given string
226 CStringRAII (char * str) noexcept : str_ (str) { }
227
228 // Destructor
229 ~CStringRAII () { free (str_); }
230
231 // Delete copy constructor and assignment operator
232 CStringRAII (const CStringRAII &) = delete;
233 CStringRAII &operator= (const CStringRAII &) = delete;
234
235 // Move constructor
236 CStringRAII (CStringRAII &&other) noexcept
237 : str_ (std::exchange (other.str_, nullptr))
238 {
239 }
240
241 // Move assignment operator
242 CStringRAII &operator= (CStringRAII &&other) noexcept
243 {
244 if (this != &other)
245 {
246 free (str_);
247 str_ = std::exchange (other.str_, nullptr);
248 }
249 return *this;
250 }
251
252 // Getter for the underlying C-string
253 [[nodiscard]] const char * c_str () const noexcept { return str_; }
254
255 bool empty () const noexcept { return !str_ || strlen (str_) == 0; }
256
257 Utf8String to_utf8_string () const
258 {
260 }
261
262private:
263 char * str_;
264};
265
266}; // namespace zrythm::utils
267
268// Formatter for Utf8String
269template <>
270struct fmt::formatter<zrythm::utils::Utf8String>
271 : fmt::formatter<std::string_view>
272{
273 auto format (const zrythm::utils::Utf8String &s, format_context &ctx) const
274 -> format_context::iterator
275 {
276 return fmt::formatter<std::string_view>::format (s.view (), ctx);
277 }
278};
279
280// Hasher for Utf8String
281static inline size_t
282qHash (const zrythm::utils::Utf8String &t, size_t seed = 0) noexcept
283{
284 return qHash (t.view (), seed); // <-- qHash used as public API
285}
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:37
Utf8String get_substr_before_suffix(const Utf8String &suffix) const
Removes the suffix starting from suffix from full_str and returns a newly allocated string.
std::pair< int, Utf8String > get_int_after_last_space() const
Returns the integer found at the end of a string like "My String 3" -> 3, or -1 if no number is found...
Utf8String expand_env_vars() const
Expands environment variables enclosed in ${} in the given string.
Utf8String get_regex_group(const Utf8String &regex, int group) const
Gets the string in the given regex group.
Utf8String convert_to_filename() const
Returns a filename-safe version of the given string.
Utf8String symbolify() const
Returns a new string with only ASCII alphanumeric characters and replaces the rest with underscore.
Utf8String remove_until_after_first_match(const Utf8String &match) const
Removes everything up to and including the first match of match from the start of the string.
int get_regex_group_as_int(const Utf8String &regex, int group, int def) const
Gets the string in the given regex group as an integer.
static constexpr Utf8String from_utf8_encoded_string(std::string_view str)
Construct from a std::string_view that we are 100% sure is UTF8-encoded.
Definition utf8_string.h:80
String utilities.