Skip to content

Commit

Permalink
Expose additional FLKeyPath API
Browse files Browse the repository at this point in the history
Exposed existing methods of the internal KeyPath class to the C & C++
APIs, so we can use them in LiteCore code that uses the public API:

FLKeyPath_GetCount
FLKeyPath_NewEmpty
FLKeyPath_AddProperty
FLKeyPath_AddIndex
FLKeyPath_AddComponents
FLKeyPath_DropComponents
  • Loading branch information
snej committed Jun 6, 2024
1 parent 6be7745 commit 333c3e0
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 18 deletions.
42 changes: 34 additions & 8 deletions API/fleece/FLKeyPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,32 +46,58 @@ extern "C" {

/** Creates a new FLKeyPath object by compiling a path specifier string. */
NODISCARD FLEECE_PUBLIC FLKeyPath FL_NULLABLE FLKeyPath_New(FLSlice specifier,
FLError* FL_NULLABLE outError) FLAPI;
FLError* FL_NULLABLE outError) FLAPI;

/** Frees a compiled FLKeyPath object. (It's ok to pass NULL.) */
FLEECE_PUBLIC void FLKeyPath_Free(FLKeyPath FL_NULLABLE) FLAPI;

/** Evaluates a compiled key-path for a given Fleece root object. */
NODISCARD FLEECE_PUBLIC FLValue FL_NULLABLE FLKeyPath_Eval(FLKeyPath,
FLValue root) FLAPI;
FLValue root) FLAPI;

/** Evaluates a key-path from a specifier string, for a given Fleece root object.
If you only need to evaluate the path once, this is a bit faster than creating an
FLKeyPath object, evaluating, then freeing it. */
NODISCARD FLEECE_PUBLIC FLValue FL_NULLABLE FLKeyPath_EvalOnce(FLSlice specifier, FLValue root,
FLError* FL_NULLABLE outError) FLAPI;
FLError* FL_NULLABLE outError) FLAPI;

/** Returns a path in string form. */
NODISCARD FLEECE_PUBLIC FLStringResult FLKeyPath_ToString(FLKeyPath path) FLAPI;

/** Equality test. */
FLEECE_PUBLIC bool FLKeyPath_Equals(FLKeyPath path1, FLKeyPath path2) FLAPI;

/** Returns an element of a path, either a key or an array index. */
FLEECE_PUBLIC bool FLKeyPath_GetElement(FLKeyPath,
size_t i,
FLSlice *outDictKey,
int32_t *outArrayIndex) FLAPI;
/** The number of path components. */
FLEECE_PUBLIC size_t FLKeyPath_GetCount(FLKeyPath) FLAPI;

/** Returns an element of a path, either a key or an array index.
@param path The path to examine.
@param i The index of the component to examine.
@param outDictKey On return this will be the property name, or a null slice
if this component is an array index.
@param outArrayIndex On return this will be the array index,
or 0 if this component is a property.
@returns True on success, false if there is no such component. */
FLEECE_PUBLIC bool FLKeyPath_GetElement(FLKeyPath path,
size_t i,
FLSlice *outDictKey,
int32_t *outArrayIndex) FLAPI;

/** Creates a new _empty_ FLKeyPath, for the purpose of adding components to it. */
NODISCARD FLEECE_PUBLIC FLKeyPath FL_NULLABLE FLKeyPath_NewEmpty(void) FLAPI;

/** Appends a single property/key component to a path. The string should not be escaped. */
FLEECE_PUBLIC void FLKeyPath_AddProperty(FLKeyPath, FLString property) FLAPI;

/** Appends a single array index component to a path. */
FLEECE_PUBLIC void FLKeyPath_AddIndex(FLKeyPath, int index) FLAPI;

/** Appends one or more components, encoded as a specifier like the one passed to FLKeyPath_New. */
NODISCARD FLEECE_PUBLIC bool FLKeyPath_AddComponents(FLKeyPath, FLString specifier,
FLError* FL_NULLABLE outError) FLAPI;

/** Removes the first `n` components. */
FLEECE_PUBLIC void FLKeyPath_DropComponents(FLKeyPath, size_t n) FLAPI;

/** @} */

Expand Down
38 changes: 30 additions & 8 deletions API/fleece/Fleece.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "Fleece.h"
#endif
#include "slice.hh"
#include <stdexcept>
#include <string>
#include <utility>

Expand Down Expand Up @@ -255,7 +256,8 @@ namespace fleece {
property name (but not yet in the middle of a name.) */
class KeyPath {
public:
KeyPath(slice_NONNULL spec, FLError* FL_NULLABLE err) :_path(FLKeyPath_New(spec, err)) { }
KeyPath() :_path(FLKeyPath_NewEmpty()) { }
KeyPath(slice_NONNULL spec, FLError* FL_NULLABLE err) :_path(FLKeyPath_New(spec, err)) { }
~KeyPath() {FLKeyPath_Free(_path);}

KeyPath(KeyPath &&kp) :_path(kp._path) {kp._path = nullptr;}
Expand All @@ -264,27 +266,37 @@ namespace fleece {

KeyPath(const KeyPath &kp) :KeyPath(std::string(kp), nullptr) { }


explicit operator bool() const {return _path != nullptr;}
operator FLKeyPath FL_NONNULL () const {return _path;}

Value eval(Value root) const {
return FLKeyPath_Eval(_path, root);
}
size_t count() const {return FLKeyPath_GetCount(_path);}

inline std::pair<slice,int> get(size_t i) const;

Value eval(Value root) const {return FLKeyPath_Eval(_path, root);}

static Value eval(slice_NONNULL specifier, Value root, FLError* FL_NULLABLE error) {
return FLKeyPath_EvalOnce(specifier, root, error);
}

explicit operator std::string() const {
return std::string(alloc_slice(FLKeyPath_ToString(_path)));
}
alloc_slice toString() const {return FLKeyPath_ToString(_path);}
explicit operator std::string() const {return std::string(toString());}

bool operator== (const KeyPath &kp) const {return FLKeyPath_Equals(_path, kp._path);}

void addProperty(slice key) {FLKeyPath_AddProperty(_path, key);}
void addIndex(int index) {FLKeyPath_AddIndex(_path, index);}
bool addComponents(slice components, FLError* FL_NULLABLE err) {
return FLKeyPath_AddComponents(_path, components, err);
}
void dropComponents(size_t n) {FLKeyPath_DropComponents(_path, n);}

private:
KeyPath& operator=(const KeyPath&) =delete;
friend class Value;

FLKeyPath _path;
FLKeyPath FL_NULLABLE _path;
};


Expand Down Expand Up @@ -596,6 +608,16 @@ namespace fleece {
template<>
inline void Encoder::keyref::operator= (bool value) {_enc.writeKey(_key); _enc.writeBool(value);}

inline std::pair<slice,int> KeyPath::get(size_t i) const {
FLSlice key = {};
int32_t index = 0;
if (FLKeyPath_GetElement(_path, i, &key, &index))
return {key, index};
else
throw std::domain_error("invalid KeyPath index");
}


inline Doc Doc::fromJSON(slice_NONNULL json, FLError * FL_NULLABLE outError) {
return Doc(FLDoc_FromJSON(json, outError), false);
}
Expand Down
33 changes: 31 additions & 2 deletions Fleece/API_Impl/Fleece.cc
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ FLSliceResult FLDeepIterator_GetJSONPointer(FLDeepIterator i) FLAPI {

FLKeyPath FL_NULLABLE FLKeyPath_New(FLSlice specifier, FLError* FL_NULLABLE outError) FLAPI {
try {
return new Path((std::string)(slice)specifier);
return new Path(specifier);
} catchError(outError)
return nullptr;
}
Expand All @@ -570,7 +570,7 @@ FLValue FL_NULLABLE FLKeyPath_Eval(FLKeyPath path, FLValue root) FLAPI {

FLValue FL_NULLABLE FLKeyPath_EvalOnce(FLSlice specifier, FLValue root, FLError * FL_NULLABLE outError) FLAPI {
try {
return Path::eval((std::string)(slice)specifier, root);
return Path::eval(specifier, root);
} catchError(outError)
return nullptr;
}
Expand All @@ -583,6 +583,10 @@ bool FLKeyPath_Equals(FLKeyPath path1, FLKeyPath path2) FLAPI {
return *path1 == *path2;
}

size_t FLKeyPath_GetCount(FLKeyPath path) FLAPI {
return path->size();
}

bool FLKeyPath_GetElement(FLKeyPath path, size_t i, FLSlice *outKey, int32_t *outIndex) FLAPI {
if (i >= path->size())
return false;
Expand All @@ -592,6 +596,31 @@ bool FLKeyPath_GetElement(FLKeyPath path, size_t i, FLSlice *outKey, int32_t *ou
return true;
}

FLKeyPath FL_NULLABLE FLKeyPath_NewEmpty(void) FLAPI {
return new Path();
}

void FLKeyPath_AddProperty(FLKeyPath path, FLString property) FLAPI {
if (property.size > 0)
path->addProperty(property);
}

void FLKeyPath_AddIndex(FLKeyPath path, int index) FLAPI {
path->addIndex(index);
}

bool FLKeyPath_AddComponents(FLKeyPath path, FLString specifier, FLError* FL_NULLABLE outError) FLAPI {
try {
path->addComponents(specifier);
return true;
} catchError(outError)
return false;
}

void FLKeyPath_DropComponents(FLKeyPath path, size_t n) FLAPI {
path->drop(n);
}


#pragma mark - ENCODER:

Expand Down

0 comments on commit 333c3e0

Please sign in to comment.