[libc++] Add an option to disable wide character support in libc++
Some embedded platforms do not wish to support the C library functionality
for handling wchar_t because they have no use for it. It makes sense for
libc++ to work properly on those platforms, so this commit adds a carve-out
of functionality for wchar_t.
Unfortunately, unlike some other carve-outs (e.g. random device), this
patch touches several parts of the library. However, despite the wide
impact of this patch, I still think it is important to support this
configuration since it makes it much simpler to port libc++ to some
embedded platforms.
Differential Revision: https://reviews.llvm.org/D111265
diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp
index 012b2ea..c8dae34 100644
--- a/libcxx/src/string.cpp
+++ b/libcxx/src/string.cpp
@@ -9,13 +9,16 @@
#include "string"
#include "charconv"
#include "cstdlib"
-#include "cwchar"
#include "cerrno"
#include "limits"
#include "stdexcept"
#include <stdio.h>
#include "__debug"
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+# include "cwchar"
+#endif
+
_LIBCPP_BEGIN_NAMESPACE_STD
void __basic_string_common<true>::__throw_length_error() const {
@@ -28,11 +31,15 @@
#define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__;
#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
-_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
-_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
+ _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
+# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+ _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
+# endif
#else
-_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
-_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
+ _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
+# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+ _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
+# endif
#endif
#undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
@@ -137,6 +144,7 @@
return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
// wstring
template<>
inline
@@ -181,6 +189,7 @@
{
return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
}
+#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
// as_float
@@ -232,6 +241,7 @@
return as_float_helper<long double>( func, s, idx, strtold );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
template<>
inline
float
@@ -255,6 +265,7 @@
{
return as_float_helper<long double>( func, s, idx, wcstold );
}
+#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
} // unnamed namespace
@@ -264,11 +275,13 @@
return as_integer<int>( "stoi", str, idx, base );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
int
stoi(const wstring& str, size_t* idx, int base)
{
return as_integer<int>( "stoi", str, idx, base );
}
+#endif
long
stol(const string& str, size_t* idx, int base)
@@ -276,11 +289,13 @@
return as_integer<long>( "stol", str, idx, base );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
long
stol(const wstring& str, size_t* idx, int base)
{
return as_integer<long>( "stol", str, idx, base );
}
+#endif
unsigned long
stoul(const string& str, size_t* idx, int base)
@@ -288,11 +303,13 @@
return as_integer<unsigned long>( "stoul", str, idx, base );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
unsigned long
stoul(const wstring& str, size_t* idx, int base)
{
return as_integer<unsigned long>( "stoul", str, idx, base );
}
+#endif
long long
stoll(const string& str, size_t* idx, int base)
@@ -300,11 +317,13 @@
return as_integer<long long>( "stoll", str, idx, base );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
long long
stoll(const wstring& str, size_t* idx, int base)
{
return as_integer<long long>( "stoll", str, idx, base );
}
+#endif
unsigned long long
stoull(const string& str, size_t* idx, int base)
@@ -312,11 +331,13 @@
return as_integer<unsigned long long>( "stoull", str, idx, base );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
unsigned long long
stoull(const wstring& str, size_t* idx, int base)
{
return as_integer<unsigned long long>( "stoull", str, idx, base );
}
+#endif
float
stof(const string& str, size_t* idx)
@@ -324,11 +345,13 @@
return as_float<float>( "stof", str, idx );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
float
stof(const wstring& str, size_t* idx)
{
return as_float<float>( "stof", str, idx );
}
+#endif
double
stod(const string& str, size_t* idx)
@@ -336,11 +359,13 @@
return as_float<double>( "stod", str, idx );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
double
stod(const wstring& str, size_t* idx)
{
return as_float<double>( "stod", str, idx );
}
+#endif
long double
stold(const string& str, size_t* idx)
@@ -348,11 +373,13 @@
return as_float<long double>( "stold", str, idx );
}
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
long double
stold(const wstring& str, size_t* idx)
{
return as_float<long double>( "stold", str, idx );
}
+#endif
// to_string
@@ -403,6 +430,7 @@
}
};
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
template <>
struct initial_string<wstring>
{
@@ -427,6 +455,7 @@
return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf);
#endif
}
+#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
template <typename S, typename V>
S i_to_string(V v)
@@ -450,20 +479,23 @@
string to_string (unsigned long val) { return i_to_string< string>(val); }
string to_string (unsigned long long val) { return i_to_string< string>(val); }
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
wstring to_wstring(int val) { return i_to_string<wstring>(val); }
wstring to_wstring(long val) { return i_to_string<wstring>(val); }
wstring to_wstring(long long val) { return i_to_string<wstring>(val); }
wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); }
wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); }
wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
-
+#endif
string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }
string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }
string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); }
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }
wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }
wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
+#endif
_LIBCPP_END_NAMESPACE_STD