mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-20758 Add a StringPiece constructor for any string view type.
Using the C++ SFINAE (substitution failure is not an error) technique, it's possible to provide an icu::StringPiece constructor that accepts any string view type that might be available in the current compilation unit, without adding any additional dependencies or configuration flags to ICU.
This commit is contained in:
parent
c78d9fa137
commit
d8f14e22df
5 changed files with 158 additions and 0 deletions
|
@ -31,6 +31,9 @@
|
|||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/std_string.h"
|
||||
|
||||
|
@ -77,6 +80,33 @@ class U_COMMON_API StringPiece : public UMemory {
|
|||
*/
|
||||
StringPiece(const std::string& str)
|
||||
: ptr_(str.data()), length_(static_cast<int32_t>(str.size())) { }
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Constructs from some other implementation of a string piece class, from any
|
||||
* C++ record type that has these two methods:
|
||||
*
|
||||
* \code{.cpp}
|
||||
*
|
||||
* struct OtherStringPieceClass {
|
||||
* const char* data();
|
||||
* size_t size();
|
||||
* };
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* The other string piece class will typically be std::string_view from C++17
|
||||
* or absl::string_view from Abseil.
|
||||
*
|
||||
* @param str the other string piece
|
||||
* @draft ICU 65
|
||||
*/
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<
|
||||
std::is_same<decltype(T().data()), const char*>::value &&
|
||||
std::is_same<decltype(T().size()), size_t>::value>::type>
|
||||
StringPiece(T str)
|
||||
: ptr_(str.data()), length_(static_cast<int32_t>(str.size())) {}
|
||||
#endif // U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Constructs from a const char * pointer and a specified length.
|
||||
* @param offset a const char * pointer (need not be terminated)
|
||||
|
|
77
icu4c/source/configure
vendored
77
icu4c/source/configure
vendored
|
@ -2201,6 +2201,60 @@ $as_echo "$ac_res" >&6; }
|
|||
|
||||
} # ac_fn_c_check_func
|
||||
|
||||
# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES
|
||||
# ---------------------------------------------
|
||||
# Tests whether TYPE exists after having included INCLUDES, setting cache
|
||||
# variable VAR accordingly.
|
||||
ac_fn_cxx_check_type ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
eval "$3=no"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (sizeof ($2))
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (sizeof (($2)))
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
|
||||
else
|
||||
eval "$3=yes"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_cxx_check_type
|
||||
|
||||
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
|
||||
# -------------------------------------------
|
||||
# Tests whether TYPE exists after having included INCLUDES, setting cache
|
||||
|
@ -7153,6 +7207,29 @@ else
|
|||
fi
|
||||
|
||||
|
||||
# Check if C++17 std::string_view is available.
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
ac_fn_cxx_check_type "$LINENO" "std::string_view" "ac_cv_type_std__string_view" "#include <string_view>
|
||||
"
|
||||
if test "x$ac_cv_type_std__string_view" = xyes; then :
|
||||
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_type_std__string_view" = xyes; then :
|
||||
CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRING_VIEW=1"
|
||||
fi
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
# Checks for typedefs
|
||||
ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
|
||||
if test "x$ac_cv_type_int8_t" = xyes; then :
|
||||
|
|
|
@ -903,6 +903,14 @@ else
|
|||
fi
|
||||
AC_SUBST(U_HAVE_STRTOD_L)
|
||||
|
||||
# Check if C++17 std::string_view is available.
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_CHECK_TYPE(std::string_view, [], [], [[#include <string_view>]])
|
||||
if test "x$ac_cv_type_std__string_view" = xyes; then :
|
||||
CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRING_VIEW=1"
|
||||
fi
|
||||
AC_LANG_POP([C++])
|
||||
|
||||
# Checks for typedefs
|
||||
AC_CHECK_TYPE(int8_t,signed char)
|
||||
AC_CHECK_TYPE(uint8_t,unsigned char)
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
* created by: Markus W. Scherer
|
||||
*/
|
||||
|
||||
#if U_HAVE_STRING_VIEW
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <string.h>
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
@ -177,6 +182,10 @@ void StringTest::runIndexedTest(int32_t index, UBool exec, const char *&name, ch
|
|||
TESTCASE_AUTO(TestSTLCompatibility);
|
||||
TESTCASE_AUTO(TestStringPiece);
|
||||
TESTCASE_AUTO(TestStringPieceComparisons);
|
||||
TESTCASE_AUTO(TestStringPieceOther);
|
||||
#if U_HAVE_STRING_VIEW
|
||||
TESTCASE_AUTO(TestStringPieceStringView);
|
||||
#endif
|
||||
TESTCASE_AUTO(TestByteSink);
|
||||
TESTCASE_AUTO(TestCheckedArrayByteSink);
|
||||
TESTCASE_AUTO(TestStringByteSink);
|
||||
|
@ -346,6 +355,36 @@ StringTest::TestStringPieceComparisons() {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
StringTest::TestStringPieceOther() {
|
||||
static constexpr char msg[] = "Kapow!";
|
||||
|
||||
// Another string piece implementation.
|
||||
struct Other {
|
||||
const char* data() { return msg; }
|
||||
size_t size() { return sizeof msg - 1; }
|
||||
};
|
||||
|
||||
Other other;
|
||||
StringPiece piece(other);
|
||||
|
||||
assertEquals("size()", piece.size(), other.size());
|
||||
assertEquals("data()", piece.data(), other.data());
|
||||
}
|
||||
|
||||
#if U_HAVE_STRING_VIEW
|
||||
void
|
||||
StringTest::TestStringPieceStringView() {
|
||||
static constexpr char msg[] = "Kapow!";
|
||||
|
||||
std::string_view view(msg); // C++17
|
||||
StringPiece piece(view);
|
||||
|
||||
assertEquals("size()", piece.size(), view.size());
|
||||
assertEquals("data()", piece.data(), view.data());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Verify that ByteSink is subclassable and Flush() overridable.
|
||||
class SimpleByteSink : public ByteSink {
|
||||
public:
|
||||
|
|
|
@ -42,6 +42,10 @@ private:
|
|||
void Test_UTF8_COUNT_TRAIL_BYTES();
|
||||
void TestStringPiece();
|
||||
void TestStringPieceComparisons();
|
||||
void TestStringPieceOther();
|
||||
#if U_HAVE_STRING_VIEW
|
||||
void TestStringPieceStringView();
|
||||
#endif
|
||||
void TestByteSink();
|
||||
void TestCheckedArrayByteSink();
|
||||
void TestStringByteSink();
|
||||
|
|
Loading…
Add table
Reference in a new issue