Commit 1d4de585 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Make Range.h and FBString.h mutually independent

Summary:
[Folly] Make `Range.h` and `FBString.h` mutually independent.

This means that `Range` cannot directly know about `fbstring`, so any interactions between the two types must be indirected through templates.

Motivation: `FBString.h` is a relatively heaviweight `#include` for things that need `Range.h` but which do not use `fbstring`.

Reviewed By: ericniebler

Differential Revision: D6062434

fbshipit-source-id: e2f21c33f482eadffd0a8679eff4ece59bab53e9
parent d201571c
...@@ -2894,3 +2894,13 @@ FOLLY_POP_WARNING ...@@ -2894,3 +2894,13 @@ FOLLY_POP_WARNING
#undef FBSTRING_LIKELY #undef FBSTRING_LIKELY
#undef FBSTRING_UNLIKELY #undef FBSTRING_UNLIKELY
#undef FBSTRING_ASSERT #undef FBSTRING_ASSERT
#ifndef _LIBSTDCXX_FBSTRING
namespace folly {
template <class T>
struct IsSomeString;
template <>
struct IsSomeString<fbstring> : std::true_type {};
} // namespace folly
#endif
...@@ -790,29 +790,6 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase { ...@@ -790,29 +790,6 @@ class BasicFixedString : private detail::fixedstring::FixedStringBase {
return *this; return *this;
} }
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Conversion to folly::Range
* \return `Range<Iter>{begin(), end()}`
*/
template <
class Iter,
class = typename std::enable_if<
std::is_convertible<Char*, Iter>::value>::type>
FOLLY_CPP14_CONSTEXPR /* implicit */ operator Range<Iter>() noexcept {
return {begin(), end()};
}
/**
* \overload
*/
template <
class Iter,
class = typename std::enable_if<
std::is_convertible<const Char*, Iter>::value>::type>
constexpr /* implicit */ operator Range<Iter>() const noexcept {
return {begin(), end()};
}
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Conversion to folly::Range * Conversion to folly::Range
* \return `Range<Char*>{begin(), end()}` * \return `Range<Char*>{begin(), end()}`
......
...@@ -931,7 +931,7 @@ template <> ...@@ -931,7 +931,7 @@ template <>
struct KeyFromStringPiece<fbstring> : public FormatTraitsBase { struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
typedef fbstring key_type; typedef fbstring key_type;
static fbstring convert(StringPiece s) { static fbstring convert(StringPiece s) {
return s.toFbstring(); return s.to<fbstring>();
} }
}; };
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <functional> #include <functional>
#include <iosfwd> #include <iosfwd>
#include <folly/FBString.h>
#include <folly/Hash.h> #include <folly/Hash.h>
#include <folly/Range.h> #include <folly/Range.h>
#include <folly/detail/IPAddress.h> #include <folly/detail/IPAddress.h>
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <map> #include <map>
#include <stdexcept> #include <stdexcept>
#include <folly/FBString.h>
#include <folly/Hash.h> #include <folly/Hash.h>
#include <folly/Optional.h> #include <folly/Optional.h>
#include <folly/Range.h> #include <folly/Range.h>
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#pragma once #pragma once
#include <folly/FBString.h>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/hash/SpookyHashV2.h> #include <folly/hash/SpookyHashV2.h>
#include <folly/portability/BitsFunctexcept.h> #include <folly/portability/BitsFunctexcept.h>
...@@ -30,6 +29,7 @@ ...@@ -30,6 +29,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cassert>
#include <climits> #include <climits>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
...@@ -38,17 +38,6 @@ ...@@ -38,17 +38,6 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
// libc++ doesn't provide this header, nor does msvc
#ifdef FOLLY_HAVE_BITS_CXXCONFIG_H
// This file appears in two locations: inside fbcode and in the
// libstdc++ source code (when embedding fbstring as std::string).
// To aid in this schizophrenic use, two macros are defined in
// c++config.h:
// _LIBSTDCXX_FBSTRING - Set inside libstdc++. This is useful to
// gate use inside fbcode v. libstdc++
#include <bits/c++config.h>
#endif
#include <folly/CpuId.h> #include <folly/CpuId.h>
#include <folly/Likely.h> #include <folly/Likely.h>
#include <folly/Traits.h> #include <folly/Traits.h>
...@@ -61,6 +50,15 @@ FOLLY_GCC_DISABLE_WARNING("-Wshadow") ...@@ -61,6 +50,15 @@ FOLLY_GCC_DISABLE_WARNING("-Wshadow")
namespace folly { namespace folly {
/**
* Ubiquitous helper template for knowing what's a string.
*/
template <class T>
struct IsSomeString : std::false_type {};
template <>
struct IsSomeString<std::string> : std::true_type {};
template <class Iter> template <class Iter>
class Range; class Range;
...@@ -251,30 +249,58 @@ class Range : private boost::totally_ordered<Range<Iter>> { ...@@ -251,30 +249,58 @@ class Range : private boost::totally_ordered<Range<Iter>> {
Range(const Range& other, size_type first, size_type length = npos) Range(const Range& other, size_type first, size_type length = npos)
: Range(other.subpiece(first, length)) {} : Range(other.subpiece(first, length)) {}
template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> template <
/* implicit */ Range(const fbstring& str) class Container,
: b_(str.data()), e_(b_ + str.size()) {} class = typename std::enable_if<
std::is_same<Iter, typename Container::const_pointer>::value>::type,
class = decltype(
Iter(std::declval<Container const&>().data()),
Iter(
std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
/* implicit */ constexpr Range(Container const& container)
: b_(container.data()), e_(b_ + container.size()) {}
template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> template <
Range(const fbstring& str, fbstring::size_type startFrom) { class Container,
if (UNLIKELY(startFrom > str.size())) { class = typename std::enable_if<
std::is_same<Iter, typename Container::const_pointer>::value>::type,
class = decltype(
Iter(std::declval<Container const&>().data()),
Iter(
std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
Range(Container const& container, typename Container::size_type startFrom) {
auto const cdata = container.data();
auto const csize = container.size();
if (UNLIKELY(startFrom > csize)) {
std::__throw_out_of_range("index out of range"); std::__throw_out_of_range("index out of range");
} }
b_ = str.data() + startFrom; b_ = cdata + startFrom;
e_ = str.data() + str.size(); e_ = cdata + csize;
} }
template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0> template <
class Container,
class = typename std::enable_if<
std::is_same<Iter, typename Container::const_pointer>::value>::type,
class = decltype(
Iter(std::declval<Container const&>().data()),
Iter(
std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
Range( Range(
const fbstring& str, Container const& container,
fbstring::size_type startFrom, typename Container::size_type startFrom,
fbstring::size_type size) { typename Container::size_type size) {
if (UNLIKELY(startFrom > str.size())) { auto const cdata = container.data();
auto const csize = container.size();
if (UNLIKELY(startFrom > csize)) {
std::__throw_out_of_range("index out of range"); std::__throw_out_of_range("index out of range");
} }
b_ = str.data() + startFrom; b_ = cdata + startFrom;
if (str.size() - startFrom < size) { if (csize - startFrom < size) {
e_ = str.data() + str.size(); e_ = cdata + csize;
} else { } else {
e_ = b_ + size; e_ = b_ + size;
} }
...@@ -448,19 +474,22 @@ class Range : private boost::totally_ordered<Range<Iter>> { ...@@ -448,19 +474,22 @@ class Range : private boost::totally_ordered<Range<Iter>> {
assert(b_ < e_); assert(b_ < e_);
return detail::value_before(e_); return detail::value_before(e_);
} }
// Works only for Range<const char*> and Range<char*>
std::string str() const { template <typename Tgt>
return std::string(b_, size()); auto to() const
} -> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
std::string toString() const { return Tgt(b_, size());
return str();
} }
// Works only for Range<const char*> and Range<char*> // Works only for Range<const char*> and Range<char*>
fbstring fbstr() const { template <typename Tgt = std::string>
return fbstring(b_, size()); auto str() const
-> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
return to<Tgt>();
} }
fbstring toFbstring() const { template <typename Tgt = std::string>
return fbstr(); auto toString() const
-> decltype(Tgt(std::declval<Iter const&>(), std::declval<size_type>())) {
return to<Tgt>();
} }
const_range_type castToConst() const { const_range_type castToConst() const {
...@@ -1314,17 +1343,6 @@ struct hasher< ...@@ -1314,17 +1343,6 @@ struct hasher<
} }
}; };
/**
* Ubiquitous helper template for knowing what's a string
*/
template <class T>
struct IsSomeString {
enum {
value =
std::is_same<T, std::string>::value || std::is_same<T, fbstring>::value
};
};
/** /**
* _sp is a user-defined literal suffix to make an appropriate Range * _sp is a user-defined literal suffix to make an appropriate Range
* specialization from a literal string. * specialization from a literal string.
......
...@@ -102,15 +102,20 @@ bool setThreadName(std::thread::id tid, StringPiece name) { ...@@ -102,15 +102,20 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
#if !FOLLY_HAVE_PTHREAD || _WIN32 #if !FOLLY_HAVE_PTHREAD || _WIN32
return false; return false;
#else #else
auto trimmedName = name.fbstr().substr(0, kMaxThreadNameLength - 1); auto const piece = name.subpiece(0, kMaxThreadNameLength - 1);
auto const data = piece.data();
auto const size = piece.size();
char trimmedName[kMaxThreadNameLength];
std::memcpy(trimmedName, data, size);
std::memset(trimmedName + size, 0, kMaxThreadNameLength - size);
auto id = stdTidToPthreadId(tid); auto id = stdTidToPthreadId(tid);
#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
return 0 == pthread_setname_np(id, trimmedName.c_str()); return 0 == pthread_setname_np(id, const_cast<char const*>(trimmedName));
#elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME #elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
// Since OS X 10.6 it is possible for a thread to set its own name, // Since OS X 10.6 it is possible for a thread to set its own name,
// but not that of some other thread. // but not that of some other thread.
if (pthread_equal(pthread_self(), id)) { if (pthread_equal(pthread_self(), id)) {
return 0 == pthread_setname_np(trimmedName.c_str()); return 0 == pthread_setname_np(const_cast<char const*>(trimmedName));
} }
return false; return false;
#else #else
......
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