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 <string>
8#include <utility>
9
10#include "utils/traits.h"
11#include "utils/types.h"
12
13#include <QString>
14#include <QUrl>
15
16#include <fmt/format.h>
17#include <fmt/ranges.h>
18#include <nlohmann/json_fwd.hpp>
19
20namespace juce
21{
22class String;
23class File;
24}
25
29namespace zrythm::utils
30{
31
37class Utf8String
38{
39public:
40 constexpr Utf8String () noexcept = default;
41 constexpr Utf8String (const char8_t * str)
42 : Utf8String (std::u8string_view{ str })
43 {
44 }
45 constexpr Utf8String (std::u8string_view str)
46 : str_ (str.begin (), str.end ())
47 {
48 }
49
50 Utf8String (const Utf8String &) = default;
51 Utf8String (Utf8String &&) = default;
52 Utf8String &operator= (const Utf8String &) = default;
53 Utf8String &operator= (Utf8String &&) = default;
54 ~Utf8String () = default;
55
56 friend void to_json (nlohmann::json &j, const Utf8String &s);
57 friend void from_json (const nlohmann::json &j, Utf8String &s);
58
59 static Utf8String from_path (const fs::path &path)
60 {
61 return Utf8String{ path.generic_u8string () };
62 }
63 static Utf8String from_qstring (const QString &str)
64 {
65 Utf8String ret;
66 ret.str_ = str.toUtf8 ().toStdString ();
67 return ret;
68 }
69 static Utf8String from_qurl (const QUrl &url)
70 {
71 return from_qstring (url.toLocalFile ());
72 }
73 static Utf8String from_juce_string (const juce::String &str);
74
81 static constexpr Utf8String from_utf8_encoded_string (std::string_view str)
82 {
83 Utf8String ret;
84 ret.str_ = str;
85 return ret;
86 }
87
88 // --- Accessors ---
89 std::string_view view () const noexcept { return str_; }
90 const std::string &str () const noexcept { return str_; }
91 const char * c_str () const noexcept { return str_.c_str (); }
92 auto empty () const noexcept { return str_.empty (); }
93
94 // --- Conversions ---
95 fs::path to_path () const { return { to_u8_string () }; }
96 std::u8string to_u8_string () const { return { str_.begin (), str_.end () }; }
97 QString to_qstring () const { return QString::fromUtf8 (c_str ()); }
98 juce::String to_juce_string () const;
99 juce::File to_juce_file () const;
100
101 // --- Operators ---
102 explicit operator std::string_view () const noexcept { return view (); }
103 bool operator== (std::string_view other) const noexcept
104 {
105 return view () == other;
106 }
107 Utf8String &operator+= (const Utf8String &other)
108 {
109 str_ += other.str_;
110 return *this;
111 }
112 Utf8String operator+ (const Utf8String &other) const
113 {
114 return Utf8String::from_utf8_encoded_string (str_ + other.str_);
115 }
116
117 operator fs::path () const { return to_path (); }
118 operator QString () const { return to_qstring (); }
119 friend std::ostream &operator<< (std::ostream &os, const Utf8String &str)
120 {
121 return os << str.view ();
122 }
123
124 // --- Utils ---
125 Utf8String escape_html () const;
126 bool is_ascii () const;
127 bool contains_substr (const Utf8String &substr) const;
128 bool contains_substr_case_insensitive (const Utf8String &substr) const;
129 bool is_equal_ignore_case (const Utf8String &other) const;
130 Utf8String to_upper () const;
131 Utf8String to_lower () const;
132
138 Utf8String convert_to_filename () const;
139
145 Utf8String get_substr_before_suffix (const Utf8String &suffix) const;
146
151 Utf8String remove_until_after_first_match (const Utf8String &match) const;
152
153 Utf8String replace (const Utf8String &from, const Utf8String &to) const;
154
160 Utf8String get_regex_group (const Utf8String &regex, int group) const;
161
169 int
170 get_regex_group_as_int (const Utf8String &regex, int group, int def) const;
171
181 std::pair<int, Utf8String> get_int_after_last_space () const;
182
187 Utf8String symbolify () const;
188
192 Utf8String expand_env_vars () const;
193
194 static Utf8String
195 join (const RangeOf<Utf8String> auto &strings, const Utf8String &delimiter)
196 {
198 fmt::format (
199 "{}",
200 fmt::join (
201 std::views::transform (strings, &Utf8String::view),
202 delimiter.view ())));
203 }
204
205 // --- Comparisons ---
206 friend auto operator<=> (const Utf8String &a, const Utf8String &b) noexcept
207 {
208 return a.str_ <=> b.str_;
209 }
210 friend bool operator== (const Utf8String &a, const Utf8String &b) noexcept
211 {
212 return a.str_ == b.str_;
213 }
214
215private:
216 std::string str_;
217};
218
224class CStringRAII
225{
226public:
227 // Constructor that takes ownership of the given string
228 CStringRAII (char * str) noexcept : str_ (str) { }
229
230 // Destructor
231 ~CStringRAII () { free (str_); }
232
233 // Delete copy constructor and assignment operator
234 CStringRAII (const CStringRAII &) = delete;
235 CStringRAII &operator= (const CStringRAII &) = delete;
236
237 // Move constructor
238 CStringRAII (CStringRAII &&other) noexcept
239 : str_ (std::exchange (other.str_, nullptr))
240 {
241 }
242
243 // Move assignment operator
244 CStringRAII &operator= (CStringRAII &&other) noexcept
245 {
246 if (this != &other)
247 {
248 free (str_);
249 str_ = std::exchange (other.str_, nullptr);
250 }
251 return *this;
252 }
253
254 // Getter for the underlying C-string
255 [[nodiscard]] const char * c_str () const noexcept { return str_; }
256
257 bool empty () const noexcept { return !str_ || strlen (str_) == 0; }
258
259 Utf8String to_utf8_string () const
260 {
262 }
263
264private:
265 char * str_;
266};
267
268}; // namespace zrythm::utils
269
270// Formatter for Utf8String
271template <>
272struct fmt::formatter<zrythm::utils::Utf8String>
273 : fmt::formatter<std::string_view>
274{
275 template <typename FormatContext>
276 auto format (const zrythm::utils::Utf8String &s, FormatContext &ctx) const
277 {
278 return fmt::formatter<std::string_view>::format (s.view (), ctx);
279 }
280};
281
282// Hasher for Utf8String
283static inline size_t
284qHash (const zrythm::utils::Utf8String &t, size_t seed = 0) noexcept
285{
286 return qHash (t.view (), seed); // <-- qHash used as public API
287}
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38
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:81
String utilities.
Definition algorithms.h:12