/************************************************************************** Copyright (c) 2017 sewenew Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *************************************************************************/ #ifndef SEWENEW_REDISPLUSPLUS_UTILS_H #define SEWENEW_REDISPLUSPLUS_UTILS_H #include #include #include namespace sw { namespace redis { // By now, not all compilers support std::string_view, // so we make our own implementation. class StringView { public: constexpr StringView() noexcept = default; constexpr StringView(const char *data, std::size_t size) : _data(data), _size(size) {} StringView(const char *data) : _data(data), _size(std::strlen(data)) {} StringView(const std::string &str) : _data(str.data()), _size(str.size()) {} constexpr StringView(const StringView &) noexcept = default; StringView& operator=(const StringView &) noexcept = default; constexpr const char* data() const noexcept { return _data; } constexpr std::size_t size() const noexcept { return _size; } private: const char *_data = nullptr; std::size_t _size = 0; }; template class Optional { public: Optional() = default; Optional(const Optional &) = default; Optional& operator=(const Optional &) = default; Optional(Optional &&) = default; Optional& operator=(Optional &&) = default; ~Optional() = default; template explicit Optional(Args &&...args) : _value(true, T(std::forward(args)...)) {} explicit operator bool() const { return _value.first; } T& value() { return _value.second; } const T& value() const { return _value.second; } T* operator->() { return &(_value.second); } const T* operator->() const { return &(_value.second); } T& operator*() { return _value.second; } const T& operator*() const { return _value.second; } private: std::pair _value; }; using OptionalString = Optional; using OptionalLongLong = Optional; using OptionalDouble = Optional; using OptionalStringPair = Optional>; template struct IsKvPair : std::false_type {}; template struct IsKvPair> : std::true_type {}; template using Void = void; template > struct IsInserter : std::false_type {}; template //struct IsInserter> : std::true_type {}; struct IsInserter::value>::type> : std::true_type {}; template > struct IterType { using type = typename std::iterator_traits::value_type; }; template //struct IterType> { struct IterType::value>::type> { typename std::enable_if::value>::type> { using type = typename std::decay::type; }; template > struct IsIter : std::false_type {}; template struct IsIter::value>::type> : std::true_type {}; template //struct IsIter::iterator_category>> struct IsIter::value_type>::value>::type> : std::integral_constant::value> {}; template struct IsKvPairIter : IsKvPair::type> {}; template struct TupleWithType : std::false_type {}; template struct TupleWithType> : std::false_type {}; template struct TupleWithType> : TupleWithType> {}; template struct TupleWithType> : std::true_type {}; template struct IndexSequence {}; template struct MakeIndexSequence : MakeIndexSequence {}; template struct MakeIndexSequence<0, Is...> : IndexSequence {}; // NthType and NthValue are taken from // https://stackoverflow.com/questions/14261183 template struct NthType {}; template struct NthType<0, Arg, Args...> { using type = Arg; }; template struct NthType { using type = typename NthType::type; }; template struct LastType { using type = typename NthType::type; }; struct InvalidLastType {}; template <> struct LastType<> { using type = InvalidLastType; }; template auto NthValue(Arg &&arg, Args &&...) -> typename std::enable_if<(I == 0), decltype(std::forward(arg))>::type { return std::forward(arg); } template auto NthValue(Arg &&, Args &&...args) -> typename std::enable_if<(I > 0), decltype(std::forward::type>( std::declval::type>()))>::type { return std::forward::type>( NthValue(std::forward(args)...)); } template auto LastValue(Args &&...args) -> decltype(std::forward::type>( std::declval::type>())) { return std::forward::type>( NthValue(std::forward(args)...)); } template > struct HasPushBack : std::false_type {}; template struct HasPushBack().push_back(std::declval()) )>::value>::type> : std::true_type {}; template > struct HasInsert : std::false_type {}; template struct HasInsert().insert(std::declval(), std::declval())), typename T::iterator>::value>::type> : std::true_type {}; template struct IsSequenceContainer : std::integral_constant::value && !std::is_same::type, std::string>::value> {}; template struct IsAssociativeContainer : std::integral_constant::value && !HasPushBack::value> {}; uint16_t crc16(const char *buf, int len); } } #endif // end SEWENEW_REDISPLUSPLUS_UTILS_H