30 #ifndef DCCLFIELDCODECDEFAULT20110322H
31 #define DCCLFIELDCODECDEFAULT20110322H
35 #include <google/protobuf/descriptor.h>
37 #include "dccl/option_extensions.pb.h"
39 #include "../binary.h"
40 #include "../field_codec.h"
41 #include "../field_codec_fixed.h"
42 #include "../thread_safety.h"
43 #include "field_codec_default_message.h"
53 template <
typename WireType,
typename FieldType = WireType>
64 dc.regenerate(this->this_message(), this->root_message());
80 dc.regenerate(this->this_message(), this->root_message());
93 virtual double resolution()
96 return std::pow(10.0, -precision());
104 "missing (dccl.field).min");
106 "missing (dccl.field).max");
109 "(dccl.field).resolution must be greater than 0");
113 "at most one of either (dccl.field).precision or (dccl.field).resolution can be set");
115 validate_numeric_bounds();
118 void validate_numeric_bounds()
122 std::numeric_limits<WireType>::lowest(),
123 "(dccl.field).min must be >= minimum of this field type.");
125 std::numeric_limits<WireType>::max(),
126 "(dccl.field).max must be <= maximum of this field type.");
129 const double min_max_eps = 1e-10;
130 bool min_multiple_of_res = std::abs(quantize(min(), resolution()) - min()) < min_max_eps;
131 bool max_multiple_of_res = std::abs(quantize(max(), resolution()) - max()) < min_max_eps;
137 "(dccl.field).min must be an exact multiple of (dccl.field).resolution");
140 "(dccl.field).max must be an exact multiple of (dccl.field).resolution");
144 auto res = resolution();
146 if (!min_multiple_of_res)
147 dccl::dlog.
is(dccl::logger::WARN, dccl::logger::GENERAL) &&
148 dccl::dlog <<
"Warning: (dccl.field).min should be an exact multiple of "
149 "10^(-(dccl.field).precision), i.e. "
150 << res <<
": " << this->
this_field()->DebugString() << std::endl;
151 if (!max_multiple_of_res)
152 dccl::dlog.
is(dccl::logger::WARN, dccl::logger::GENERAL) &&
153 dccl::dlog <<
"Warning: (dccl.field).max should be an exact multiple of "
154 "10^(-(dccl.field).precision), i.e. "
155 << res <<
": " << this->
this_field()->DebugString() << std::endl;
160 std::numeric_limits<double>::digits,
161 "[(dccl.field).max-(dccl.field).min]/(dccl.field).resolution must "
162 "fit in a double-precision floating point value. Please increase "
163 "min, decrease max, or decrease precision.");
170 dccl::dlog.
is(dccl::logger::DEBUG2, dccl::logger::ENCODE) &&
171 dlog <<
"Encode " << value <<
" with bounds: [" << min() <<
"," << max() <<
"]"
175 double res = resolution();
176 WireType wire_value = dccl::quantize(value, res);
179 if (wire_value < min() || wire_value > max())
184 std::string(
"Value exceeds min/max bounds for field: ") +
193 wire_value -= dccl::quantize(
static_cast<WireType
>(min()), res);
197 wire_value *= (1.0 / res);
198 auto uint_value =
static_cast<dccl::uint64>(dccl::round(wire_value, 0));
211 dccl::dlog.
is(dccl::logger::DEBUG2, dccl::logger::DECODE) &&
212 dlog <<
"Decode with bounds: [" << min() <<
"," << max() <<
"]" << std::endl;
218 dccl::uint64 uint_value = (bits->template to<dccl::uint64>)();
227 auto wire_value = (WireType)uint_value;
228 double res = resolution();
232 wire_value /= (1.0 / res);
237 dccl::quantize(wire_value + dccl::quantize(
static_cast<WireType
>(min()), res), res);
249 return dccl::ceil_log2((max() - min()) / resolution() + 1 + NULL_VALUE);
262 unsigned size()
override;
263 unsigned size(
const bool& wire_value)
override {
return size(); }
274 Bitset encode(
const std::string& wire_value)
override;
275 std::string decode(
Bitset* bits)
override;
276 unsigned size()
override;
277 unsigned size(
const std::string& wire_value)
override;
278 unsigned max_size()
override;
279 unsigned min_size()
override;
280 void validate()
override;
285 MAX_STRING_LENGTH = 255
296 unsigned size()
override;
297 unsigned size(
const std::string& wire_value)
override;
308 int32 pre_encode(
const google::protobuf::EnumValueDescriptor*
const& field_value)
override;
309 const google::protobuf::EnumValueDescriptor*
post_decode(
const int32& wire_value)
override;
312 void validate()
override {}
313 std::size_t hash()
override
315 return std::hash<std::string>{}(
this_field()->enum_type()->DebugString());
318 double max()
override
320 const google::protobuf::EnumDescriptor* e =
this_field()->enum_type();
321 return e->value_count() - 1;
323 double min()
override {
return 0; }
332 if (!this->has_clock())
333 this->set_clock<std::chrono::system_clock>();
336 template <
typename Clock>
static void set_clock()
338 #if DCCL_THREAD_SUPPORT
339 const std::lock_guard<std::mutex> lock(clock_mutex_);
342 epoch_sec_func_ = []() ->
int64
344 typename Clock::time_point now = Clock::now();
345 std::chrono::seconds sec =
346 std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
350 static bool has_clock()
352 #if DCCL_THREAD_SUPPORT
353 const std::lock_guard<std::mutex> lock(clock_mutex_);
355 return epoch_sec_func_ ? true :
false;
359 static int64 epoch_sec()
361 #if DCCL_THREAD_SUPPORT
362 const std::lock_guard<std::mutex> lock(clock_mutex_);
364 return epoch_sec_func_();
368 #if DCCL_THREAD_SUPPORT
369 static std::mutex clock_mutex_;
371 static std::function<
int64()> epoch_sec_func_;
374 typedef double time_wire_type;
378 template <
typename TimeType,
int conversion_factor>
385 time_wire_type
pre_encode(
const TimeType& time_of_day)
override
387 time_wire_type max_secs = max();
388 return std::fmod(time_of_day /
static_cast<time_wire_type
>(conversion_factor), max_secs);
391 TimeType post_decode(
const time_wire_type& encoded_time)
override
393 auto max_secs =
static_cast<int64>(max());
394 int64_t now_secs = this->epoch_sec();
395 int64 daystart = now_secs - (now_secs % max_secs);
396 int64 today_time = now_secs - daystart;
399 if ((encoded_time - today_time) > (max_secs / 2))
400 daystart -= max_secs;
401 else if ((today_time - encoded_time) > (max_secs / 2))
402 daystart += max_secs;
404 return dccl::round((TimeType)(conversion_factor * (daystart + encoded_time)),
405 precision() - std::log10((
double)conversion_factor));
409 void validate()
override
411 DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds();
414 double max()
override
419 double min()
override {
return 0; }
420 double precision()
override
427 (double)std::log10((
double)conversion_factor);
434 SECONDS_IN_DAY = 86400
440 static_assert(
sizeof(
TimeCodec) == 0,
"Must use specialization of TimeCodec");
456 Bitset encode(
const T&)
override {
return Bitset(size()); }
460 T decode(
Bitset* )
override
468 unsigned size()
override {
return 0; }
470 void validate()
override
473 "missing (dccl.field).static_value");
476 std::istringstream iss(t);