27#ifndef DCCLFIELDCODECDEFAULT20110322H
28#define DCCLFIELDCODECDEFAULT20110322H
32#include <google/protobuf/descriptor.h>
34#include "dccl/option_extensions.pb.h"
37#include "../field_codec.h"
38#include "../field_codec_fixed.h"
39#include "../thread_safety.h"
40#include "field_codec_default_message.h"
50template <
typename WireType,
typename FieldType = WireType>
61 dc.regenerate(this->this_message(), this->root_message());
77 dc.regenerate(this->this_message(), this->root_message());
90 virtual double resolution()
93 return std::pow(10.0, -precision());
101 "missing (dccl.field).min");
103 "missing (dccl.field).max");
106 "(dccl.field).resolution must be greater than 0");
110 "at most one of either (dccl.field).precision or (dccl.field).resolution can be set");
112 validate_numeric_bounds();
115 void validate_numeric_bounds()
119 std::numeric_limits<WireType>::lowest(),
120 "(dccl.field).min must be >= minimum of this field type.");
122 std::numeric_limits<WireType>::max(),
123 "(dccl.field).max must be <= maximum of this field type.");
126 const double min_max_eps = 1e-10;
127 bool min_multiple_of_res = std::abs(
quantize(min(), resolution()) - min()) < min_max_eps;
128 bool max_multiple_of_res = std::abs(
quantize(max(), resolution()) - max()) < min_max_eps;
134 "(dccl.field).min must be an exact multiple of (dccl.field).resolution");
137 "(dccl.field).max must be an exact multiple of (dccl.field).resolution");
141 auto res = resolution();
143 if (!min_multiple_of_res)
144 dccl::dlog.
is(dccl::logger::WARN, dccl::logger::GENERAL) &&
145 dccl::dlog <<
"Warning: (dccl.field).min should be an exact multiple of "
146 "10^(-(dccl.field).precision), i.e. "
147 << res <<
": " << this->
this_field()->DebugString() << std::endl;
148 if (!max_multiple_of_res)
149 dccl::dlog.
is(dccl::logger::WARN, dccl::logger::GENERAL) &&
150 dccl::dlog <<
"Warning: (dccl.field).max should be an exact multiple of "
151 "10^(-(dccl.field).precision), i.e. "
152 << res <<
": " << this->
this_field()->DebugString() << std::endl;
157 std::numeric_limits<double>::digits,
158 "[(dccl.field).max-(dccl.field).min]/(dccl.field).resolution must "
159 "fit in a double-precision floating point value. Please increase "
160 "min, decrease max, or decrease precision.");
167 dccl::dlog.
is(dccl::logger::DEBUG2, dccl::logger::ENCODE) &&
168 dlog <<
"Encode " << value <<
" with bounds: [" << min() <<
"," << max() <<
"]"
172 double res = resolution();
176 if (wire_value < min() || wire_value > max())
181 std::string(
"Value exceeds min/max bounds for field: ") +
194 wire_value *= (1.0 / res);
195 auto uint_value =
static_cast<dccl::uint64>(dccl::round(wire_value, 0));
208 dccl::dlog.
is(dccl::logger::DEBUG2, dccl::logger::DECODE) &&
209 dlog <<
"Decode with bounds: [" << min() <<
"," << max() <<
"]" << std::endl;
215 dccl::uint64 uint_value = (bits->template to<dccl::uint64>)();
224 auto wire_value = (WireType)uint_value;
225 double res = resolution();
229 wire_value /= (1.0 / res);
246 return dccl::ceil_log2((max() - min()) / resolution() + 1 + NULL_VALUE);
259 unsigned size()
override;
260 unsigned size(
const bool& wire_value)
override {
return size(); }
271 Bitset encode(
const std::string& wire_value)
override;
272 std::string decode(
Bitset* bits)
override;
273 unsigned size()
override;
274 unsigned size(
const std::string& wire_value)
override;
275 unsigned max_size()
override;
276 unsigned min_size()
override;
277 void validate()
override;
282 MAX_STRING_LENGTH = 255
293 unsigned size()
override;
294 unsigned size(
const std::string& wire_value)
override;
305 int32 pre_encode(
const google::protobuf::EnumValueDescriptor*
const& field_value)
override;
306 const google::protobuf::EnumValueDescriptor* post_decode(
const int32& wire_value)
override;
309 void validate()
override {}
310 std::size_t hash()
override
312 return std::hash<std::string>{}(
this_field()->enum_type()->DebugString());
315 double max()
override
317 const google::protobuf::EnumDescriptor* e =
this_field()->enum_type();
318 return e->value_count() - 1;
320 double min()
override {
return 0; }
329 if (!this->has_clock())
330 this->set_clock<std::chrono::system_clock>();
333 template <
typename Clock>
static void set_clock()
335#if DCCL_THREAD_SUPPORT
336 const std::lock_guard<std::mutex> lock(clock_mutex_);
339 epoch_sec_func_ = []() ->
int64
341 typename Clock::time_point now = Clock::now();
342 std::chrono::seconds sec =
343 std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
347 static bool has_clock()
349#if DCCL_THREAD_SUPPORT
350 const std::lock_guard<std::mutex> lock(clock_mutex_);
352 return epoch_sec_func_ ? true :
false;
356 static int64 epoch_sec()
358#if DCCL_THREAD_SUPPORT
359 const std::lock_guard<std::mutex> lock(clock_mutex_);
361 return epoch_sec_func_();
365#if DCCL_THREAD_SUPPORT
366 static std::mutex clock_mutex_;
368 static std::function<
int64()> epoch_sec_func_;
371typedef double time_wire_type;
375template <
typename TimeType,
int conversion_factor>
382 time_wire_type pre_encode(
const TimeType& time_of_day)
override
384 time_wire_type max_secs = max();
385 return std::fmod(time_of_day /
static_cast<time_wire_type
>(conversion_factor), max_secs);
388 TimeType post_decode(
const time_wire_type& encoded_time)
override
390 auto max_secs =
static_cast<int64>(max());
391 int64_t now_secs = this->epoch_sec();
392 int64 daystart = now_secs - (now_secs % max_secs);
393 int64 today_time = now_secs - daystart;
396 if ((encoded_time - today_time) > (max_secs / 2))
397 daystart -= max_secs;
398 else if ((today_time - encoded_time) > (max_secs / 2))
399 daystart += max_secs;
401 return dccl::round((TimeType)(conversion_factor * (daystart + encoded_time)),
402 precision() - std::log10((
double)conversion_factor));
406 void validate()
override
411 double max()
override
416 double min()
override {
return 0; }
417 double precision()
override
424 (double)std::log10((
double)conversion_factor);
431 SECONDS_IN_DAY = 86400
437 static_assert(
sizeof(
TimeCodec) == 0,
"Must use specialization of TimeCodec");
453 Bitset encode(
const T&)
override {
return Bitset(size()); }
457 T decode(
Bitset* )
override
465 unsigned size()
override {
return 0; }
467 void validate()
override
470 "missing (dccl.field).static_value");
473 std::istringstream iss(t);
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
void from(IntType value, size_type num_bits=std::numeric_limits< IntType >::digits)
Sets value of the Bitset to the contents of an integer.
const google::protobuf::Descriptor * this_descriptor() const
Returns the Descriptor (message schema meta-data) for the immediate parent Message.
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
void require(bool b, const std::string &description)
Essentially an assertion to be used in the validate() virtual method.
dccl::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
bool use_required()
Whether to use the required or optional encoding.
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Exception used to signal null (non-existent) value within field codecs during decode.
Base class for static-typed (no dccl::any) field encoders/decoders. Most single-valued user defined v...
Base class for static-typed field encoders/decoders that use a fixed number of bits on the wire regar...
Provides a bool encoder. Uses 1 bit if field is required, 2 bits if optional
unsigned size() override
The size of the encoded message in bits. Use TypedFieldCodec if the size depends on the data.
Bitset encode() override
Encode an empty field.
bool decode(Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
Provides an fixed length byte string encoder.
unsigned min_size() override
Calculate minimum size of the field in bits.
Bitset encode() override
Encode an empty field.
unsigned size() override
Calculate the size (in bits) of an empty field.
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
unsigned max_size() override
Calculate maximum size of the field in bits.
std::string decode(Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
Provides an enum encoder. This converts the enumeration to an integer (based on the enumeration index...
Provides a basic bounded arbitrary length numeric (double, float, uint32, uint64, int32,...
Bitset encode() override
Encode an empty field.
WireType decode(Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
unsigned size() override
The size of the encoded message in bits. Use TypedFieldCodec if the size depends on the data.
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
Bitset encode(const WireType &value) override
Encode a non-empty field.
Provides an variable length ASCII string encoder. Can encode strings up to 255 bytes by using a lengt...
Placeholder codec that takes no space on the wire (0 bits).
Encodes time of day (default: second precision, but can be set with (dccl.field).precision extension)
Dynamic Compact Control Language namespace.
google::protobuf::uint64 uint64
an unsigned 64 bit integer
google::protobuf::int32 int32
a signed 32 bit integer
google::protobuf::int64 int64
a signed 64 bit integer
std::enable_if< std::is_floating_point< Float >::value, Float >::type quantize(Float value, double interval)
unsigned ceil_log2(dccl::uint64 v)