diff --git a/API/fleece/CompilerSupport.h b/API/fleece/CompilerSupport.h index 34ef9653..b02bf266 100644 --- a/API/fleece/CompilerSupport.h +++ b/API/fleece/CompilerSupport.h @@ -148,18 +148,6 @@ #endif -// `constexpr14` is for uses of `constexpr` that are valid in C++14 but not earlier. -// In constexpr functions this includes `if`, `for`, `while` statements; or multiple `return`s. -// The macro expands to `constexpr` in C++14 or later, otherwise to nothing. -#ifdef __cplusplus - #if __cplusplus >= 201400L || _MSVC_LANG >= 201400L - #define constexpr14 constexpr - #else - #define constexpr14 - #endif -#endif // __cplusplus - - // STEPOVER is for trivial little glue functions that are annoying to step into in the debugger // on the way to the function you _do_ want to step into. Examples are RefCounted's operator->, // or slice constructors. Suppressing debug info for those functions means the debugger diff --git a/API/fleece/FLSlice.h b/API/fleece/FLSlice.h index 04e9720c..3a5a977d 100644 --- a/API/fleece/FLSlice.h +++ b/API/fleece/FLSlice.h @@ -47,8 +47,11 @@ typedef struct FLSlice { size_t size; #ifdef __cplusplus - explicit operator bool() const noexcept FLPURE {return buf != nullptr;} - explicit operator std::string() const {return std::string((char*)buf, size);} + constexpr const void* FL_NULLABLE data() const noexcept FLPURE {return buf;} + constexpr size_t size_bytes() const noexcept FLPURE {return size;} // compatibility with std::span + constexpr bool empty() const noexcept FLPURE {return size == 0;} + constexpr explicit operator bool() const noexcept FLPURE {return buf != nullptr;} + explicit operator std::string() const {return std::string((char*)buf, size);} #endif } FLSlice; @@ -65,8 +68,11 @@ struct NODISCARD FLSliceResult { size_t size; #ifdef __cplusplus - explicit operator bool() const noexcept FLPURE {return buf != nullptr;} - explicit operator FLSlice () const {return {buf, size};} + constexpr const void* FL_NULLABLE data() const noexcept FLPURE {return buf;} + constexpr size_t size_bytes() const noexcept FLPURE {return size;} // compatibility with std::span + constexpr bool empty() const noexcept FLPURE {return size == 0;} + constexpr explicit operator bool() const noexcept FLPURE {return buf != nullptr;} + constexpr explicit operator FLSlice () const {return {buf, size};} inline explicit operator std::string() const; #endif }; @@ -123,7 +129,7 @@ static inline void FLMemCpy(void* FL_NULLABLE dst, const void* FL_NULLABLE src, It's OK to pass NULL; this returns an empty slice. \note If the string is a literal, it's more efficient to use \ref FLSTR instead. \note Performance is O(n) with the length of the string, since it has to call `strlen`. */ -static inline FLSlice FLStr(const char* FL_NULLABLE str) FLAPI { +static inline FLSlice FLStr(const char* FL_NULLABLE str LIFETIMEBOUND) FLAPI { FLSlice foo = { str, str ? strlen(str) : 0 }; return foo; } @@ -185,7 +191,7 @@ static inline void FLSliceResult_Release(FLSliceResult s) FLAPI { } /** Type-casts a FLSliceResult to FLSlice, since C doesn't know it's a subclass. */ -static inline FLSlice FLSliceResult_AsSlice(FLSliceResult sr) { +static inline FLSlice FLSliceResult_AsSlice(FLSliceResult sr LIFETIMEBOUND) { FLSlice ret; memcpy(&ret, &sr, sizeof(ret)); return ret; diff --git a/API/fleece/slice.hh b/API/fleece/slice.hh index d84ab756..3b937573 100644 --- a/API/fleece/slice.hh +++ b/API/fleece/slice.hh @@ -16,14 +16,15 @@ #include "FLSlice.h" #include // for std::min() -#include -#include -#include // for fputs() -#include // for memcpy(), memcmp() +#include +#include +#include // for fputs() +#include // for memcpy(), memcmp() #include +#include #ifndef assert -# include +# include #endif # ifndef assert_precondition # define assert_precondition(e) assert(e) @@ -39,14 +40,6 @@ # endif #endif -// Figure out whether and how string_view is available -#ifdef __has_include -# if __has_include() -# include -# define SLICE_SUPPORTS_STRING_VIEW -# endif -#endif - // Utility for using slice with printf-style formatting. // Use "%.*" in the format string; then for the corresponding argument put FMTSLICE(theslice). @@ -62,10 +55,6 @@ namespace fleece { struct alloc_slice; struct nullslice_t; -#ifdef SLICE_SUPPORTS_STRING_VIEW - using string_view = std::string_view; // create typedef with correct namespace -#endif - #ifdef __APPLE__ using CFStringRef = const struct ::__CFString *; using CFDataRef = const struct ::__CFData *; @@ -73,13 +62,13 @@ namespace fleece { /** Adds a byte offset to a pointer. */ template - FLCONST constexpr14 inline const T* FL_NONNULL offsetby(const T * FL_NONNULL t, ptrdiff_t offset) noexcept { + FLCONST constexpr inline const T* FL_NONNULL offsetby(const T * FL_NONNULL t, ptrdiff_t offset) noexcept { return (const T*)((uint8_t*)t + offset); } /** Adds a byte offset to a pointer. */ template - FLCONST constexpr14 inline T* FL_NONNULL offsetby(T * FL_NONNULL t, ptrdiff_t offset) noexcept { + FLCONST constexpr inline T* FL_NONNULL offsetby(T * FL_NONNULL t, ptrdiff_t offset) noexcept { return (T*)((uint8_t*)t + offset); } @@ -110,13 +99,14 @@ namespace fleece { ownership: it manages a ref-counted heap-allocated buffer. * Instances are immutable: `buf` and `size` cannot be changed. The `slice` subclass changes this. - * The memory pointed to cannot be modified through this class. `slice` has some - methods that allow writes. */ + * The memory pointed to cannot be modified through this class. */ struct pure_slice { - const void* FL_NULLABLE const buf; - size_t const size; + const void* FL_NULLABLE const buf = nullptr; + size_t const size = 0; + + constexpr const void* data() const noexcept FLPURE {return buf;} //like std::span + constexpr size_t size_bytes() const noexcept FLPURE {return size;} //like std::span - pure_slice(const pure_slice &) noexcept = default; /// True if the slice's length is zero. bool empty() const noexcept FLPURE {return size == 0;} @@ -178,11 +168,9 @@ namespace fleece { /// Copies my contents to memory starting at `dst`, using `memcpy`. void copyTo(void *dst) const noexcept {FLMemCpy(dst, buf, size);} - /// Returns new malloc'ed slice containing same data. Call free() on it when done. - inline slice copy() const; - // String conversions: + operator std::string_view() const noexcept STEPOVER {return {(const char*)buf, size};} explicit operator std::string() const {return std::string((const char*)buf, size);} std::string asString() const {return (std::string)*this;} @@ -192,15 +180,8 @@ namespace fleece { will not overflow the buffer. Returns false if the slice was truncated. */ inline bool toCString(char *buf, size_t bufSize) const noexcept; - // FLSlice interoperability: constexpr operator FLSlice () const noexcept {return {buf, size};} -#ifdef SLICE_SUPPORTS_STRING_VIEW - // std::string_view interoperability: - constexpr pure_slice(string_view str) noexcept :pure_slice(str.data(), str.length()) {} - operator string_view() const noexcept STEPOVER {return string_view((const char*)buf, size);} -#endif - #ifdef __APPLE__ // Implementations in slice+CoreFoundation.cc and slice+ObjC.mm explicit pure_slice(CFDataRef FL_NULLABLE data) noexcept; @@ -220,15 +201,18 @@ namespace fleece { constexpr pure_slice(std::nullptr_t) noexcept :pure_slice() {} constexpr pure_slice(const char* FL_NULLABLE str) noexcept :buf(str), size(_strlen(str)) {} - pure_slice(const std::string& str LIFETIMEBOUND) noexcept :buf(&str[0]), size(str.size()) {} + pure_slice(const std::string& str LIFETIMEBOUND) noexcept :buf(str.data()), size(str.size()) {} + constexpr pure_slice(std::string_view str) noexcept :pure_slice(str.data(), str.length()) {} // Raw memory allocation. These throw std::bad_alloc on failure. RETURNS_NONNULL inline static void* newBytes(size_t sz); template RETURNS_NONNULL static inline T* FL_NONNULL reallocBytes(T* FL_NULLABLE bytes, size_t newSz); + // Returns new malloc'ed slice containing same data. Call free() on it when done. + inline slice copy() const; protected: - constexpr pure_slice() noexcept :buf(nullptr), size(0) {} + constexpr pure_slice() noexcept = default; inline constexpr pure_slice(const void* FL_NULLABLE b, size_t s) noexcept; inline void setBuf(const void *b) noexcept; @@ -259,13 +243,14 @@ namespace fleece { * `buf` may be NULL, but only if `size` is zero; this is called `nullslice`. * `size` may be zero with a non-NULL `buf`; that's called an "empty slice". */ struct slice : public pure_slice { - constexpr slice() noexcept STEPOVER :pure_slice() {} + constexpr slice() noexcept STEPOVER = default; constexpr slice(std::nullptr_t) noexcept STEPOVER :pure_slice() {} inline constexpr slice(nullslice_t) noexcept STEPOVER; constexpr slice(const void* FL_NULLABLE b LIFETIMEBOUND, size_t s) noexcept STEPOVER :pure_slice(b, s) {} inline constexpr slice(const void* start LIFETIMEBOUND, const void* end) noexcept STEPOVER; inline slice(const alloc_slice& LIFETIMEBOUND) noexcept STEPOVER; + constexpr slice(std::string_view str) noexcept STEPOVER :pure_slice(str) {} slice(const std::string& str LIFETIMEBOUND) noexcept STEPOVER :pure_slice(str) {} constexpr slice(const char* FL_NULLABLE str LIFETIMEBOUND) noexcept STEPOVER :pure_slice(str) {} @@ -294,10 +279,6 @@ namespace fleece { explicit slice(const FLSliceResult &sr LIFETIMEBOUND) STEPOVER :pure_slice(sr.buf, sr.size) { } slice& operator= (FLHeapSlice s) noexcept {set(s.buf, s.size); return *this;} // disambiguation -#ifdef SLICE_SUPPORTS_STRING_VIEW - constexpr slice(string_view str) noexcept STEPOVER :pure_slice(str) {} -#endif - #ifdef __APPLE__ explicit slice(CFDataRef data) noexcept :pure_slice(data) {} # ifdef __OBJC__ @@ -309,10 +290,10 @@ namespace fleece { /** An awkwardly unrelated struct for when the bytes need to be writeable. */ struct mutable_slice { - void* FL_NULLABLE buf; - size_t size; + void* FL_NULLABLE buf = nullptr; + size_t size = 0; - constexpr mutable_slice() noexcept :buf(nullptr), size(0) {} + constexpr mutable_slice() noexcept = default; explicit constexpr mutable_slice(pure_slice s) noexcept :buf((void*)s.buf), size(s.size) {} constexpr mutable_slice(void* FL_NULLABLE b, size_t s) noexcept :buf(b), size(s) {} constexpr mutable_slice(void* b, void* e) noexcept :buf(b), @@ -343,16 +324,16 @@ namespace fleece { /** A \ref slice that owns a heap-allocated, ref-counted block of memory. */ struct [[nodiscard]] alloc_slice : public pure_slice { - constexpr alloc_slice() noexcept STEPOVER {} + constexpr alloc_slice() noexcept STEPOVER = default; constexpr alloc_slice(std::nullptr_t) noexcept STEPOVER {} constexpr alloc_slice(nullslice_t) noexcept STEPOVER {} inline explicit alloc_slice(size_t sz) STEPOVER; alloc_slice(const void* FL_NULLABLE b, size_t s) :alloc_slice(slice(b, s)) {} - alloc_slice(const void* start, - const void* end) :alloc_slice(slice(start, end)) {} + alloc_slice(const void* start, const void* end) :alloc_slice(slice(start, end)) {} explicit alloc_slice(const char* FL_NULLABLE str) :alloc_slice(slice(str)) {} + explicit alloc_slice(std::string_view str) STEPOVER :alloc_slice(slice(str)) {} explicit alloc_slice(const std::string &str) :alloc_slice(slice(str)) {} inline explicit alloc_slice(pure_slice s) STEPOVER; @@ -374,11 +355,12 @@ namespace fleece { inline static alloc_slice nullPaddedString(pure_slice); alloc_slice& operator= (pure_slice s) {return *this = alloc_slice(s);} - alloc_slice& operator= (FLSlice s) {return operator=(slice(s.buf,s.size));} + alloc_slice& operator= (FLSlice s) {return *this = alloc_slice(s);} alloc_slice& operator= (std::nullptr_t) noexcept {reset(); return *this;} // disambiguation: alloc_slice& operator= (const char *str) {*this = (slice)str; return *this;} + alloc_slice& operator=(std::string_view str) {*this = (slice)str; return *this;} alloc_slice& operator= (const std::string &str) {*this = (slice)str; return *this;} /// Releases and clears; same as assigning `nullslice`. @@ -405,12 +387,6 @@ namespace fleece { alloc_slice& operator= (FLHeapSlice) noexcept; operator FLHeapSlice () const noexcept {return {buf, size};} - // std::string_view interoperability: -#ifdef SLICE_SUPPORTS_STRING_VIEW - explicit alloc_slice(string_view str) STEPOVER :alloc_slice(slice(str)) {} - alloc_slice& operator=(string_view str) {*this = (slice)str; return *this;} -#endif - // CFData / CFString / NSData / NSString interoperability: #ifdef __APPLE__ // Implementations in slice+CoreFoundation.cc and slice+ObjC.mm @@ -445,17 +421,14 @@ namespace fleece { constexpr slice_NONNULL(slice s) :slice_NONNULL(s.buf, s.size) {} constexpr slice_NONNULL(FLSlice s) :slice_NONNULL(s.buf,s.size) {} constexpr slice_NONNULL(const char *str NONNULL) :slice(str) {} - slice_NONNULL(alloc_slice s) :slice_NONNULL(s.buf,s.size) {} + slice_NONNULL(const alloc_slice& s) :slice_NONNULL(s.buf,s.size) {} slice_NONNULL(const std::string &str) :slice_NONNULL(str.data(),str.size()) {} -#ifdef SLICE_SUPPORTS_STRING_VIEW - slice_NONNULL(string_view str) :slice_NONNULL(str.data(),str.size()) {} -#endif + slice_NONNULL(std::string_view str) :slice_NONNULL(str.data(),str.size()) {} slice_NONNULL(std::nullptr_t) =delete; slice_NONNULL(nullslice_t) =delete; }; - #ifdef __APPLE__ /** A slice holding the UTF-8 data of an NSString. If possible, it gets a pointer directly into the NSString in O(1) time -- so don't modify or release the NSString while this is in scope. @@ -475,14 +448,6 @@ namespace fleece { #endif - /** Functor class for hashing the contents of a slice. - \note The below declarations of `std::hash` usually make it unnecessary to use this. */ - struct sliceHash { - std::size_t operator() (pure_slice const& s) const {return s.hash();} - }; - - - #pragma mark - PURE_SLICE METHOD BODIES: diff --git a/Fleece/Integration/MDict.hh b/Fleece/Integration/MDict.hh index af5d0a26..10446efd 100644 --- a/Fleece/Integration/MDict.hh +++ b/Fleece/Integration/MDict.hh @@ -26,7 +26,7 @@ namespace fleece { public: using MValue = MValue; using MCollection = MCollection; - using MapType = std::unordered_map; + using MapType = std::unordered_map; /** Constructs an empty MDict not connected to any existing Fleece Dict. */ MDict() :MCollection() { }