-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathExpert.hh
More file actions
204 lines (153 loc) · 7.63 KB
/
Expert.hh
File metadata and controls
204 lines (153 loc) · 7.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//
// Expert.hh
//
// Copyright 2017-Present Couchbase, Inc.
//
// Use of this software is governed by the Business Source License included
// in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
// in that file, in accordance with the Business Source License, use of this
// software will be governed by the Apache License, Version 2.0, included in
// the file licenses/APL2.txt.
//
#pragma once
#ifndef _FLEECE_OBSCURE_HH
#define _FLEECE_OBSCURE_HH
#ifndef _FLEECE_HH
#include "Fleece.hh"
#endif
#include "FLExpert.h"
FL_ASSUME_NONNULL_BEGIN
namespace fleece {
// VOLATILE API: These methods are meant for internal use, and will be removed
// in a future release
// Rarely-needed or advanced functionality; a C++ wrapper around fleece/FLExpert.h
// For documentation, see the comments above the C functions these wrap.
/** Just a simple wrapper around \ref FLValue_FromData.
You should generally use a \ref Doc instead; it's safer.*/
static inline Value ValueFromData(slice data, FLTrust t =kFLUntrusted) {
return FLValue_FromData(data,t);
}
//====== ENCODER:
/** Encoder subclass that exposes more bells and whistles, most of which are experimental.
You don't actually instantiate this, you call `expert(enc)` (below) to make a reference. */
class Encoder_ExpertAPI : public Encoder {
public:
Encoder_ExpertAPI() = delete;
/// Creates an Encoder that writes directly to a file.
static inline Encoder encodeToFile(FILE *file, bool uniqueStrings =true);
inline void amend(slice base, bool reuseStrings =false, bool externPointers =false);
slice base() const {return FLEncoder_GetBase(_enc);}
void suppressTrailer() {FLEncoder_SuppressTrailer(_enc);}
inline void writeRaw(slice data) {FLEncoder_WriteRaw(_enc, data);}
size_t bytesWritten() const {return FLEncoder_BytesWritten(_enc);}
size_t nextWritePos() const {return FLEncoder_GetNextWritePos(_enc);}
inline size_t finishItem() {return FLEncoder_FinishItem(_enc);}
};
// use this to call one of the above methods; e.g. `expert(e).suppressTrailer()`.
static inline auto& expert(Encoder &enc) {return (Encoder_ExpertAPI&)enc;}
static inline auto& expert(const Encoder &enc) {return (const Encoder_ExpertAPI&)(enc);}
//====== DELTAS:
/** Generates and applyies JSON-format deltas/diffs between two Fleece values.
See <https://github.com/couchbaselabs/fleece/wiki/Advanced-Fleece#5-json-deltas> */
class JSONDelta {
public:
static inline alloc_slice create(Value old, Value nuu);
static inline bool create(Value old, Value nuu, Encoder &jsonEncoder);
static inline alloc_slice apply(Value old,
slice jsonDelta,
FLError* FL_NULLABLE error);
static inline bool apply(Value old,
slice jsonDelta,
Encoder &encoder);
};
//====== SHARED KEYS:
/** Keeps track of a set of dictionary keys that are stored in abbreviated (small integer) form.
Encoders can be configured to use an instance of this, and will use it to abbreviate keys
that are given to them as strings. (Note: This class is not thread-safe!)
See <https://github.com/couchbaselabs/fleece/wiki/Advanced-Fleece#4-shared-keys> */
class SharedKeys {
public:
SharedKeys() :_sk(nullptr) { }
SharedKeys(FLSharedKeys FL_NULLABLE sk) :_sk(FLSharedKeys_Retain(sk)) { }
~SharedKeys() {FLSharedKeys_Release(_sk);}
static SharedKeys create() {return SharedKeys(FLSharedKeys_New(), 1);}
static inline SharedKeys create(slice state);
bool loadState(slice data) {return FLSharedKeys_LoadStateData(_sk, data);}
bool loadState(Value state) {return FLSharedKeys_LoadState(_sk, state);}
alloc_slice stateData() const {return FLSharedKeys_GetStateData(_sk);}
inline void writeState(const Encoder &enc);
unsigned count() const {return FLSharedKeys_Count(_sk);}
void revertToCount(unsigned count) {FLSharedKeys_RevertToCount(_sk, count);}
operator FLSharedKeys FL_NULLABLE () const {return _sk;}
bool operator== (SharedKeys other) const {return _sk == other._sk;}
SharedKeys(const SharedKeys &other) noexcept :_sk(FLSharedKeys_Retain(other._sk)) { }
SharedKeys(SharedKeys &&other) noexcept :_sk(other._sk) {other._sk = nullptr;}
inline SharedKeys& operator= (const SharedKeys &other);
inline SharedKeys& operator= (SharedKeys &&other) noexcept;
private:
SharedKeys(FLSharedKeys sk, int) :_sk(sk) { }
FLSharedKeys FL_NULLABLE _sk {nullptr};
};
//====== DEPRECATED:
/** A Dict that manages its own storage. This has been superseded by \ref Doc. */
class AllocedDict : public Dict, alloc_slice {
public:
AllocedDict()
=default;
explicit AllocedDict(alloc_slice s)
:Dict(FLValue_AsDict(FLValue_FromData(s, kFLUntrusted)))
,alloc_slice(std::move(s))
{ }
explicit AllocedDict(slice s)
:AllocedDict(alloc_slice(s)) { }
const alloc_slice& data() const {return *this;}
explicit operator bool () const {return Dict::operator bool();}
// MI disambiguation:
inline Value operator[] (slice key) const {return Dict::get(key);}
inline Value operator[] (const char *key) const {return Dict::get(key);}
};
//====== IMPLEMENTATION GUNK:
inline Encoder Encoder_ExpertAPI::encodeToFile(FILE *file, bool uniqueStrings) {
return Encoder(FLEncoder_NewWritingToFile(file, uniqueStrings));
}
inline void Encoder_ExpertAPI::amend(slice base, bool reuseStrings, bool externPointers) {
FLEncoder_Amend(_enc, base, reuseStrings, externPointers);
}
inline alloc_slice JSONDelta::create(Value old, Value nuu) {
return FLCreateJSONDelta(old, nuu);
}
inline bool JSONDelta::create(Value old, Value nuu, Encoder &jsonEncoder) {
return FLEncodeJSONDelta(old, nuu, jsonEncoder);
}
inline alloc_slice JSONDelta::apply(Value old, slice jsonDelta, FLError * FL_NULLABLE error) {
return FLApplyJSONDelta(old, jsonDelta, error);
}
inline bool JSONDelta::apply(Value old,
slice jsonDelta,
Encoder &encoder)
{
return FLEncodeApplyingJSONDelta(old, jsonDelta, encoder);
}
inline void SharedKeys::writeState(const Encoder &enc) {
FLSharedKeys_WriteState(_sk, enc);
}
inline SharedKeys SharedKeys::create(slice state) {
auto sk = create();
sk.loadState(state);
return sk;
}
inline SharedKeys& SharedKeys::operator= (const SharedKeys &other) {
auto sk = FLSharedKeys_Retain(other._sk);
FLSharedKeys_Release(_sk);
_sk = sk;
return *this;
}
inline SharedKeys& SharedKeys::operator= (SharedKeys &&other) noexcept {
FLSharedKeys_Release(_sk);
_sk = other._sk;
other._sk = nullptr;
return *this;
}
}
FL_ASSUME_NONNULL_END
#endif // _FLEECE_OBSCURE_HH