Skip to content
Snippets Groups Projects

ENH: Add retrieval and queries to Extern C interface

Merged Florian Spreckelsen requested to merge f-extended-c into f-files
2 unresolved threads
3 files
+ 296
99
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 170
72
@@ -33,7 +33,9 @@
#include "caosdb/message_code.h" // for get_message_code, Messag...
#include <google/protobuf/util/json_util.h> // for MessageToJsonString, Jso...
#include <google/protobuf/message.h> // for RepeatedPtrField, Message
#include <iterator> // for iterator, output_iterato...
#include <map> // for map
#include <stdexcept> // for out_of_range
#include <string> // for string
namespace caosdb::entity {
@@ -46,12 +48,17 @@ using ::google::protobuf::RepeatedPtrField;
static const std::string logger_name = "caosdb::entity";
/**
* Abstract base class for Messages, Properties and Parents container classes.
*
* This is a list-like class.
*/
template <typename T, typename P> class RepeatedPtrFieldWrapper {
class iterator;
public:
/**
* Return the current size of the properties container.
*
* This is also the number of properties the owning entity currently has.
* Return the current size of the container.
*/
[[nodiscard]] inline auto Size() const -> int { return wrapped->size(); }
/**
@@ -65,11 +72,30 @@ public:
* Return a mutable pointer to the element at the given index.
*/
[[nodiscard]] inline auto mutable_at(int index) const -> T * {
if (index >= Size() || index < 0) {
throw std::out_of_range("Container has size " + std::to_string(Size()));
}
if (cache.count(index) == 0) {
cache.emplace(index, T(&(wrapped->at(index))));
}
return &(cache.at(index));
}
/**
* Return iterator positioned at the beginning of the list.
*/
auto begin() -> iterator;
/**
* Return iterator positioned at the end of the list.
*/
auto end() -> iterator;
/**
* Return constant iterator positioned at the beginning of the list.
*/
auto begin() const -> const iterator;
/**
* Return constant iterator positioned at the end of the list.
*/
auto end() const -> const iterator;
friend class Entity;
@@ -81,23 +107,159 @@ protected:
::google::protobuf::RepeatedPtrField<P> *wrapped)
: wrapped(wrapped){};
virtual auto Append(const T &element) -> void = 0;
/**
* Append an element. This adds the element to the end of the wrapped list
* and increases the size by one.
*/
inline auto Append(const T &element) -> void {
auto *destination = this->wrapped->Add();
destination->Swap(element.wrapped);
// Clear the originally wrapped object and return it to the Arena
element.wrapped->Clear();
// set the pointer to the new object which is owned by the RepeatedPtrField
element.wrapped = destination;
}
/**
* Remove the element at the given index.
*/
inline auto remove(int index) -> void {
this->wrapped->DeleteSubrange(index, 1);
if (cache.count(index) > 0) {
cache.erase(index);
}
// shift all indices in the cache above index (such that the values do not
// get deleted/copied because this could destroy pointers (c-interface).
// auto next = cache.begin();
// while(next != cache.end()) {
// auto cached = *next;
// if(cached.first > index) {
// std::make_pair<int, T>(cached.first-1,
//}
// cached.first
// next = std::next(next);
//}
// for(auto &cached : cache) {
// if(cached.first > index) {
// cached.first--;
//}
//}
// for(int i = index + 1; i < Size(); i++) {
// if(cache.count(i)>0) {
// cache.at(i).wrapped = &(this->wrapped->at(i));
//}
//}
for (int i = index + 1; i < Size(); i++) {
if (cache.count(i) > 0) {
auto handle = cache.extract(i);
handle.key()--;
cache.insert(std::move(handle));
}
}
}
::google::protobuf::RepeatedPtrField<P> *wrapped;
mutable std::map<int, T> cache;
private:
class iterator : public std::iterator<std::output_iterator_tag, T> {
public:
explicit iterator(const RepeatedPtrFieldWrapper<T, P> *instance,
int index = 0);
auto operator*() const -> T &;
auto operator++() -> iterator &;
auto operator++(int) -> iterator;
auto operator!=(const iterator &rhs) const -> bool;
private:
int current_index = 0;
const RepeatedPtrFieldWrapper<T, P> *instance;
};
};
template <class T, class P>
RepeatedPtrFieldWrapper<T, P>::iterator::iterator(
const RepeatedPtrFieldWrapper<T, P> *instance, int index)
: current_index(index), instance(instance) {}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::iterator::operator*() const -> T & {
return *(this->instance->mutable_at(current_index));
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::iterator::operator++()
-> RepeatedPtrFieldWrapper<T, P>::iterator & {
current_index++;
return *this;
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::iterator::operator++(int)
-> RepeatedPtrFieldWrapper<T, P>::iterator {
iterator tmp(*this);
operator++();
return tmp;
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::iterator::operator!=(
const iterator &rhs) const -> bool {
return this->current_index != rhs.current_index;
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::begin()
-> RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, 0);
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::end()
-> RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, Size());
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::begin() const
-> const RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, 0);
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::end() const
-> const RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, Size());
}
/**
* Messages convey information about the state and result of transactions.
* Messages convey information about the state of entities and result of
* transactions.
*
* A Message object can be thought of as kinf of a generalized error object in
* other frameworks. Please have a look at MessageCodes for more details.
*/
class Message {
public:
/**
* Get the code of this message.
*
* The message code is a unique identifier of the type of message and is
* intended to make it easiert to identify messages in a machine-readable
* way.
*/
[[nodiscard]] inline auto GetCode() const -> MessageCode {
return get_message_code(wrapped->code());
}
/**
* Get the description of this message.
*
* The description is intended for a human reader.
*/
[[nodiscard]] inline auto GetDescription() const -> std::string {
return wrapped->description();
}
@@ -122,10 +284,6 @@ private:
class Messages : public RepeatedPtrFieldWrapper<Message, ProtoMessage> {
public:
~Messages();
//[[nodiscard]] inline auto Size() const -> int { return wrapped->size(); }
//[[nodiscard]] inline auto At(int index) const -> const Message {
// return Message(&(wrapped->at(index)));
//}
friend class Entity;
// TODO(fspreck) Same here.
@@ -134,10 +292,6 @@ public:
private:
inline Messages() : RepeatedPtrFieldWrapper(){};
auto Append(const Message &message) -> void override;
//::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Message>
//*wrapped;
};
/**
@@ -249,19 +403,6 @@ private:
class Parents : public RepeatedPtrFieldWrapper<Parent, ProtoParent> {
public:
~Parents() = default;
/**
* Return the current size of the parent container.
*
* That is also the number of parents the owning entity currently has.
*/
//[[nodiscard]] inline auto Size() const -> int { return wrapped->size(); }
/**
* Return the parent at the given index.
*/
//[[nodiscard]] inline auto At(int index) const -> const Parent {
// return Parent(&(wrapped->at(index)));
//}
friend class Entity;
private:
@@ -270,20 +411,6 @@ private:
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent>
*wrapped)
: RepeatedPtrFieldWrapper(wrapped){};
//: wrapped(wrapped){};
/**
* Append a parent.
*
* This increases the Size() by one.
*/
auto Append(const Parent &parent) -> void override;
/**
* The collection of parent messages which serves as a backend for this
* class.
*/
//::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent>
//*wrapped;
};
/**
@@ -391,26 +518,6 @@ class Properties
caosdb::entity::v1alpha1::Property> {
public:
~Properties() = default;
/**
* Return the current size of the properties container.
*
* This is also the number of properties the owning entity currently has.
*/
//[[nodiscard]] inline auto Size() const -> int { return wrapped->size(); }
/**
* Return the property at the given index.
*/
//[[nodiscard]] auto At(int index) const -> const Property & {
// return mutable_at(index);
//}
//[[nodiscard]] auto mutable_at(int index) const -> Property & {
// if (cache.count(index) == 0) {
// cache.emplace(index, Property(&(wrapped->at(index))));
//}
// return cache.at(index);
//}
friend class Entity;
private:
@@ -420,18 +527,6 @@ private:
*wrapped)
: RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property>(
wrapped){};
//: wrapped(wrapped){};
/**
* Append a property
*
* This increases the Size() by one.
*/
auto Append(const Property &property) -> void override;
//::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Property>
//*wrapped;
// mutable std::map<int, Property> cache;
};
/**
@@ -513,9 +608,12 @@ public:
auto SetUnit(const std::string &unit) -> void;
// Currently no references or lists.
auto SetDatatype(const std::string &datatype) -> void;
auto AppendProperty(const Property &property) -> void;
auto RemoveProperty(int index) -> void;
auto AppendParent(const Parent &parent) -> void;
auto RemoveParent(int index) -> void;
/**
* Copy all of this entity's features to the target ProtoEntity.
*/
Loading