Couchbase Lite C++
Couchbase Lite C++ API
Loading...
Searching...
No Matches
Base.hh
Go to the documentation of this file.
1//
2// Base.hh
3//
4// Copyright (c) 2019 Couchbase, Inc All rights reserved.
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17//
18
19#pragma once
20#include "cbl/CBLBase.h"
21#include "cbl/CBLQueryTypes.h"
22#include "fleece/slice.hh"
23#include <algorithm>
24#include <functional>
25#include <cassert>
26#include <memory>
27#include <stdexcept>
28#include <utility>
29
30#if DEBUG
31#include "cbl/CBLLog.h"
32#endif
33
34
36
39inline bool operator== (const CBLError &e1, const CBLError &e2) {
40 if (e1.code != 0)
41 return e1.domain == e2.domain && e1.code == e2.code;
42 else
43 return e2.code == 0;
44}
45
46namespace cbl {
47
49 using slice = fleece::slice;
51 using alloc_slice = fleece::alloc_slice;
52
54
55 // Internal base class of the C++ wrapper classes; it holds the reference to the
56 // underlying ref-counted C object and manages retain/release for it.
57 // Not part of the public API, and excluded from the API docs.
58 class RefCounted {
59 protected:
60 RefCounted() noexcept :_ref(nullptr) { }
61 explicit RefCounted(CBLRefCounted* _cbl_nullable ref) noexcept :_ref(CBL_Retain(ref)) { }
62 RefCounted(const RefCounted &other) noexcept :_ref(CBL_Retain(other._ref)) { }
63 RefCounted(RefCounted &&other) noexcept :_ref(other._ref) {other._ref = nullptr;}
64 ~RefCounted() noexcept {CBL_Release(_ref);}
65
66 RefCounted& operator= (const RefCounted &other) noexcept {
67 CBL_Retain(other._ref);
68 CBL_Release(_ref);
69 _ref = other._ref;
70 return *this;
71 }
72
73 RefCounted& operator= (RefCounted &&other) noexcept {
74 if (other._ref != _ref) {
75 CBL_Release(_ref);
76 _ref = other._ref;
77 other._ref = nullptr;
78 }
79 return *this;
80 }
81
82 void clear() {CBL_Release(_ref); _ref = nullptr;}
83 bool valid() const {return _ref != nullptr;}
84 explicit operator bool() const {return valid();}
85
87
88 friend class Extension;
89 friend class Transaction;
90 };
91
97 struct Error: std::runtime_error {
102 Error(CBLErrorDomain domain, int code, const std::string& what)
103 : std::runtime_error(what)
104 , domain(domain)
105 , code(code)
106 {}
108 : std::runtime_error("")
110 , code(0)
111 {}
112 Error& operator=(const Error& other) {
113 std::runtime_error::operator=(other);
114 domain = other.domain;
115 code = other.code;
116 return *this;
117 }
119 int code;
120 };
121
122 namespace internal {
123 inline std::string asString(FLSlice s) {return slice(s).asString();}
124 inline std::string asString(FLSliceResult &&s) {return alloc_slice(s).asString();}
125
126 inline void check(bool ok, CBLError &error) {
127 if (!ok) {
128 alloc_slice message = CBLError_Message(&error);
129#if DEBUG
130 CBL_Log(kCBLLogDomainDatabase, kCBLLogError, "API returning error %d/%d: %.*s",
131 error.domain, error.code, (int)message.size, (char*)message.buf);
132#endif
133 throw cbl::Error{error.domain, error.code, message.asString()};
134 }
135 }
136 }
137
138// For use by the cbl++ headers only: generates the public boilerplate members (ctors,
139// assignment ops, comparisons, ref()) that each wrapper class must declare itself.
140#define CBL_REFCOUNTED_WITHOUT_COPY_MOVE_BOILERPLATE(CLASS, SUPER, C_TYPE) \
141public: \
142 \
143 CLASS() noexcept :SUPER() { } \
144 \
145 CLASS& operator=(std::nullptr_t) {clear(); return *this;} \
146 \
147 bool valid() const {return RefCounted::valid();} \
148 \
149 explicit operator bool() const {return valid();} \
150 \
151 bool operator==(const CLASS &other) const {return _ref == other._ref;} \
152 \
153 bool operator!=(const CLASS &other) const {return _ref != other._ref;} \
154 \
155 C_TYPE* _cbl_nullable ref() const {return (C_TYPE*)_ref;}\
156protected: \
157 \
158 explicit CLASS(C_TYPE* _cbl_nullable ref) :SUPER((CBLRefCounted*)ref) { }
159
160#define CBL_REFCOUNTED_BOILERPLATE(CLASS, SUPER, C_TYPE) \
161CBL_REFCOUNTED_WITHOUT_COPY_MOVE_BOILERPLATE(CLASS, SUPER, C_TYPE) \
162public: \
163 \
164 CLASS(const CLASS &other) noexcept :SUPER(other) { } \
165 \
166 CLASS(CLASS &&other) noexcept :SUPER((SUPER&&)other) { } \
167 \
168 CLASS& operator=(const CLASS &other) noexcept {SUPER::operator=(other); return *this;} \
169 \
170 CLASS& operator=(CLASS &&other) noexcept {SUPER::operator=((SUPER&&)other); return *this;}
171
176 template <class... Args>
178 public:
180 using Callback = std::function<void(Args...)>;
181
183 ListenerToken() =default;
186
191 :_callback(new Callback(cb))
192 { }
193
196 :_token(other._token),
197 _callback(std::move(other._callback))
198 {other._token = nullptr;}
199
203 CBLListener_Remove(_token);
204 _token = other._token;
205 other._token = nullptr;
206 _callback = std::move(other._callback);
207 return *this;
208 }
209
211 void remove() {
212 CBLListener_Remove(_token);
213 _token = nullptr;
214 _callback = nullptr;
215 }
216
218 void* _cbl_nullable context() const {return _callback.get();}
221 CBLListenerToken* _cbl_nullable token() const {return _token;}
224 void setToken(CBLListenerToken* token) {assert(!_token); _token = token;}
225
228 static void call(void* _cbl_nullable context, Args... args) {
229 auto listener = (Callback*)context;
230 (*listener)(args...);
231 }
232
233 private:
234 CBLListenerToken* _cbl_nullable _token {nullptr};
235 std::shared_ptr<Callback> _callback; // Use shared_ptr instead of unique_ptr to allow to move
236
237 ListenerToken(const ListenerToken&) =delete;
238 ListenerToken& operator=(const ListenerToken &other) =delete;
239 };
240}
241
bool operator==(const CBLError &e1, const CBLError &e2)
Equality for two CBLError values.
Definition Base.hh:39
#define _cbl_nullable
#define CBL_ASSUME_NONNULL_END
#define CBL_ASSUME_NONNULL_BEGIN
Manages Couchbase Lite extensions, such as the Vector Search extension.
Definition Database.hh:55
void remove()
Unregisters the listener early, before it leaves scope.
Definition Base.hh:211
~ListenerToken()
Unregisters the listener (if any) and releases the token.
Definition Base.hh:185
static void call(void *_Nullable context, Args... args)
Static thunk used as the C-API callback.
Definition Base.hh:228
ListenerToken()=default
Creates an empty, unregistered token.
ListenerToken & operator=(ListenerToken &&other)
Move-assigns a token: removes this token's existing listener (if any) and adopts the other token's re...
Definition Base.hh:202
ListenerToken(ListenerToken &&other)
Move-constructs a token, transferring ownership of the underlying listener registration.
Definition Base.hh:195
CBLListenerToken *_Nullable token() const
Returns the underlying CBLListenerToken (the C registration handle), or NULL if not registered.
Definition Base.hh:221
ListenerToken(Callback cb)
Creates a token wrapping the given callback.
Definition Base.hh:190
void *_Nullable context() const
Returns an opaque pointer used internally as the context argument for C-API callbacks.
Definition Base.hh:218
void setToken(CBLListenerToken *token)
Assigns the underlying CBLListenerToken returned from a C-API AddXxxListener call.
Definition Base.hh:224
std::function< void(Args...)> Callback
The type of the user callback that this token holds.
Definition Base.hh:180
A helper object for database transactions.
Definition Database.hh:495
CBLErrorDomain
FLSliceResult CBLError_Message(const CBLError *_cbl_nullable outError)
kCBLDomain
void CBLListener_Remove(CBLListenerToken *_cbl_nullable)
struct CBLListenerToken CBLListenerToken
void CBL_Log(CBLLogDomain domain, CBLLogLevel level, const char *format,...) __printflike(3
CBLQueryLanguage
struct CBLRefCounted CBLRefCounted
void CBL_Release(CBLRefCounted *_cbl_nullable)
CBLRefCounted * CBL_Retain(CBLRefCounted *_cbl_nullable)
Definition Base.hh:46
fleece::slice slice
Convenience alias for fleece::slice, a non-owning view of a byte range.
Definition Base.hh:49
CBLQueryLanguage QueryLanguage
Definition Base.hh:53
fleece::alloc_slice alloc_slice
Convenience alias for fleece::alloc_slice, an owning byte buffer.
Definition Base.hh:51
CBLErrorDomain domain
int code
Error code, specific to the domain. 0 always means no error.
Definition Base.hh:119
Error & operator=(const Error &other)
Definition Base.hh:112
Error()
Definition Base.hh:107
Error(CBLErrorDomain domain, int code, const std::string &what)
Constructs an Error.
Definition Base.hh:102
CBLErrorDomain domain
Domain of errors.
Definition Base.hh:118