Commit e37262d4 authored by Andrew Krieger's avatar Andrew Krieger Committed by Facebook GitHub Bot

dynamic constructor from anything String-like

Summary:
With the exception of std::string, nothing else string-like can be
optimized further than a copy. So, create a generic Stringish constructor
that copies .size() elements from .data(), where .data() has a value type
of char.

Reviewed By: yfeldblum

Differential Revision: D5407445

fbshipit-source-id: acf709f07e73bb5bef3f124169c81d76edefa52c
parent e80c094b
......@@ -27,6 +27,7 @@
namespace folly {
namespace detail {
struct DynamicHasher {
using is_transparent = void;
......@@ -329,10 +330,6 @@ inline dynamic::dynamic(ObjectMaker (*)()) : type_(OBJECT) {
new (getAddress<ObjectImpl>()) ObjectImpl();
}
inline dynamic::dynamic(StringPiece s) : type_(STRING) {
new (&u_.string) std::string(s.data(), s.size());
}
inline dynamic::dynamic(char const* s) : type_(STRING) {
new (&u_.string) std::string(s);
}
......@@ -341,6 +338,11 @@ inline dynamic::dynamic(std::string s) : type_(STRING) {
new (&u_.string) std::string(std::move(s));
}
template <typename Stringish, typename>
inline dynamic::dynamic(Stringish&& s) : type_(STRING) {
new (&u_.string) std::string(s.data(), s.size());
}
inline dynamic::dynamic(ObjectMaker&& maker) : type_(OBJECT) {
new (getAddress<ObjectImpl>())
ObjectImpl(std::move(*maker.val_.getAddress<ObjectImpl>()));
......@@ -535,9 +537,6 @@ inline bool dynamic::getBool() && {
return get<bool>();
}
inline const char* dynamic::data() const& {
return get<std::string>().data();
}
inline const char* dynamic::c_str() const& {
return get<std::string>().c_str();
}
......
......@@ -77,6 +77,12 @@ struct TypeError;
//////////////////////////////////////////////////////////////////////
namespace dynamic_detail {
template <typename T>
using detect_construct_string = decltype(std::string(
FOLLY_DECLVAL(T const&).data(), FOLLY_DECLVAL(T const&).size()));
}
struct dynamic : private boost::operators<dynamic> {
enum Type {
NULLT,
......@@ -167,9 +173,13 @@ struct dynamic : private boost::operators<dynamic> {
* String compatibility constructors.
*/
/* implicit */ dynamic(std::nullptr_t);
/* implicit */ dynamic(StringPiece val);
/* implicit */ dynamic(char const* val);
/* implicit */ dynamic(std::string val);
template <
typename Stringish,
typename = std::enable_if_t<
is_detected_v<dynamic_detail::detect_construct_string, Stringish>>>
/* implicit */ dynamic(Stringish&& s);
/*
* This is part of the plumbing for array() and object(), above.
......@@ -326,8 +336,6 @@ struct dynamic : private boost::operators<dynamic> {
*
* These will throw a TypeError if the dynamic is not a string.
*/
const char* data() const&;
const char* data() && = delete;
const char* c_str() const&;
const char* c_str() && = delete;
StringPiece stringPiece() const;
......
......@@ -38,11 +38,10 @@ TEST(Dynamic, StringPtrs) {
dynamic nullStr = folly::parseJson("\"foo\\u0000bar\"");
EXPECT_EQ(0, strcmp(str.c_str(), "12.0"));
EXPECT_EQ(0, strncmp(str.data(), "12.0", str.asString().length()));
EXPECT_EQ(0, strncmp(str.c_str(), "12.0", str.asString().length()));
EXPECT_EQ(str.stringPiece(), "12.0");
EXPECT_THROW(num.c_str(), TypeError);
EXPECT_THROW(num.data(), TypeError);
EXPECT_THROW(num.stringPiece(), TypeError);
EXPECT_EQ(nullStr.stringPiece(), folly::StringPiece("foo\0bar", 7));
......
......@@ -410,6 +410,18 @@ TEST(Dynamic, StringBasics) {
EXPECT_FALSE(str.empty());
str = "";
EXPECT_TRUE(str.empty());
dynamic std_str = std::string("hello world");
EXPECT_EQ(11, std_str.size());
EXPECT_FALSE(std_str.empty());
dynamic stringpiece = folly::StringPiece("hello world");
EXPECT_EQ(11, stringpiece.size());
EXPECT_FALSE(stringpiece.empty());
dynamic vectorstring = std::vector<char>{'a', 'b', 'c', 'd', 'e', 'f'};
EXPECT_EQ(6, vectorstring.size());
EXPECT_FALSE(vectorstring.empty());
}
TEST(Dynamic, ArrayBasics) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment