IODA Bundle
Integer.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 #ifndef odc_core_codec_Integer_H
12 #define odc_core_codec_Integer_H
13 
14 #include "odc/core/Codec.h"
15 
16 /// @note We have some strange behaviour in here. In particular, we support BOTH decoding
17 /// and encoding integers from a representation as doubles, and also as integers.
18 /// This is a little bit strange, and reflects the history of these being used in the IFS
19 /// and ODB1 where everything was a double.
20 ///
21 /// n.b. The decoded size is int64_t, even though the codec only goes up to int32, as we
22 /// want to support bigger numbers in the future.
23 
24 namespace odc {
25 namespace codec {
26 
27 //----------------------------------------------------------------------------------------------------------------------
28 
29 template<typename ByteOrder, typename ValueType>
30 class BaseCodecInteger : public core::DataStreamCodec<ByteOrder> {
31 
32 public: // definitions
33 
34  using value_type = ValueType;
35 
36 public: // methods
37 
38  BaseCodecInteger(api::ColumnType type, const std::string& name, double minmaxmissing=odc::MDI::integerMDI()) :
39  core::DataStreamCodec<ByteOrder>(name, type) {
40 
41  this->min_ = minmaxmissing;
42  this->max_ = minmaxmissing;
43  this->missingValue_ = minmaxmissing;
44  }
45 
46  ~BaseCodecInteger() override {}
47 
48 private: // methods
49 
50  void gatherStats(const double& v) override {
51  static_assert(sizeof(ValueType) == sizeof(v), "unsafe casting check");
52  const ValueType& val(reinterpret_cast<const ValueType&>(v));
54  }
55 };
56 
57 
58 //----------------------------------------------------------------------------------------------------------------------
59 
60 template <typename ByteOrder,
61  typename ValueType,
62  typename InternalValueType,
63  class DerivedCodec> // codec_nam passed through CRTP as char* is odd to deal with in template
64 class CodecIntegerOffset : public BaseCodecInteger<ByteOrder, ValueType> {
65 
66 public: // methods
67 
68  CodecIntegerOffset(api::ColumnType type) : BaseCodecInteger<ByteOrder, ValueType>(type, DerivedCodec::codec_name()) {}
69  ~CodecIntegerOffset() override {}
70 
71 private: // methods
72 
73  unsigned char* encode(unsigned char* p, const double& d) override {
74  static_assert(sizeof(ValueType) == sizeof(d), "unsafe casting check");
75 
76  const ValueType& val(reinterpret_cast<const ValueType&>(d));
77  InternalValueType s = val - this->min_;
78  ByteOrder::swap(s);
79  ::memcpy(p, &s, sizeof(s));
80  return p + sizeof(s);
81  }
82 
83  void decode(double* out) override {
84  static_assert(sizeof(ValueType) == sizeof(out), "unsafe casting check");
85 
86  ValueType* val_out = reinterpret_cast<ValueType*>(out);
87  InternalValueType s;
88  this->ds().read(s);
89  (*val_out) = s + this->min_;
90  }
91 
92  void skip() override {
93  this->ds().advance(sizeof(InternalValueType));
94  }
95 };
96 
97 
98 //----------------------------------------------------------------------------------------------------------------------
99 
100 template <typename ByteOrder,
101  typename ValueType,
102  typename InternalValueType,
103  class DerivedCodec> // codec_nam passed through CRTP as char* is odd to deal with in template
104 class CodecIntegerDirect : public BaseCodecInteger<ByteOrder, ValueType> {
105 
106 public: // methods
107 
108  CodecIntegerDirect(api::ColumnType type) : BaseCodecInteger<ByteOrder, ValueType>(type, DerivedCodec::codec_name()) {}
109  ~CodecIntegerDirect() override {}
110 
111 private: // methods
112 
113  unsigned char* encode(unsigned char* p, const double& d) override {
114  static_assert(sizeof(ValueType) == sizeof(d), "unsafe casting check");
115 
116  const ValueType& val(reinterpret_cast<const ValueType&>(d));
117  InternalValueType s = val;
118  ByteOrder::swap(s);
119  ::memcpy(p, &s, sizeof(s));
120  return p + sizeof(s);
121  }
122 
123  void decode(double* out) override {
124  static_assert(sizeof(ValueType) == sizeof(out), "unsafe casting check");
125 
126  ValueType* val_out = reinterpret_cast<ValueType*>(out);
127  InternalValueType s;
128  this->ds().read(s);
129  (*val_out) = s;
130  }
131 
132  void skip() override {
133  this->ds().advance(sizeof(InternalValueType));
134  }
135 };
136 
137 //----------------------------------------------------------------------------------------------------------------------
138 
139 template<typename ByteOrder, typename ValueType>
140 struct CodecInt8 : public CodecIntegerOffset<ByteOrder, ValueType, uint8_t, CodecInt8<ByteOrder, ValueType>> {
141  constexpr static const char* codec_name() { return "int8"; }
143 };
144 
145 //----------------------------------------------------------------------------------------------------------------------
146 
147 template<typename ByteOrder, typename ValueType>
148 struct CodecInt16 : public CodecIntegerOffset<ByteOrder, ValueType, uint16_t, CodecInt16<ByteOrder, ValueType>> {
149  constexpr static const char* codec_name() { return "int16"; }
151 };
152 
153 //----------------------------------------------------------------------------------------------------------------------
154 
155 template<typename ByteOrder, typename ValueType>
156 struct CodecInt32 : public CodecIntegerDirect<ByteOrder, ValueType, int32_t, CodecInt32<ByteOrder, ValueType>> {
157  constexpr static const char* codec_name() { return "int32"; }
159 };
160 
161 //----------------------------------------------------------------------------------------------------------------------
162 
163 } // namespace codec
164 } // namespace odc
165 
166 #endif
167 
static double integerMDI()
Definition: MDI.h:22
void gatherStats(const double &v) override
Definition: Integer.h:50
~BaseCodecInteger() override
Definition: Integer.h:46
BaseCodecInteger(api::ColumnType type, const std::string &name, double minmaxmissing=odc::MDI::integerMDI())
Definition: Integer.h:38
void decode(double *out) override
Definition: Integer.h:123
CodecIntegerDirect(api::ColumnType type)
Definition: Integer.h:108
unsigned char * encode(unsigned char *p, const double &d) override
Definition: Integer.h:113
CodecIntegerOffset(api::ColumnType type)
Definition: Integer.h:68
unsigned char * encode(unsigned char *p, const double &d) override
Definition: Integer.h:73
~CodecIntegerOffset() override
Definition: Integer.h:69
void decode(double *out) override
Definition: Integer.h:83
void skip() override
Definition: Integer.h:92
const std::string & name() const
Definition: Codec.h:40
double missingValue_
Definition: Codec.h:99
double max_
Definition: Codec.h:101
virtual void gatherStats(const double &v)
Definition: Codec.cc:98
double min_
Definition: Codec.h:100
DataStreamCodec(const std::string &name, api::ColumnType type)
Definition: Codec.h:125
DataStream< ByteOrder > & ds()
Definition: Codec.h:157
Definition: ColumnInfo.h:23
constexpr static const char * codec_name()
Definition: Integer.h:149
constexpr static const char * codec_name()
Definition: Integer.h:157
constexpr static const char * codec_name()
Definition: Integer.h:141