Loading...
Searching...
No Matches
StringSTL.h
Go to the documentation of this file.
1/**************************************************************************************************
2 * This file is a part of Ultralight. *
3 * *
4 * See <https://ultralig.ht> for licensing and more. *
5 * *
6 * (C) 2024 Ultralight, Inc. *
7 **************************************************************************************************/
8///
9/// @file StringSTL.h
10///
11/// STL compatibility header for ultralight::String.
12///
13/// `#include <Ultralight/StringSTL.h>`
14///
15/// This optional header provides utility functions for converting between ultralight::String,
16/// std::string, and std::string_view. It also provides support for using ultralight::String
17/// with standard library containers and stream operators.
18///
19/// @pre This header requires C++17 or later.
20///
21/// ## Example
22///
23/// ```cpp
24/// #include <Ultralight/StringSTL.h>
25/// #include <string>
26/// #include <iostream>
27///
28/// ultralight::String myStr("Hello, world!");
29///
30/// // Convert ultralight::String to std::string
31/// std::string stdStr = ultralight::Convert(myStr);
32///
33/// // Convert std::string to ultralight::String
34/// ultralight::String backToUl = ultralight::Convert(stdStr);
35///
36/// // Print ultralight::String to std::cout
37/// std::cout << myStr << std::endl;
38/// ```
39///
40#pragma once
41#include <Ultralight/String.h>
42#include <string>
43#include <string_view>
44#include <type_traits>
45
46namespace ultralight {
47
48///
49/// Trait to check if a type is a supported string-like type.
50///
51template <typename T>
52struct is_string_type : std::false_type {};
53
54template <> struct is_string_type<String> : std::true_type {};
55template <> struct is_string_type<std::string> : std::true_type {};
56template <> struct is_string_type<std::string_view> : std::true_type {};
57template <> struct is_string_type<const char*> : std::true_type {};
58
59///
60/// Convert between string types.
61///
62/// This function provides efficient conversion between different string types.
63/// It supports ultralight::String, std::string, std::string_view, and const char*.
64///
65/// The following type conversions are automatically deduced (no template argument needed):
66/// - ultralight::String -> std::string
67/// - std::string -> ultralight::String
68/// - std::string_view -> ultralight::String
69/// - const char* -> ultralight::String
70///
71/// For explicit conversion to std::string_view, use Convert<std::string_view>().
72///
73/// @tparam To The target string type (optional, deduced in common cases)
74/// @tparam From The source string type (optional)
75///
76/// @param from The string to convert
77///
78/// @return The converted string in the target type
79///
80/// ## Example
81///
82/// ```cpp
83/// ultralight::String myStr("Hello, world!");
84///
85/// // ultralight::String -> std::string
86/// std::string stdStr = ultralight::Convert(myStr);
87///
88/// // ultralight::String -> std::string_view
89/// std::string_view svStr = ultralight::Convert<std::string_view>(myStr);
90///
91/// // std::string -> ultralight::String
92/// ultralight::String backToUl = ultralight::Convert(stdStr);
93///
94/// // std::string_view -> ultralight::String
95/// ultralight::String fromView = ultralight::Convert(std::string_view("View"));
96/// ```
97///
98template <typename To = void, typename From>
99auto Convert(const From& from) {
101 "Convert only supports String, std::string, std::string_view, and const char*");
102
103 if constexpr (std::is_same_v<To, void>) {
104 // Automatic deduction
105 if constexpr (std::is_same_v<From, String>) {
106 return std::string(from.utf8().data(), from.utf8().length());
107 } else if constexpr (std::is_same_v<From, std::string> ||
108 std::is_same_v<From, std::string_view>) {
109 return String(from.data(), from.length());
110 } else if constexpr (std::is_same_v<From, const char*>) {
111 return String(from); // String constructor handles null-termination
112 } else {
113 // This case should never be reached due to the static_assert
114 return From{};
115 }
116 } else {
117 // Explicit conversion
118 static_assert(is_string_type<To>::value,
119 "Convert only supports String, std::string, std::string_view, and const char*");
120
121 if constexpr (std::is_same_v<To, From>) {
122 return from;
123 } else if constexpr (std::is_same_v<To, String>) {
124 if constexpr (std::is_same_v<From, const char*>) {
125 return String(from); // String constructor handles null-termination
126 } else {
127 return String(from.data(), from.length());
128 }
129 } else if constexpr (std::is_same_v<To, std::string>) {
130 if constexpr (std::is_same_v<From, String>) {
131 return std::string(from.utf8().data(), from.utf8().length());
132 } else if constexpr (std::is_same_v<From, const char*>) {
133 return std::string(from); // std::string constructor handles null-termination
134 } else {
135 return std::string(from);
136 }
137 } else if constexpr (std::is_same_v<To, std::string_view>) {
138 if constexpr (std::is_same_v<From, String>) {
139 return std::string_view(from.utf8().data(), from.utf8().length());
140 } else if constexpr (std::is_same_v<From, const char*>) {
141 return std::string_view(from); // std::string_view constructor handles null-termination
142 } else {
143 return std::string_view(from);
144 }
145 } else if constexpr (std::is_same_v<To, const char*>) {
146 static_assert(!std::is_same_v<To, const char*>,
147 "Direct conversion to const char* is not supported due to ownership issues. "
148 "Convert to String, std::string, or std::string_view instead.");
149 } else {
150 // This case should never be reached due to the static_assert
151 return To{};
152 }
153 }
154}
155
156} // namespace ultralight
157
158namespace std {
159
160///
161/// Hash specialization for ultralight::String
162///
163template<>
164struct hash<ultralight::String> {
165 size_t operator()(const ultralight::String& str) const {
166 return str.Hash();
167 }
168};
169
170} // namespace std
171
172///
173/// Stream output operator for ultralight::String.
174///
175/// @param os The output stream.
176//
177/// @param str The string to output.
178///
179/// @return The output stream.
180///
181inline std::ostream& operator<<(std::ostream& os, const ultralight::String& str) {
182 return os << ultralight::Convert<std::string_view>(str);
183}
184
185///
186/// Stream input operator for ultralight::String.
187///
188/// @param is The input stream.
189///
190/// @param str The string to input into.
191///
192/// @return The input stream.
193///
194inline std::istream& operator>>(std::istream& is, ultralight::String& str) {
195 std::string temp;
196 is >> temp;
198 return is;
199}
std::ostream & operator<<(std::ostream &os, const ultralight::String &str)
Stream output operator for ultralight::String.
Definition StringSTL.h:181
std::istream & operator>>(std::istream &is, ultralight::String &str)
Stream input operator for ultralight::String.
Definition StringSTL.h:194
Unicode string container with conversions for UTF-8, UTF-16, and UTF-32.
Definition String.h:34
size_t Hash() const
Hash function.
Definition StringSTL.h:158
Definition App.h:14
auto Convert(const From &from)
Convert between string types.
Definition StringSTL.h:99
size_t operator()(const ultralight::String &str) const
Definition StringSTL.h:165
Trait to check if a type is a supported string-like type.
Definition StringSTL.h:52