Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
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.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) { j = s.str (); }
57 friend void from_json (const nlohmann::json &j, Utf8String &s)
58 {
59 s = from_utf8_encoded_string (j.get<std::string> ());
60 }
61
62 static Utf8String from_path (const fs::path &path)
63 {
64 return Utf8String{ path.generic_u8string () };
65 }
66 static Utf8String from_qstring (const QString &str)
67 {
68 Utf8String ret;
69 ret.str_ = str.toUtf8 ().toStdString ();
70 return ret;
71 }
72 static Utf8String from_qurl (const QUrl &url)
73 {
74 return from_qstring (url.toLocalFile ());
75 }
76 static Utf8String from_juce_string (const juce::String &str);
77
84 static constexpr Utf8String from_utf8_encoded_string (std::string_view str)
85 {
86 Utf8String ret;
87 ret.str_ = str;
88 return ret;
89 }
90
91 // --- Accessors ---
92 std::string_view view () const noexcept { return str_; }
93 const std::string &str () const noexcept { return str_; }
94 const char * c_str () const noexcept { return str_.c_str (); }
95 auto empty () const noexcept { return str_.empty (); }
96
97 // --- Conversions ---
98 fs::path to_path () const { return { to_u8_string () }; }
99 std::u8string to_u8_string () const { return { str_.begin (), str_.end () }; }
100 QString to_qstring () const { return QString::fromUtf8 (c_str ()); }
101 juce::String to_juce_string () const;
102 juce::File to_juce_file () const;
103
104 // --- Operators ---
105 explicit operator std::string_view () const noexcept { return view (); }
106 bool operator== (std::string_view other) const noexcept
107 {
108 return view () == other;
109 }
110 Utf8String &operator+= (const Utf8String &other)
111 {
112 str_ += other.str_;
113 return *this;
114 }
115 Utf8String operator+ (const Utf8String &other) const
116 {
117 return Utf8String::from_utf8_encoded_string (str_ + other.str_);
118 }
119
120 operator fs::path () const { return to_path (); }
121 operator QString () const { return to_qstring (); }
122 friend std::ostream &operator<< (std::ostream &os, const Utf8String &str)
123 {
124 return os << str.view ();
125 }
126
127 // --- Utils ---
128 Utf8String escape_html () const;
129 bool is_ascii () const;
130 bool contains_substr (const Utf8String &substr) const;
131 bool contains_substr_case_insensitive (const Utf8String &substr) const;
132 bool is_equal_ignore_case (const Utf8String &other) const;
133 Utf8String to_upper () const;
134 Utf8String to_lower () const;
135
141 Utf8String convert_to_filename () const;
142
148 Utf8String get_substr_before_suffix (const Utf8String &suffix) const;
149
154 Utf8String remove_until_after_first_match (const Utf8String &match) const;
155
156 Utf8String replace (const Utf8String &from, const Utf8String &to) const;
157
163 Utf8String get_regex_group (const Utf8String &regex, int group) const;
164
172 int
173 get_regex_group_as_int (const Utf8String &regex, int group, int def) const;
174
184 std::pair<int, Utf8String> get_int_after_last_space () const;
185
190 Utf8String symbolify () const;
191
195 Utf8String expand_env_vars () const;
196
197 static Utf8String
198 join (const RangeOf<Utf8String> auto &strings, const Utf8String &delimiter)
199 {
201 fmt::format (
202 "{}",
203 fmt::join (
204 std::views::transform (strings, &Utf8String::view),
205 delimiter.view ())));
206 }
207
208 // --- Comparisons ---
209 friend auto operator<=> (const Utf8String &a, const Utf8String &b) noexcept
210 {
211 return a.str_ <=> b.str_;
212 }
213 friend bool operator== (const Utf8String &a, const Utf8String &b) noexcept
214 {
215 return a.str_ == b.str_;
216 }
217
218private:
219 std::string str_;
220};
221
227class CStringRAII
228{
229public:
230 // Constructor that takes ownership of the given string
231 CStringRAII (char * str) noexcept : str_ (str) { }
232
233 // Destructor
234 ~CStringRAII () { free (str_); }
235
236 // Delete copy constructor and assignment operator
237 CStringRAII (const CStringRAII &) = delete;
238 CStringRAII &operator= (const CStringRAII &) = delete;
239
240 // Move constructor
241 CStringRAII (CStringRAII &&other) noexcept
242 : str_ (std::exchange (other.str_, nullptr))
243 {
244 }
245
246 // Move assignment operator
247 CStringRAII &operator= (CStringRAII &&other) noexcept
248 {
249 if (this != &other)
250 {
251 free (str_);
252 str_ = std::exchange (other.str_, nullptr);
253 }
254 return *this;
255 }
256
257 // Getter for the underlying C-string
258 [[nodiscard]] const char * c_str () const noexcept { return str_; }
259
260 bool empty () const noexcept { return !str_ || strlen (str_) == 0; }
261
262 Utf8String to_utf8_string () const
263 {
265 }
266
267private:
268 char * str_;
269};
270
271}; // namespace zrythm::utils
272
273// Formatter for Utf8String
274template <>
275struct fmt::formatter<zrythm::utils::Utf8String>
276 : fmt::formatter<std::string_view>
277{
278 template <typename FormatContext>
279 auto format (const zrythm::utils::Utf8String &s, FormatContext &ctx) const
280 {
281 return fmt::formatter<std::string_view>::format (s.view (), ctx);
282 }
283};
284
285// Hasher for Utf8String
286static inline size_t
287qHash (const zrythm::utils::Utf8String &t, size_t seed = 0) noexcept
288{
289 return qHash (t.view (), seed); // <-- qHash used as public API
290}
Lightweight UTF-8 string wrapper with safe conversions.
Definition 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 string.h:84
String utilities.
Definition algorithms.h:12