diff --git a/src/AccessorDefs.h b/src/AccessorDefs.h new file mode 100644 index 000000000..8b3560263 --- /dev/null +++ b/src/AccessorDefs.h @@ -0,0 +1,20 @@ +#pragma once + +#include "AccessorUtils/NamedType.h" +#include +#include + +//namespace eccodes::accessor { + +class grib_accessor; +using AccessorPtr = grib_accessor *; +//using AccessorPtr = std::shared_ptr; + +class AccessorData; +using AccessorDataPtr = std::unique_ptr; + +using AccessorName = NamedType; +using AccessorType = NamedType; +using AccessorNameSpace = NamedType; + +//} diff --git a/src/AccessorFactory.cc b/src/AccessorFactory.cc new file mode 100644 index 000000000..e459e4b4b --- /dev/null +++ b/src/AccessorFactory.cc @@ -0,0 +1,88 @@ +#include "AccessorFactory.h" +#include "AccessorUtils/AccessorException.h" +#include "grib_api_internal.h" + +#include + +//namespace eccodes::accessor { + +AccessorFactory::~AccessorFactory() { + std::lock_guard guard(mutex_); + if(!builders_.empty()) + { + for(auto it = builders_.begin(); it != builders_.end();) + { + grib_context* context = grib_context_get_default(); + grib_context_log(context, GRIB_LOG_DEBUG, "AccessorFactory::~AccessorFactory - Erasing %s", it->first.get().c_str()); + it = builders_.erase(it); + } + } +} + +AccessorFactory& AccessorFactory::instance() { + static AccessorFactory theOne; + return theOne; +} + +void AccessorFactory::add(AccessorType const& type, AccessorBuilderBase* builder) +{ + std::lock_guard guard(mutex_); + if (has(type)) { + throw AccessorException("AccessorFactory::add - duplicate entry: " + type.get()); + } + builders_[type] = builder; +} + +void AccessorFactory::remove(AccessorType const& type) +{ + std::lock_guard guard(mutex_); + builders_.erase(type); +} + +bool AccessorFactory::has(AccessorType const& type) +{ + std::lock_guard guard(mutex_); + return builders_.find(type) != builders_.end(); +} + +void AccessorFactory::list(std::ostream& out) +{ + std::lock_guard guard(mutex_); + grib_context* context = grib_context_get_default(); + const char* sep = ""; + for (auto const& entry : builders_) { + grib_context_log(context, GRIB_LOG_DEBUG, "%s, ", entry.first.get().c_str()); + } +} + +AccessorPtr AccessorFactory::build(AccessorType const& type, AccessorName const& name, AccessorNameSpace const& nameSpace) +{ + std::lock_guard guard(mutex_); + + if (auto builder_ = builders_.find(type); builder_ == builders_.end()) { + grib_context* context = grib_context_get_default(); + grib_context_log(context, GRIB_LOG_ERROR, "No AccessorBuilder called %s", type.get().c_str()); + grib_context_log(context, GRIB_LOG_ERROR, "AccessorBuilders are:"); + for (auto const& entry : builders_) { + grib_context_log(context, GRIB_LOG_ERROR, "No AccessorBuilder called %s", entry.first.get().c_str()); + } + throw AccessorException(std::string("No AccessorBuilder called ") + type.get()); + } + else { + AccessorPtr ptr = builder_->second->make(name, nameSpace); + // TOOD(maee): Re-enable this when AccessorStore is used + //AccessorStore::instance().addAccessor(ptr); + return ptr; + } +} + +AccessorBuilderBase::AccessorBuilderBase(AccessorType const& type) : + type_(type) { + AccessorFactory::instance().add(type_, this); +} + +AccessorBuilderBase::~AccessorBuilderBase() { + AccessorFactory::instance().remove(type_); +} + +//} diff --git a/src/AccessorFactory.h b/src/AccessorFactory.h new file mode 100644 index 000000000..c42226b09 --- /dev/null +++ b/src/AccessorFactory.h @@ -0,0 +1,50 @@ +#pragma once + +#include "AccessorDefs.h" +#include +#include + +//namespace eccodes::accessor { + +class AccessorBuilderBase { + AccessorType type_; + +public: + AccessorBuilderBase(AccessorType const&); + virtual ~AccessorBuilderBase(); + virtual AccessorPtr make(AccessorName const& name, AccessorNameSpace const& nameSpace) = 0; +}; + +template +class AccessorBuilder : public AccessorBuilderBase { + AccessorPtr make(AccessorName const& name, AccessorNameSpace const& nameSpace) override { + return new ACCESSOR_DATA_TYPE(); + } + + +public: + AccessorBuilder() : + AccessorBuilderBase(ACCESSOR_DATA_TYPE::accessor_type) {} +}; + +class AccessorFactory { +public: + static AccessorFactory& instance(); + + ~AccessorFactory(); + + void add(AccessorType const& type, AccessorBuilderBase* builder); + void remove(AccessorType const& type); + bool has(AccessorType const& type); + void list(std::ostream&); + + AccessorPtr build(AccessorType const& type, AccessorName const& name, AccessorNameSpace const& nameSpace); + +private: + AccessorFactory() {} + + std::map builders_; + std::recursive_mutex mutex_; +}; + +//} diff --git a/src/AccessorUtils/AccessorException.h b/src/AccessorUtils/AccessorException.h new file mode 100644 index 000000000..995d56c25 --- /dev/null +++ b/src/AccessorUtils/AccessorException.h @@ -0,0 +1,28 @@ +#pragma once + +// Utilities provided to help get the C++ build working +// +// May be replaced with ECKit or other code at a later date + +#include +#include + +//namespace eccodes::accessor { + +using GribStatus = int; + +class AccessorException : public std::exception{ +std::string what_; + GribStatus code_{}; + +public: + AccessorException(int code) : code_{code} {} + AccessorException(std::string const& what) : what_{what} {} + + const char* what() const noexcept override { return what_.c_str(); } + GribStatus code() const { return code_; } + +}; + +//} + diff --git a/src/AccessorUtils/NamedType.h b/src/AccessorUtils/NamedType.h new file mode 100644 index 000000000..f186211d7 --- /dev/null +++ b/src/AccessorUtils/NamedType.h @@ -0,0 +1,26 @@ +#pragma once + +// https://www.fluentcpp.com/2016/12/08/strong-types-for-strong-interfaces/ + +#include + +//namespace eccodes::accessor { + +template +class NamedType +{ +public: + explicit NamedType(T const& value) : value_(value) {} + explicit NamedType(T&& value) : value_(std::move(value)) {} + T& get() { return value_; } + T const& get() const {return value_; } + + bool hasValue() { return value_ != T{}; } + + friend bool operator<(const NamedType& l, const NamedType& r) { return l.value_ < r.value_; } + +private: + T value_; +}; + +//} diff --git a/src/grib_accessor_class.cc b/src/grib_accessor_class.cc index d19aa48aa..487945562 100644 --- a/src/grib_accessor_class.cc +++ b/src/grib_accessor_class.cc @@ -10,12 +10,7 @@ #include "grib_api_internal.h" -//#include "grib_accessor_classes_hash.cc" -#include -#include "GribCpp/GribStatus.h" -#include "AccessorUtils/AccessorLogger.h" #include "AccessorFactory.h" -//#include "AccessorStore.h" /* This file is generated by ./make_class.pl */