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 "field_codec_default_message.h"
52 template <
typename WireType,
typename FieldType = WireType>
63 dc.regenerate(this->this_message(), this->root_message());
79 dc.regenerate(this->this_message(), this->root_message());
92 virtual double resolution()
95 return std::pow(10.0, -precision());
103 "missing (dccl.field).min");
105 "missing (dccl.field).max");
108 "(dccl.field).resolution must be greater than 0");
112 "at most one of either (dccl.field).precision or (dccl.field).resolution can be set");
114 validate_numeric_bounds();
117 void validate_numeric_bounds()
121 std::numeric_limits<WireType>::lowest(),
122 "(dccl.field).min must be >= minimum of this field type.");
124 std::numeric_limits<WireType>::max(),
125 "(dccl.field).max must be <= maximum of this field type.");
128 const double min_max_eps = 1e-10;
129 bool min_multiple_of_res = std::abs(quantize(min(), resolution()) - min()) < min_max_eps;
130 bool max_multiple_of_res = std::abs(quantize(max(), resolution()) - max()) < min_max_eps;
136 "(dccl.field).min must be an exact multiple of (dccl.field).resolution");
139 "(dccl.field).max must be an exact multiple of (dccl.field).resolution");
143 auto res = resolution();
145 if (!min_multiple_of_res)
146 dccl::dlog.
is(dccl::logger::WARN, dccl::logger::GENERAL) &&
147 dccl::dlog <<
"Warning: (dccl.field).min should be an exact multiple of "
148 "10^(-(dccl.field).precision), i.e. "
149 << res <<
": " << this->
this_field()->DebugString() << std::endl;
150 if (!max_multiple_of_res)
151 dccl::dlog.
is(dccl::logger::WARN, dccl::logger::GENERAL) &&
152 dccl::dlog <<
"Warning: (dccl.field).max should be an exact multiple of "
153 "10^(-(dccl.field).precision), i.e. "
154 << res <<
": " << this->
this_field()->DebugString() << std::endl;
159 std::numeric_limits<double>::digits,
160 "[(dccl.field).max-(dccl.field).min]/(dccl.field).resolution must "
161 "fit in a double-precision floating point value. Please increase "
162 "min, decrease max, or decrease precision.");
169 dccl::dlog.
is(dccl::logger::DEBUG2, dccl::logger::ENCODE) &&
170 dlog <<
"Encode " << value <<
" with bounds: [" << min() <<
"," << max() <<
"]"
174 double res = resolution();
175 WireType wire_value = dccl::quantize(value, res);
178 if (wire_value < min() || wire_value > max())
183 std::string(
"Value exceeds min/max bounds for field: ") +
192 wire_value -= dccl::quantize(
static_cast<WireType
>(min()), res);
196 wire_value *= (1.0 / res);
197 auto uint_value =
static_cast<dccl::uint64>(dccl::round(wire_value, 0));
210 dccl::dlog.
is(dccl::logger::DEBUG2, dccl::logger::DECODE) &&
211 dlog <<
"Decode with bounds: [" << min() <<
"," << max() <<
"]" << std::endl;
217 dccl::uint64 uint_value = (bits->template to<dccl::uint64>)();
226 auto wire_value = (WireType)uint_value;
227 double res = resolution();
231 wire_value /= (1.0 / res);
236 dccl::quantize(wire_value + dccl::quantize(
static_cast<WireType
>(min()), res), res);
248 return dccl::ceil_log2((max() - min()) / resolution() + 1 + NULL_VALUE);
258 Bitset encode(
const bool& wire_value)
override;
260 bool decode(
Bitset* bits)
override;
261 unsigned size()
override;
262 void validate()
override;
272 Bitset encode(
const std::string& wire_value)
override;
273 std::string decode(
Bitset* bits)
override;
274 unsigned size()
override;
275 unsigned size(
const std::string& wire_value)
override;
276 unsigned max_size()
override;
277 unsigned min_size()
override;
278 void validate()
override;
283 MAX_STRING_LENGTH = 255
292 Bitset encode(
const std::string& wire_value)
override;
293 std::string decode(
Bitset* bits)
override;
294 unsigned size()
override;
295 unsigned size(
const std::string& wire_value)
override;
296 unsigned max_size()
override;
297 unsigned min_size()
override;
298 void validate()
override;
306 int32 pre_encode(
const google::protobuf::EnumValueDescriptor*
const& field_value)
override;
307 const google::protobuf::EnumValueDescriptor*
post_decode(
const int32& wire_value)
override;
310 void validate()
override {}
312 double max()
override
314 const google::protobuf::EnumDescriptor* e =
this_field()->enum_type();
315 return e->value_count() - 1;
317 double min()
override {
return 0; }
320 typedef double time_wire_type;
324 template <
typename TimeType,
int conversion_factor>
328 time_wire_type
pre_encode(
const TimeType& time_of_day)
override
330 time_wire_type max_secs = max();
331 return std::fmod(time_of_day /
static_cast<time_wire_type
>(conversion_factor), max_secs);
334 TimeType post_decode(
const time_wire_type& encoded_time)
override
336 auto max_secs = (
int64)max();
338 gettimeofday(&t,
nullptr);
339 int64 now = t.tv_sec;
340 int64 daystart = now - (now % max_secs);
341 int64 today_time = now - daystart;
344 if ((encoded_time - today_time) > (max_secs / 2))
346 daystart -= max_secs;
348 else if ((today_time - encoded_time) > (max_secs / 2))
350 daystart += max_secs;
353 return dccl::round((TimeType)(conversion_factor * (daystart + encoded_time)),
354 precision() - std::log10((
double)conversion_factor));
358 void validate()
override
360 DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds();
363 double max()
override
368 double min()
override {
return 0; }
369 double precision()
override
376 (double)std::log10((
double)conversion_factor);
383 SECONDS_IN_DAY = 86400
389 static_assert(
sizeof(
TimeCodec) == 0,
"Must use specialization of TimeCodec");
405 Bitset encode(
const T&)
override {
return Bitset(size()); }
409 T decode(
Bitset* )
override
417 unsigned size()
override {
return 0; }
419 void validate()
override
422 "missing (dccl.field).static_value");
425 std::istringstream iss(t);