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
Compare and Show latest version
6 files
+ 392
121
Compare changes
  • Side-by-side
  • Inline
Files
6
+ 234
70
@@ -29,28 +29,237 @@
#ifndef CAOSDB_ENTITY_H
#define CAOSDB_ENTITY_H
#include <string> // for string
#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message
#include "caosdb/entity/v1alpha1/main.pb.h" // for ProtoEntity, ProtoParent...
#include "caosdb/message_code.h" // for get_message_code, Messag...
#include "google/protobuf/util/json_util.h" // for MessageToJsonString, Jso...
#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 {
using caosdb::entity::v1alpha1::IdResponse;
using ProtoParent = caosdb::entity::v1alpha1::Parent;
using ProtoProperty = caosdb::entity::v1alpha1::Property;
using ProtoEntity = caosdb::entity::v1alpha1::Entity;
using ProtoMessage = caosdb::entity::v1alpha1::Message;
using ::google::protobuf::RepeatedPtrField;
static const std::string logger_name = "caosdb::entity";
/**
* Messages convey information about the state and result of transactions.
* 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 container.
*/
[[nodiscard]] inline auto Size() const -> int { return wrapped->size(); }
/**
* Return a const reference to the element at the given index.
*/
[[nodiscard]] inline auto At(int index) const -> const T & {
return *mutable_at(index);
}
/**
* 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;
virtual ~RepeatedPtrFieldWrapper(){};
protected:
RepeatedPtrFieldWrapper(){};
explicit inline RepeatedPtrFieldWrapper(
::google::protobuf::RepeatedPtrField<P> *wrapped)
: wrapped(wrapped){};
/**
* 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 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();
}
@@ -61,23 +270,20 @@ public:
// friend class Parent;
// friend class Property;
friend class Messages;
friend class RepeatedPtrFieldWrapper<Message, ProtoMessage>;
private:
explicit inline Message(caosdb::entity::v1alpha1::Message *wrapped)
: wrapped(wrapped){};
explicit inline Message(ProtoMessage *wrapped) : wrapped(wrapped){};
caosdb::entity::v1alpha1::Message *wrapped;
ProtoMessage *wrapped;
};
/**
* Container for Messages.
*/
class Messages {
class Messages : public RepeatedPtrFieldWrapper<Message, ProtoMessage> {
public:
[[nodiscard]] inline auto Size() const -> int { return wrapped->size(); }
[[nodiscard]] inline auto At(int index) const -> const Message {
return Message(&(wrapped->at(index)));
}
~Messages();
friend class Entity;
// TODO(fspreck) Same here.
@@ -85,10 +291,7 @@ public:
// friend class Property;
private:
inline Messages() : wrapped(nullptr){};
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Message>
*wrapped;
inline Messages() : RepeatedPtrFieldWrapper(){};
};
/**
@@ -168,6 +371,7 @@ public:
friend class Entity;
friend class Parents;
friend class RepeatedPtrFieldWrapper<Parent, ProtoParent>;
private:
/**
@@ -196,42 +400,17 @@ private:
*
* Should only be instantiated and write-accessed by the owning entity.
*/
class Parents {
class Parents : public RepeatedPtrFieldWrapper<Parent, ProtoParent> {
public:
/**
* 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)));
}
~Parents() = default;
friend class Entity;
private:
inline Parents(){};
inline Parents() : RepeatedPtrFieldWrapper(){};
explicit inline Parents(
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent>
*wrapped)
: wrapped(wrapped){};
/**
* Append a parent.
*
* This increases the Size() by one.
*/
auto Append(const Parent &parent) -> void;
/**
* The collection of parent messages which serves as a backend for this
* class.
*/
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent>
*wrapped;
: RepeatedPtrFieldWrapper(wrapped){};
};
/**
@@ -321,6 +500,7 @@ public:
friend class Entity;
friend class Properties;
friend class RepeatedPtrFieldWrapper<Property, ProtoProperty>;
private:
static auto CreateProtoProperty() -> ProtoProperty *;
@@ -333,21 +513,11 @@ private:
*
* Should only be instantiated and write-accessed by the owning entity.
*/
class Properties {
class Properties
: public RepeatedPtrFieldWrapper<Property,
caosdb::entity::v1alpha1::Property> {
public:
/**
* 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 Property(&(wrapped->at(index)));
}
~Properties() = default;
friend class Entity;
private:
@@ -355,17 +525,8 @@ private:
explicit inline Properties(
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Property>
*wrapped)
: wrapped(wrapped){};
/**
* Append a property
*
* This increases the Size() by one.
*/
auto Append(const Property &property) -> void;
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Property>
*wrapped;
: RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property>(
wrapped){};
};
/**
@@ -447,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