24 #ifndef DCCLFIELDCODECDEFAULT20110322H
25 #define DCCLFIELDCODECDEFAULT20110322H
29 #include <boost/utility.hpp>
30 #include <boost/type_traits.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/numeric/conversion/bounds.hpp>
33 #include <boost/numeric/conversion/cast.hpp>
34 #include <boost/lexical_cast.hpp>
36 #include <google/protobuf/descriptor.h>
38 #include "dccl/option_extensions.pb.h"
40 #include "dccl/codecs2/field_codec_default_message.h"
41 #include "dccl/field_codec_fixed.h"
42 #include "dccl/field_codec.h"
43 #include "dccl/binary.h"
53 template<
typename WireType,
typename FieldType = WireType>
64 virtual double precision()
70 "missing (dccl.field).min");
72 "missing (dccl.field).max");
74 validate_numeric_bounds();
77 void validate_numeric_bounds()
82 "(dccl.field).min must be >= minimum of this field type.");
84 "(dccl.field).max must be <= maximum of this field type.");
88 FieldCodecBase::require((precision() + std::ceil(std::log10(max() - min()))) <= std::numeric_limits<double>::digits10,
89 "[(dccl.field).max-(dccl.field).min]*10^(dccl.field).precision must fit in a double-precision floating point value. Please increase min, decrease max, or decrease precision.");
103 WireType wire_value = dccl::round(value, precision());
106 if(wire_value < min() || wire_value > max())
116 wire_value -= dccl::round((WireType)min(), precision());
118 if (precision() < 0) {
119 wire_value /= (WireType)std::pow(10.0, -precision());
120 }
else if (precision() > 0) {
121 wire_value *= (WireType)std::pow(10.0, precision());
124 dccl::uint64 uint_value = boost::numeric_cast<dccl::uint64>(dccl::round(wire_value, 0));
142 dccl::uint64 uint_value = (bits->template to<dccl::uint64>)();
150 WireType wire_value = (WireType)uint_value;
152 if (precision() < 0) {
153 wire_value *= (WireType)std::pow(10.0, -precision());
154 }
else if (precision() > 0) {
155 wire_value /= (WireType)std::pow(10.0, precision());
160 wire_value = dccl::round(wire_value + dccl::round((WireType)min(), precision()),
174 return dccl::ceil_log2((max()-min())*std::pow(10.0, precision())+1 + NULL_VALUE);
185 Bitset encode(
const bool& wire_value);
187 bool decode(
Bitset* bits);
199 Bitset encode(
const std::string& wire_value);
200 std::string decode(
Bitset* bits);
202 unsigned size(
const std::string& wire_value);
207 enum { MAX_STRING_LENGTH = 255 };
217 Bitset encode(
const std::string& wire_value);
218 std::string decode(
Bitset* bits);
220 unsigned size(
const std::string& wire_value);
231 int32 pre_encode(
const google::protobuf::EnumValueDescriptor*
const& field_value);
232 const google::protobuf::EnumValueDescriptor*
post_decode(
const int32& wire_value);
239 const google::protobuf::EnumDescriptor* e =
this_field()->enum_type();
240 return e->value_count()-1;
247 typedef double time_wire_type;
251 template<
typename TimeType,
int conversion_factor>
256 time_wire_type max_secs = max();
257 return std::fmod(time_of_day /
static_cast<time_wire_type
>(conversion_factor), max_secs);
260 TimeType post_decode(
const time_wire_type& encoded_time) {
265 int64 now = t.tv_sec;
266 int64 daystart = now - (now % max_secs);
267 int64 today_time = now - daystart;
270 if ((encoded_time - today_time) > (max_secs/2)) {
271 daystart -= max_secs;
272 }
else if ((today_time - encoded_time) > (max_secs/2)) {
273 daystart += max_secs;
276 return dccl::round((TimeType)(conversion_factor * (daystart + encoded_time)),
277 precision() - std::log10((
double)conversion_factor));
283 DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds();
290 double min() {
return 0; }
304 enum { SECONDS_IN_DAY = 86400 };
307 template<
typename TimeType>
309 { BOOST_STATIC_ASSERT(
sizeof(
TimeCodec) == 0); };
321 {
return Bitset(size()); }
324 {
return Bitset(size()); }
328 return boost::lexical_cast<T>(
342 boost::lexical_cast<T>(t);
344 catch(boost::bad_lexical_cast&)