IODA Bundle
CodecFactory.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 1996-2012 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 /// @author Simon Smart
12 /// @date January 2019
13 
14 #ifndef odc_core_CodecFactory_H
15 #define odc_core_CodecFactory_H
16 
17 #include <functional>
18 #include <map>
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 #include <cstdint>
23 
24 #include "eckit/memory/NonCopyable.h"
25 
26 #include "odc/api/ColumnType.h"
27 #include "odc/core/Exceptions.h"
28 #include "odc/ODBAPISettings.h"
29 
30 namespace odc {
31 namespace core {
32 
33 //----------------------------------------------------------------------------------------------------------------------
34 
35 class CodecBuilderBase;
36 class Codec;
37 template <typename ByteOrder> class DataStream;
38 class SameByteOrder;
39 class OtherByteOrder;
40 
41 
42 class CodecFactory : private eckit::NonCopyable {
43 
44 public: // methods
45 
46  CodecFactory();
47  ~CodecFactory();
48 
49  static CodecFactory& instance();
50 
51  void enregister(const std::string& name, CodecBuilderBase& builder);
52  void deregister(const std::string& name, CodecBuilderBase& builder);
53 
54  template <typename ByteOrder>
55  std::unique_ptr<Codec> build(const std::string& name, api::ColumnType type) const;
56 
57  template <typename ByteOrder>
58  std::unique_ptr<Codec> load(DataStream<ByteOrder>& ds, api::ColumnType type) const;
59 
60 private: // members
61 
62  mutable std::mutex m_;
63  std::map<std::string, std::reference_wrapper<CodecBuilderBase>> builders_;
64 };
65 
66 
67 //----------------------------------------------------------------------------------------------------------------------
68 
69 
71 
72 protected: // methods
73 
74  CodecBuilderBase(const std::string& name);
76 
77 public: // methods
78 
79  virtual std::unique_ptr<Codec> make(const SameByteOrder&, api::ColumnType) const = 0;
80  virtual std::unique_ptr<Codec> make(const OtherByteOrder&, api::ColumnType) const = 0;
81 
82 private: // members
83 
84  std::string name_;
85 };
86 
87 //----------------------------------------------------------------------------------------------------------------------
88 
89 template <template <typename> class CODEC>
91 
92 #ifndef _CRAYC
93  static_assert(CODEC<SameByteOrder>::codec_name() == CODEC<OtherByteOrder>::codec_name(), "Invalid name");
94 #endif
95 
96 public: // methods
97 
98  CodecBuilder() : CodecBuilderBase(CODEC<SameByteOrder>::codec_name()) {}
100 
101 private: // methods
102 
103  std::unique_ptr<Codec> make(const SameByteOrder&, api::ColumnType type) const override {
104  return std::unique_ptr<Codec>(new CODEC<SameByteOrder>(type));
105  }
106  std::unique_ptr<Codec> make(const OtherByteOrder&, api::ColumnType type) const override {
107  return std::unique_ptr<Codec>(new CODEC<OtherByteOrder>(type));
108  }
109 };
110 
111 //----------------------------------------------------------------------------------------------------------------------
112 
113 // For integers we have two representations. Either int64_t or double.
114 // This is for backward compatibility with the IFS
115 
116 template <template <typename ByteOrder, typename ValueType> class CODEC_T>
118 
119 public: // methods
120 
121  IntegerCodecBuilder() : CodecBuilderBase(CODEC_T<SameByteOrder, double>::codec_name()) {}
123 
124 private: // methods
125 
126  std::unique_ptr<Codec> make(const SameByteOrder&, api::ColumnType type) const override {
127  if ((type == api::INTEGER || type == api::BITFIELD) && !ODBAPISettings::instance().integersAsDoubles()) {
128  return std::unique_ptr<Codec>(new CODEC_T<SameByteOrder, int64_t>(type));
129  } else {
130  return std::unique_ptr<Codec>(new CODEC_T<SameByteOrder, double>(type));
131  }
132  }
133  std::unique_ptr<Codec> make(const OtherByteOrder&, api::ColumnType type) const override {
134  if ((type == api::INTEGER || type == api::BITFIELD) && !ODBAPISettings::instance().integersAsDoubles()) {
135  return std::unique_ptr<Codec>(new CODEC_T<OtherByteOrder, int64_t>(type));
136  } else {
137  return std::unique_ptr<Codec>(new CODEC_T<OtherByteOrder, double>(type));
138  }
139  }
140 };
141 
142 //----------------------------------------------------------------------------------------------------------------------
143 
144 template <typename ByteOrder>
145 std::unique_ptr<Codec> CodecFactory::build(const std::string& name, api::ColumnType type) const {
146  std::lock_guard<std::mutex> lock(m_);
147 
148  auto it = builders_.find(name);
149  if (it == builders_.end()) throw ODBDecodeError(std::string("Codec '") + name + "' not found", Here());
150  return it->second.get().make(ByteOrder(), type);
151 }
152 
153 template <typename ByteOrder>
154 std::unique_ptr<Codec> CodecFactory::load(DataStream<ByteOrder>& ds, api::ColumnType type) const {
155 
156  std::string codecName;
157  ds.read(codecName);
158 
159  auto c = build<ByteOrder>(codecName, type);
160  c->load(ds);
161  return c;
162 }
163 
164 //----------------------------------------------------------------------------------------------------------------------
165 
166 } // namespace core
167 } // namespace odc
168 
169 #endif
static ODBAPISettings & instance()
virtual std::unique_ptr< Codec > make(const OtherByteOrder &, api::ColumnType) const =0
CodecBuilderBase(const std::string &name)
Definition: CodecFactory.cc:47
virtual std::unique_ptr< Codec > make(const SameByteOrder &, api::ColumnType) const =0
std::unique_ptr< Codec > make(const SameByteOrder &, api::ColumnType type) const override
Definition: CodecFactory.h:103
std::unique_ptr< Codec > make(const OtherByteOrder &, api::ColumnType type) const override
Definition: CodecFactory.h:106
void deregister(const std::string &name, CodecBuilderBase &builder)
Definition: CodecFactory.cc:38
std::unique_ptr< Codec > build(const std::string &name, api::ColumnType type) const
Definition: CodecFactory.h:145
std::map< std::string, std::reference_wrapper< CodecBuilderBase > > builders_
Definition: CodecFactory.h:63
static CodecFactory & instance()
Definition: CodecFactory.cc:25
void enregister(const std::string &name, CodecBuilderBase &builder)
Definition: CodecFactory.cc:30
std::unique_ptr< Codec > load(DataStream< ByteOrder > &ds, api::ColumnType type) const
Definition: CodecFactory.h:154
void read(T &elem)
Definition: DataStream.h:205
std::unique_ptr< Codec > make(const SameByteOrder &, api::ColumnType type) const override
Definition: CodecFactory.h:126
std::unique_ptr< Codec > make(const OtherByteOrder &, api::ColumnType type) const override
Definition: CodecFactory.h:133
@ BITFIELD
Definition: ColumnType.h:27
Definition: ColumnInfo.h:23