Merge lp:~tes/dccl/3.0-codec-groups into lp:~dccl-dev/dccl/3.0

Proposed by toby schneider
Status: Merged
Approved by: toby schneider
Approved revision: 321
Merged at revision: 297
Proposed branch: lp:~tes/dccl/3.0-codec-groups
Merge into: lp:~dccl-dev/dccl/3.0
Diff against target: 5407 lines (+2997/-930)
60 files modified
CMakeLists.txt (+2/-4)
src/CMakeLists.txt (+12/-2)
src/apps/dccl/dccl_tool.cpp (+208/-103)
src/arithmetic/field_codec_arithmetic.cpp (+25/-2)
src/binary.h (+23/-0)
src/ccl/CMakeLists.txt (+0/-1)
src/ccl/ccl_compatibility.cpp (+44/-17)
src/ccl/ccl_compatibility.h (+3/-4)
src/codec.cpp (+68/-30)
src/codec.h (+28/-10)
src/codecs2/field_codec_default.cpp (+25/-105)
src/codecs2/field_codec_default.h (+299/-319)
src/codecs2/field_codec_default_message.cpp (+15/-15)
src/codecs2/field_codec_default_message.h (+159/-201)
src/codecs3/field_codec_default.cpp (+122/-0)
src/codecs3/field_codec_default.h (+77/-0)
src/codecs3/field_codec_default_message.cpp (+236/-0)
src/codecs3/field_codec_default_message.h (+213/-0)
src/field_codec.cpp (+82/-18)
src/field_codec.h (+47/-5)
src/field_codec_id.cpp (+100/-0)
src/field_codec_id.h (+50/-0)
src/field_codec_manager.h (+169/-28)
src/field_codec_message_stack.cpp (+38/-4)
src/field_codec_message_stack.h (+7/-16)
src/field_codec_typed.h (+12/-3)
src/logger.cpp (+6/-4)
src/logger.h (+2/-1)
src/protobuf/option_extensions.proto (+8/-5)
src/test/CMakeLists.txt (+5/-0)
src/test/dccl_all_fields/test.cpp (+3/-1)
src/test/dccl_all_fields/test.proto (+2/-2)
src/test/dccl_arithmetic/test.proto (+7/-1)
src/test/dccl_ccl/test.cpp (+2/-4)
src/test/dccl_ccl/test.proto (+1/-0)
src/test/dccl_codec_group/CMakeLists.txt (+6/-0)
src/test/dccl_codec_group/test.cpp (+104/-0)
src/test/dccl_codec_group/test.proto (+77/-0)
src/test/dccl_custom_id/test.proto (+3/-0)
src/test/dccl_custom_message/test.proto (+2/-0)
src/test/dccl_default_id/test.proto (+8/-1)
src/test/dccl_header/header.proto (+9/-18)
src/test/dccl_header/test.cpp (+1/-1)
src/test/dccl_header/test.proto (+2/-1)
src/test/dccl_message_fix/CMakeLists.txt (+6/-0)
src/test/dccl_message_fix/test.cpp (+110/-0)
src/test/dccl_message_fix/test.proto (+31/-0)
src/test/dccl_numeric_bounds/test.proto (+3/-0)
src/test/dccl_repeated/test.cpp (+0/-1)
src/test/dccl_repeated/test.proto (+3/-0)
src/test/dccl_required_optional/test.proto (+1/-0)
src/test/dccl_static_methods/test.proto (+3/-0)
src/test/dccl_v2_all_fields/CMakeLists.txt (+6/-0)
src/test/dccl_v2_all_fields/test.cpp (+175/-0)
src/test/dccl_v2_all_fields/test.proto (+159/-0)
src/test/dccl_v2_header/CMakeLists.txt (+6/-0)
src/test/dccl_v2_header/header.proto (+54/-0)
src/test/dccl_v2_header/test.cpp (+92/-0)
src/test/dccl_v2_header/test.proto (+16/-0)
src/type_helper.h (+20/-3)
To merge this branch: bzr merge lp:~tes/dccl/3.0-codec-groups
Reviewer Review Type Date Requested Status
Chris Murphy (community) Approve
Review via email: mp+216939@code.launchpad.net

Description of the change

Two blueprints implemented:

1. http://gobysoft.org/wiki/DcclCodecGroups
These changes allow a user to change the codec name that is used for every field in an entire message with a single DCCLMessageOption. In addition, it defines an integer for the codec_version = N that resolves to a codec_group of "dccl.defaultN". This allows us to write new codecs for version 3 that fix bugs, improve functionality from version 2 while preserving backwards compatibility (since codec_version defaults to 2, the first version of Goby/DCCL that used Google Protobuf).

2. http://gobysoft.org/wiki/DcclImproveDefaultCodecs
These changes build on the codec_version defined in 1. to fix bugs and improve the efficiency of the DefaultMessageCodec and all the "repeated" field codecs that rely on the FieldCodecBase implementation (i.e. repeated calls of the singular encode/decode).

The links above go into more detail regarding the changes.

To post a comment you must log in.
lp:~tes/dccl/3.0-codec-groups updated
315. By toby schneider

Added exports for additional dccl libraries (ccl and arithmetic)

316. By toby schneider

Fixed export install location

317. By toby schneider

Added logging of size of each field to dlog

318. By toby schneider

1. Add vector size for repeated fields when reporting size during encode, 2. Restore setfill after timestamp formatting for logger

319. By toby schneider

Added b64_encode and b64_decode helper functions that are similar to their hex_* equivalents; Added 'loaded()' method to Codec to allow a user to see all the loaded DCCL messages

320. By toby schneider

Changed default string codec in v3 to use a length prefix that is sized based on max_length (not fixed to 8 bits)

321. By toby schneider

Added warning for users who don't specify (dccl.msg).codec_version to encourage use of the DCCL3 defaults: option (dccl.msg).codec_version=3

Revision history for this message
Chris Murphy (chrismurf-bluefin) wrote :

  Per our discussion yesterday, this seems like a reasonable approach. We discussed a few ideas that may or may not make it into the final:

1. Add a deprecation warning for people who are implicitly relying on DCCL2 behavior.
2. Allow codec groups to fall back on the standard codecs by default, so a Bluefin codec library could consist of the standard DCCL3 Codecs... "plus X".
3. Change codec group to codec library (I don't care)
4. More documentation

None of these are major or blockers.

review: Approve
Revision history for this message
toby schneider (tes) wrote :

The deprecation warning (1.) is included in this merge.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-01-06 17:25:02 +0000
+++ CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -72,7 +72,7 @@
72install(DIRECTORY ${dccl_INC_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include72install(DIRECTORY ${dccl_INC_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include
73 FILES_MATCHING PATTERN "*.h" PATTERN "*.proto" PATTERN "test*" EXCLUDE)73 FILES_MATCHING PATTERN "*.h" PATTERN "*.proto" PATTERN "test*" EXCLUDE)
7474
75install(EXPORT dccl-config DESTINATION share/${PROJECTNAME}/cmake)75install(EXPORT dccl-config DESTINATION share/dccl/cmake)
7676
77## let cmake know where the headers are77## let cmake know where the headers are
78include_directories(${dccl_INC_DIR})78include_directories(${dccl_INC_DIR})
@@ -132,10 +132,8 @@
132 include_directories(${Cryptopp_INCLUDE_DIRS})132 include_directories(${Cryptopp_INCLUDE_DIRS})
133endif()133endif()
134134
135
135## start adding subdirectories136## start adding subdirectories
136add_subdirectory(src)137add_subdirectory(src)
137138
138## export a file for folks to use
139export(TARGETS dccl FILE ${CMAKE_BINARY_DIR}/dccl-config.cmake)
140file(APPEND ${CMAKE_BINARY_DIR}/dccl-config.cmake "set(DCCL_INCLUDE_DIR \"${dccl_INC_DIR}\")")
141139
142140
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2014-01-08 22:30:52 +0000
+++ src/CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -10,9 +10,12 @@
10 codec.cpp10 codec.cpp
11 field_codec.cpp11 field_codec.cpp
12 field_codec_message_stack.cpp12 field_codec_message_stack.cpp
13 field_codec_default.cpp
14 field_codec_default_message.cpp
15 field_codec_manager.cpp13 field_codec_manager.cpp
14 field_codec_id.cpp
15 codecs2/field_codec_default.cpp
16 codecs2/field_codec_default_message.cpp
17 codecs3/field_codec_default_message.cpp
18 codecs3/field_codec_default.cpp
16 type_helper.cpp19 type_helper.cpp
17 bitset.cpp20 bitset.cpp
18 dynamic_protobuf_manager.cpp21 dynamic_protobuf_manager.cpp
@@ -32,14 +35,21 @@
32option(build_arithmetic "Build arithmetic coders shared library" ON)35option(build_arithmetic "Build arithmetic coders shared library" ON)
33option(build_ccl "Build Compact Control Language (CCL) legacy support shared library" ON)36option(build_ccl "Build Compact Control Language (CCL) legacy support shared library" ON)
3437
38set(DCCL_EXPORT_TARGETS dccl)
39
35if(build_ccl)40if(build_ccl)
36 add_subdirectory(ccl)41 add_subdirectory(ccl)
42 set(DCCL_EXPORT_TARGETS ${DCCL_EXPORT_TARGETS} dccl_ccl_compat)
37endif()43endif()
3844
39if(build_arithmetic)45if(build_arithmetic)
40 add_subdirectory(arithmetic)46 add_subdirectory(arithmetic)
47 set(DCCL_EXPORT_TARGETS ${DCCL_EXPORT_TARGETS} dccl_arithmetic)
41endif()48endif()
4249
50export(TARGETS ${DCCL_EXPORT_TARGETS} FILE ${CMAKE_BINARY_DIR}/dccl-config.cmake)
51file(APPEND ${CMAKE_BINARY_DIR}/dccl-config.cmake "set(DCCL_INCLUDE_DIR \"${dccl_INC_DIR}\")")
52
43if(enable_testing)53if(enable_testing)
44 add_subdirectory(test)54 add_subdirectory(test)
45endif()55endif()
4656
=== modified file 'src/apps/dccl/dccl_tool.cpp'
--- src/apps/dccl/dccl_tool.cpp 2014-04-22 20:08:20 +0000
+++ src/apps/dccl/dccl_tool.cpp 2014-08-27 16:27:22 +0000
@@ -26,6 +26,8 @@
2626
2727
28#include <sstream>28#include <sstream>
29#include <fstream>
30
2931
30#include <google/protobuf/descriptor.h>32#include <google/protobuf/descriptor.h>
31#include <google/protobuf/text_format.h>33#include <google/protobuf/text_format.h>
@@ -40,13 +42,16 @@
40#include "dccl_tool.pb.h"42#include "dccl_tool.pb.h"
4143
42enum Action { NO_ACTION, ENCODE, DECODE, ANALYZE, DISP_PROTO };44enum Action { NO_ACTION, ENCODE, DECODE, ANALYZE, DISP_PROTO };
43enum Format { TEXTFORMAT, HEX, BASE64 };45enum Format { BINARY, TEXTFORMAT, HEX, BASE64 };
4446
45struct Config47struct Config
46{48{
47 Config()49 Config()
48 : action(NO_ACTION),50 : action(NO_ACTION),
49 format(HEX)51 format(BINARY),
52 id_codec(dccl::Codec::default_id_codec_name()),
53 verbose(false),
54 omit_prefix(false)
50 { }55 { }
51 56
52 Action action;57 Action action;
@@ -55,11 +60,14 @@
55 std::set<std::string> message;60 std::set<std::string> message;
56 std::set<std::string> proto_file;61 std::set<std::string> proto_file;
57 Format format;62 Format format;
63 std::string id_codec;
64 bool verbose;
65 bool omit_prefix;
58};66};
5967
60 68
61void analyze(dccl::Codec& dccl, const Config& cfg);69void analyze(dccl::Codec& dccl, const Config& cfg);
62void encode(dccl::Codec& dccl, const Config& cfg);70void encode(dccl::Codec& dccl, Config& cfg);
63void decode(dccl::Codec& dccl, const Config& cfg);71void decode(dccl::Codec& dccl, const Config& cfg);
64void disp_proto(dccl::Codec& dccl, const Config& cfg);72void disp_proto(dccl::Codec& dccl, const Config& cfg);
6573
@@ -67,67 +75,95 @@
67void load_desc(dccl::Codec* dccl, const google::protobuf::Descriptor* desc, const std::string& name);75void load_desc(dccl::Codec* dccl, const google::protobuf::Descriptor* desc, const std::string& name);
68void parse_options(int argc, char* argv[], Config* cfg);76void parse_options(int argc, char* argv[], Config* cfg);
6977
78
70int main(int argc, char* argv[])79int main(int argc, char* argv[])
71{80{
72 Config cfg;81 std::vector<void *> dl_handles;
73 parse_options(argc, argv, &cfg);82 {
7483 Config cfg;
75 dccl::dlog.connect(dccl::logger::WARN_PLUS, &std::cerr);84 parse_options(argc, argv, &cfg);
7685
77 dccl::DynamicProtobufManager::enable_compilation();86 if(!cfg.verbose)
78 87 dccl::dlog.connect(dccl::logger::WARN_PLUS, &std::cerr);
79 for(std::set<std::string>::const_iterator it = cfg.include.begin(),88 else
80 end = cfg.include.end(); it != end; ++it)89 dccl::dlog.connect(dccl::logger::DEBUG1_PLUS, &std::cerr);
81 dccl::DynamicProtobufManager::add_include_path(*it);90
8291 dccl::DynamicProtobufManager::enable_compilation();
83 dccl::Codec dccl;92
84 for(std::set<std::string>::const_iterator it = cfg.dlopen.begin(),93 for(std::set<std::string>::const_iterator it = cfg.include.begin(),
85 end = cfg.dlopen.end(); it != end; ++it)94 end = cfg.include.end(); it != end; ++it)
86 dccl.load_library(*it);95 dccl::DynamicProtobufManager::add_include_path(*it);
87 96
88 for(std::set<std::string>::const_iterator it = cfg.proto_file.begin(),97 for(std::set<std::string>::const_iterator it = cfg.dlopen.begin(),
89 end = cfg.proto_file.end(); it != end; ++it)98 end = cfg.dlopen.end(); it != end; ++it)
90 {99 {
91 const google::protobuf::FileDescriptor* file_desc =100 void* handle = dlopen(it->c_str(), RTLD_LAZY);
92 dccl::DynamicProtobufManager::load_from_proto_file(*it);101 if(handle)
93102 {
94 if(!file_desc)103 dl_handles.push_back(handle);
95 {104 }
96 std::cerr << "failed to read in: " << *it << std::endl;105 else
97 exit(EXIT_FAILURE);106 {
98 }107 std::cerr << "Failed to open shared library: " << *it << std::endl;
99 108 exit(EXIT_FAILURE);
100 // if no messages explicity specified, load them all.109 }
101 if(cfg.message.empty())110
102 {111 }
103 for(int i = 0, n = file_desc->message_type_count(); i < n; ++i)112
104 {113 dccl::Codec dccl(cfg.id_codec);
105 const google::protobuf::Descriptor* desc = file_desc->message_type(i);114 for(std::vector<void *>::iterator it = dl_handles.begin(),
106 cfg.message.insert(file_desc->message_type(i)->full_name());115 n = dl_handles.end(); it != n; ++it)
107 }116 dccl.load_library(*it);
108 }117
109 }118 bool no_messages_specified = cfg.message.empty();
110119 for(std::set<std::string>::const_iterator it = cfg.proto_file.begin(),
111 // Load up all the messages120 end = cfg.proto_file.end(); it != end; ++it)
112 for(std::set<std::string>::const_iterator it = cfg.message.begin(),121 {
113 end = cfg.message.end(); it != end; ++it) 122 const google::protobuf::FileDescriptor* file_desc =
114 {123 dccl::DynamicProtobufManager::load_from_proto_file(*it);
115 const google::protobuf::Descriptor* desc = 124
116 dccl::DynamicProtobufManager::find_descriptor(*it);125 if(!file_desc)
117 load_desc(&dccl, desc, *it);126 {
118 }127 std::cerr << "failed to read in: " << *it << std::endl;
119128 exit(EXIT_FAILURE);
120 switch(cfg.action)129 }
121 {130
122 case ENCODE: encode(dccl, cfg); break;131 // if no messages explicitly specified, load them all.
123 case DECODE: decode(dccl, cfg); break;132 if(no_messages_specified && cfg.action != ENCODE)
124 case ANALYZE: analyze(dccl, cfg); break;133 {
125 case DISP_PROTO: disp_proto(dccl, cfg); break;134 for(int i = 0, n = file_desc->message_type_count(); i < n; ++i)
126 default:135 {
127 std::cerr << "No action specified (e.g. analyze, decode, encode). Try --help." << std::endl;136 cfg.message.insert(file_desc->message_type(i)->full_name());
128 exit(EXIT_SUCCESS);137 }
129 138 }
130 }139 }
140
141 // Load up all the messages
142 for(std::set<std::string>::const_iterator it = cfg.message.begin(),
143 end = cfg.message.end(); it != end; ++it)
144 {
145 const google::protobuf::Descriptor* desc =
146 dccl::DynamicProtobufManager::find_descriptor(*it);
147 load_desc(&dccl, desc, *it);
148 }
149
150 switch(cfg.action)
151 {
152 case ENCODE: encode(dccl, cfg); break;
153 case DECODE: decode(dccl, cfg); break;
154 case ANALYZE: analyze(dccl, cfg); break;
155 case DISP_PROTO: disp_proto(dccl, cfg); break;
156 default:
157 std::cerr << "No action specified (e.g. analyze, decode, encode). Try --help." << std::endl;
158 exit(EXIT_SUCCESS);
159
160 }
161 }
162
163 for(std::vector<void *>::iterator it = dl_handles.begin(),
164 n = dl_handles.end(); it != n; ++it)
165 dlclose(*it);
166
131}167}
132168
133169
@@ -137,16 +173,14 @@
137 dccl.info_all(&std::cout);173 dccl.info_all(&std::cout);
138}174}
139175
140void encode(dccl::Codec& dccl, const Config& cfg)176void encode(dccl::Codec& dccl, Config& cfg)
141{177{
142 if(cfg.message.size() != 1)178 if(cfg.message.size() > 1)
143 {179 {
144 std::cerr << "Exactly one DCCL message must be specified with -m or --message" << std::endl;180 std::cerr << "No more than one DCCL message can be specified with -m or --message for encoding." << std::endl;
145 exit(EXIT_FAILURE);181 exit(EXIT_FAILURE);
146 }182 }
147 const google::protobuf::Descriptor* desc = 183 std::string command_line_name = *cfg.message.begin();
148 dccl::DynamicProtobufManager::find_descriptor(*cfg.message.begin());
149 int dccl_id = dccl.id(desc);
150 184
151 while(!std::cin.eof())185 while(!std::cin.eof())
152 {186 {
@@ -156,6 +190,50 @@
156 boost::trim(input);190 boost::trim(input);
157 if(input.empty())191 if(input.empty())
158 continue;192 continue;
193
194 std::string name;
195 if(input[0] == '|')
196 {
197 std::string::size_type close_bracket_pos = input.find('|', 1);
198 if(close_bracket_pos == std::string::npos)
199 {
200 std::cerr << "Incorrectly formatted input: expected '|'" << std::endl;
201 exit(EXIT_FAILURE);
202 }
203
204 name = input.substr(1, close_bracket_pos-1);
205 if(cfg.message.find(name) == cfg.message.end())
206 {
207 const google::protobuf::Descriptor* desc =
208 dccl::DynamicProtobufManager::find_descriptor(name);
209 load_desc(&dccl, desc, name);
210 cfg.message.insert(name);
211 }
212
213
214 if(input.size() > close_bracket_pos+1)
215 input = input.substr(close_bracket_pos+1);
216 else
217 input.clear();
218 }
219 else
220 {
221 if(cfg.message.size() == 0)
222 {
223 std::cerr << "Message name not given with -m or in the input (i.e. '[Name] field1: value field2: value')." << std::endl;
224 exit(EXIT_FAILURE);
225 }
226
227 name = command_line_name;
228 }
229
230 const google::protobuf::Descriptor* desc = dccl::DynamicProtobufManager::find_descriptor(name);
231 if(desc == 0)
232 {
233 std::cerr << "No descriptor with name " << name << " found! Make sure you have loaded all the necessary .proto files and/or shared libraries. Also make sure you specified the fully qualified name including the package, if any (e.g. 'goby.acomms.protobuf.NetworkAck', not just 'NetworkAck')." << std::endl;
234 exit(EXIT_FAILURE);
235 }
236
159 237
160 boost::shared_ptr<google::protobuf::Message> msg = dccl::DynamicProtobufManager::new_protobuf_message(desc);238 boost::shared_ptr<google::protobuf::Message> msg = dccl::DynamicProtobufManager::new_protobuf_message(desc);
161 google::protobuf::TextFormat::ParseFromString(input, msg.get());239 google::protobuf::TextFormat::ParseFromString(input, msg.get());
@@ -167,6 +245,13 @@
167 switch(cfg.format)245 switch(cfg.format)
168 {246 {
169 default:247 default:
248 case BINARY:
249 {
250 std::ofstream fout("/dev/stdout", std::ios::binary | std::ios::app);
251 fout.write(encoded.data(), encoded.size());
252 break;
253 }
254
170 case TEXTFORMAT:255 case TEXTFORMAT:
171 {256 {
172 257
@@ -197,49 +282,61 @@
197282
198void decode(dccl::Codec& dccl, const Config& cfg)283void decode(dccl::Codec& dccl, const Config& cfg)
199{284{
200 if(cfg.message.size() != 1)285 std::string input;
286 if(cfg.format == BINARY)
201 {287 {
202 std::cerr << "Exactly one DCCL message must be specified with -m or --message" << std::endl;288 std::ifstream fin("/dev/stdin", std::ios::binary);
203 exit(EXIT_FAILURE);289 std::ostringstream ostrm;
290 ostrm << fin.rdbuf();
291 input = ostrm.str();
204 }292 }
205 293 else
206 while(!std::cin.eof())
207 {294 {
208 std::string input;295 while(!std::cin.eof())
209 std::getline (std::cin, input);
210
211 if(boost::trim_copy(input).empty())
212 continue;
213
214 switch(cfg.format)
215 {296 {
216 default:297 std::string line;
217 case TEXTFORMAT:298 std::getline (std::cin, line);
299
300 if(boost::trim_copy(line).empty())
301 continue;
302
303 switch(cfg.format)
218 {304 {
219 boost::trim_if(input, boost::is_any_of("\""));305 default:
220306 case BINARY:
221 307 break;
222 ByteString s;308
223 google::protobuf::TextFormat::ParseFieldValueFromString("\"" + input + "\"", s.GetDescriptor()->FindFieldByNumber(1), &s);309 case TEXTFORMAT:
224 input = s.b();310 {
225 break;311 boost::trim_if(line, boost::is_any_of("\""));
312
313
314 ByteString s;
315 google::protobuf::TextFormat::ParseFieldValueFromString("\"" + line + "\"", s.GetDescriptor()->FindFieldByNumber(1), &s);
316 input += s.b();
317 break;
318 }
319 case HEX:
320 input += dccl::hex_decode(line);
321 break;
322 case BASE64:
323 std::stringstream instream(line);
324 std::stringstream outstream;
325 base64::decoder D;
326 D.decode(instream, outstream);
327 input += outstream.str();
328 break;
226 }329 }
227 case HEX:
228 input = dccl::hex_decode(input);
229 break;
230 case BASE64:
231 std::string in = input;
232 std::stringstream instream(input);
233 std::stringstream outstream;
234 base64::decoder D;
235 D.decode(instream, outstream);
236 input = outstream.str();
237 break;
238 }330 }
331 }
239332
240 boost::shared_ptr<google::protobuf::Message> msg = dccl.decode<boost::shared_ptr<google::protobuf::Message> >(input);333 while(!input.empty())
334 {
335 boost::shared_ptr<google::protobuf::Message> msg = dccl.decode<boost::shared_ptr<google::protobuf::Message> >(&input);
336 if(!cfg.omit_prefix)
337 std::cout << "|" << msg->GetDescriptor()->full_name() << "| ";
241 std::cout << msg->ShortDebugString() << std::endl;338 std::cout << msg->ShortDebugString() << std::endl;
242 } 339 }
243}340}
244341
245void disp_proto(dccl::Codec& dccl, const Config& cfg)342void disp_proto(dccl::Codec& dccl, const Config& cfg)
@@ -286,7 +383,10 @@
286 options.push_back(dccl::Option('l', "dlopen", required_argument, "Open this shared library containing compiled DCCL messages."));383 options.push_back(dccl::Option('l', "dlopen", required_argument, "Open this shared library containing compiled DCCL messages."));
287 options.push_back(dccl::Option('m', "message", required_argument, "Message name to encode, decode or analyze."));384 options.push_back(dccl::Option('m', "message", required_argument, "Message name to encode, decode or analyze."));
288 options.push_back(dccl::Option('f', "proto_file", required_argument, ".proto file to load."));385 options.push_back(dccl::Option('f', "proto_file", required_argument, ".proto file to load."));
289 options.push_back(dccl::Option(0, "format", required_argument, "Format for encode output or decode input: 'hex' is ascii-encoded hexadecimal (default), 'textformat' is a Google Protobuf TextFormat byte string, 'base64' is ascii-encoded base 64."));386 options.push_back(dccl::Option(0, "format", required_argument, "Format for encode output or decode input: 'bin' (default) is raw binary, 'hex' is ascii-encoded hexadecimal, 'textformat' is a Google Protobuf TextFormat byte string, 'base64' is ascii-encoded base 64."));
387 options.push_back(dccl::Option('v', "verbose", no_argument, "Display extra debugging information."));
388 options.push_back(dccl::Option('o', "omit_prefix", no_argument, "Omit the DCCL type name prefix from the output of decode."));
389 options.push_back(dccl::Option('i', "id_codec", required_argument, "(Advanced) name for a nonstandard DCCL ID codec to use"));
290 390
291 std::vector<option> long_options; 391 std::vector<option> long_options;
292 std::string opt_string;392 std::string opt_string;
@@ -314,6 +414,8 @@
314 cfg->format = HEX;414 cfg->format = HEX;
315 else if(!strcmp(optarg, "base64"))415 else if(!strcmp(optarg, "base64"))
316 cfg->format = BASE64;416 cfg->format = BASE64;
417 else if(!strcmp(optarg, "bin"))
418 cfg->format = BINARY;
317 else419 else
318 {420 {
319 std::cerr << "Invalid format '" << optarg << "'" << std::endl;421 std::cerr << "Invalid format '" << optarg << "'" << std::endl;
@@ -336,6 +438,9 @@
336 case 'l': cfg->dlopen.insert(optarg); break;438 case 'l': cfg->dlopen.insert(optarg); break;
337 case 'm': cfg->message.insert(optarg); break;439 case 'm': cfg->message.insert(optarg); break;
338 case 'f': cfg->proto_file.insert(optarg); break; 440 case 'f': cfg->proto_file.insert(optarg); break;
441 case 'i': cfg->id_codec = optarg; break;
442 case 'v': cfg->verbose = true; break;
443 case 'o': cfg->omit_prefix = true; break;
339 444
340 case 'h':445 case 'h':
341 std::cout << "Usage of the Dynamic Compact Control Language (DCCL) tool ('dccl'): " << std::endl;446 std::cout << "Usage of the Dynamic Compact Control Language (DCCL) tool ('dccl'): " << std::endl;
342447
=== modified file 'src/arithmetic/field_codec_arithmetic.cpp'
--- src/arithmetic/field_codec_arithmetic.cpp 2013-06-18 12:55:43 +0000
+++ src/arithmetic/field_codec_arithmetic.cpp 2014-08-27 16:27:22 +0000
@@ -38,9 +38,9 @@
3838
39// shared library load39// shared library load
4040
41extern "C"41struct CodecLoader
42{42{
43 void dccl3_load(dccl::Codec* dccl)43 CodecLoader()
44 {44 {
45 using namespace dccl;45 using namespace dccl;
46 46
@@ -53,6 +53,29 @@
53 FieldCodecManager::add<ArithmeticFieldCodec<bool> >("_arithmetic");53 FieldCodecManager::add<ArithmeticFieldCodec<bool> >("_arithmetic");
54 FieldCodecManager::add<ArithmeticFieldCodec<const google::protobuf::EnumValueDescriptor*> >("_arithmetic");54 FieldCodecManager::add<ArithmeticFieldCodec<const google::protobuf::EnumValueDescriptor*> >("_arithmetic");
55 }55 }
56 ~CodecLoader()
57 {
58 using namespace dccl;
59
60 FieldCodecManager::remove<ArithmeticFieldCodec<int32> >("_arithmetic");
61 FieldCodecManager::remove<ArithmeticFieldCodec<int64> >("_arithmetic");
62 FieldCodecManager::remove<ArithmeticFieldCodec<uint32> >("_arithmetic");
63 FieldCodecManager::remove<ArithmeticFieldCodec<uint64> >("_arithmetic");
64 FieldCodecManager::remove<ArithmeticFieldCodec<double> >("_arithmetic");
65 FieldCodecManager::remove<ArithmeticFieldCodec<float> >("_arithmetic");
66 FieldCodecManager::remove<ArithmeticFieldCodec<bool> >("_arithmetic");
67 FieldCodecManager::remove<ArithmeticFieldCodec<const google::protobuf::EnumValueDescriptor*> >("_arithmetic");
68 }
69};
70
71
72static CodecLoader loader;
73
74extern "C"
75{
76 void dccl3_load(dccl::Codec* dccl)
77 {
78 }
56}79}
5780
58dccl::Model::symbol_type dccl::Model::value_to_symbol(value_type value) const81dccl::Model::symbol_type dccl::Model::value_to_symbol(value_type value) const
5982
=== modified file 'src/binary.h'
--- src/binary.h 2014-04-22 20:10:37 +0000
+++ src/binary.h 2014-08-27 16:27:22 +0000
@@ -29,6 +29,8 @@
29#include <sstream>29#include <sstream>
3030
31#include "dccl/common.h"31#include "dccl/common.h"
32#include "dccl/b64/encode.h"
33#include "dccl/b64/decode.h"
3234
33namespace dccl35namespace dccl
34{36{
@@ -124,6 +126,27 @@
124 hex_encode(in, &out);126 hex_encode(in, &out);
125 return out;127 return out;
126 }128 }
129
130
131 inline std::string b64_encode(const std::string& in)
132 {
133 std::stringstream instream(in);
134 std::stringstream outstream;
135 base64::encoder D;
136 D.encode(instream, outstream);
137 return outstream.str();
138 }
139
140 inline std::string b64_decode(const std::string& in)
141 {
142 std::stringstream instream(in);
143 std::stringstream outstream;
144 base64::decoder D;
145 D.decode(instream, outstream);
146 return outstream.str();
147 }
148
149
127 150
128 /// \return ceil(log2(v))151 /// \return ceil(log2(v))
129 inline unsigned ceil_log2(dccl::uint64 v)152 inline unsigned ceil_log2(dccl::uint64 v)
130153
=== modified file 'src/ccl/CMakeLists.txt'
--- src/ccl/CMakeLists.txt 2014-01-06 17:25:02 +0000
+++ src/ccl/CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -17,7 +17,6 @@
17set_target_properties(dccl_ccl_compat 17set_target_properties(dccl_ccl_compat
18 PROPERTIES VERSION "${DCCL_VERSION}" SOVERSION "${DCCL_SOVERSION}")18 PROPERTIES VERSION "${DCCL_VERSION}" SOVERSION "${DCCL_SOVERSION}")
1919
20
21install(TARGETS dccl_ccl_compat EXPORT dccl-config20install(TARGETS dccl_ccl_compat EXPORT dccl-config
22 LIBRARY DESTINATION lib21 LIBRARY DESTINATION lib
23 ARCHIVE DESTINATION lib) 22 ARCHIVE DESTINATION lib)
2423
=== modified file 'src/ccl/ccl_compatibility.cpp'
--- src/ccl/ccl_compatibility.cpp 2013-06-18 12:55:43 +0000
+++ src/ccl/ccl_compatibility.cpp 2014-08-27 16:27:22 +0000
@@ -31,27 +31,54 @@
3131
32// shared library load32// shared library load
3333
34struct CodecLoader
35{
36 CodecLoader()
37 {
38 using namespace dccl;
39 FieldCodecManager::add<LegacyCCLIdentifierCodec>("dccl.ccl.id");
40
41 FieldCodecManager::add<LegacyCCLLatLonCompressedCodec>("_ccl_latloncompressed");
42 FieldCodecManager::add<LegacyCCLFixAgeCodec>("_ccl_fix_age");
43 FieldCodecManager::add<LegacyCCLTimeDateCodec>("_ccl_time_date");
44 FieldCodecManager::add<LegacyCCLHeadingCodec>("_ccl_heading");
45 FieldCodecManager::add<LegacyCCLDepthCodec>("_ccl_depth");
46 FieldCodecManager::add<LegacyCCLVelocityCodec>("_ccl_velocity");
47 FieldCodecManager::add<LegacyCCLWattsCodec>("_ccl_watts");
48 FieldCodecManager::add<LegacyCCLGFIPitchOilCodec>("_ccl_gfi_pitch_oil");
49 FieldCodecManager::add<LegacyCCLSpeedCodec>("_ccl_speed");
50 FieldCodecManager::add<LegacyCCLHiResAltitudeCodec>("_ccl_hires_altitude");
51 FieldCodecManager::add<LegacyCCLTemperatureCodec>("_ccl_temperature");
52 FieldCodecManager::add<LegacyCCLSalinityCodec>("_ccl_salinity");
53 FieldCodecManager::add<LegacyCCLSoundSpeedCodec>("_ccl_sound_speed");
54 }
55 ~CodecLoader()
56 {
57 using namespace dccl;
58 FieldCodecManager::remove<LegacyCCLIdentifierCodec>("dccl.ccl.id");
59
60 FieldCodecManager::remove<LegacyCCLLatLonCompressedCodec>("_ccl_latloncompressed");
61 FieldCodecManager::remove<LegacyCCLFixAgeCodec>("_ccl_fix_age");
62 FieldCodecManager::remove<LegacyCCLTimeDateCodec>("_ccl_time_date");
63 FieldCodecManager::remove<LegacyCCLHeadingCodec>("_ccl_heading");
64 FieldCodecManager::remove<LegacyCCLDepthCodec>("_ccl_depth");
65 FieldCodecManager::remove<LegacyCCLVelocityCodec>("_ccl_velocity");
66 FieldCodecManager::remove<LegacyCCLWattsCodec>("_ccl_watts");
67 FieldCodecManager::remove<LegacyCCLGFIPitchOilCodec>("_ccl_gfi_pitch_oil");
68 FieldCodecManager::remove<LegacyCCLSpeedCodec>("_ccl_speed");
69 FieldCodecManager::remove<LegacyCCLHiResAltitudeCodec>("_ccl_hires_altitude");
70 FieldCodecManager::remove<LegacyCCLTemperatureCodec>("_ccl_temperature");
71 FieldCodecManager::remove<LegacyCCLSalinityCodec>("_ccl_salinity");
72 FieldCodecManager::remove<LegacyCCLSoundSpeedCodec>("_ccl_sound_speed");
73 }
74};
75
76static CodecLoader loader;
3477
35extern "C"78extern "C"
36{79{
37 void dccl3_load(dccl::Codec* dccl)80 void dccl3_load(dccl::Codec* dccl)
38 {81 {
39 using namespace dccl;
40
41 FieldCodecManager::add<LegacyCCLLatLonCompressedCodec>("_ccl_latloncompressed");
42 FieldCodecManager::add<LegacyCCLFixAgeCodec>("_ccl_fix_age");
43 FieldCodecManager::add<LegacyCCLTimeDateCodec>("_ccl_time_date");
44 FieldCodecManager::add<LegacyCCLHeadingCodec>("_ccl_heading");
45 FieldCodecManager::add<LegacyCCLDepthCodec>("_ccl_depth");
46 FieldCodecManager::add<LegacyCCLVelocityCodec>("_ccl_velocity");
47 FieldCodecManager::add<LegacyCCLWattsCodec>("_ccl_watts");
48 FieldCodecManager::add<LegacyCCLGFIPitchOilCodec>("_ccl_gfi_pitch_oil");
49 FieldCodecManager::add<LegacyCCLSpeedCodec>("_ccl_speed");
50 FieldCodecManager::add<LegacyCCLHiResAltitudeCodec>("_ccl_hires_altitude");
51 FieldCodecManager::add<LegacyCCLTemperatureCodec>("_ccl_temperature");
52 FieldCodecManager::add<LegacyCCLSalinityCodec>("_ccl_salinity");
53 FieldCodecManager::add<LegacyCCLSoundSpeedCodec>("_ccl_sound_speed");
54
55 dccl->load<dccl::protobuf::CCLMDATEmpty>();82 dccl->load<dccl::protobuf::CCLMDATEmpty>();
56 dccl->load<dccl::protobuf::CCLMDATRedirect>();83 dccl->load<dccl::protobuf::CCLMDATRedirect>();
57 dccl->load<dccl::protobuf::CCLMDATBathy>();84 dccl->load<dccl::protobuf::CCLMDATBathy>();
5885
=== modified file 'src/ccl/ccl_compatibility.h'
--- src/ccl/ccl_compatibility.h 2013-09-12 16:23:45 +0000
+++ src/ccl/ccl_compatibility.h 2014-08-27 16:27:22 +0000
@@ -24,7 +24,8 @@
24#ifndef DCCLCCLCOMPATIBILITY20120426H24#ifndef DCCLCCLCOMPATIBILITY20120426H
25#define DCCLCCLCOMPATIBILITY20120426H25#define DCCLCCLCOMPATIBILITY20120426H
2626
27#include "dccl/field_codec_default.h"27#include "dccl/codecs2/field_codec_default.h"
28#include "dccl/field_codec_id.h"
28#include "dccl/ccl/protobuf/ccl.pb.h"29#include "dccl/ccl/protobuf/ccl.pb.h"
29#include "dccl/ccl/protobuf/ccl_extensions.pb.h"30#include "dccl/ccl/protobuf/ccl_extensions.pb.h"
3031
@@ -33,8 +34,6 @@
33 void dccl3_load(dccl::Codec* dccl);34 void dccl3_load(dccl::Codec* dccl);
34}35}
3536
36
37
38namespace dccl37namespace dccl
39{38{
40 const unsigned char DCCL_CCL_HEADER = 32;39 const unsigned char DCCL_CCL_HEADER = 32;
@@ -117,7 +116,7 @@
117 enum { LATLON_COMPRESSED_BYTE_SIZE = 3 }; 116 enum { LATLON_COMPRESSED_BYTE_SIZE = 3 };
118 };117 };
119118
120 class LegacyCCLFixAgeCodec : public dccl::DefaultNumericFieldCodec<dccl::uint32>119 class LegacyCCLFixAgeCodec : public dccl::v2::DefaultNumericFieldCodec<dccl::uint32>
121 {120 {
122 private:121 private:
123 dccl::Bitset encode()122 dccl::Bitset encode()
124123
=== modified file 'src/codec.cpp'
--- src/codec.cpp 2014-04-22 20:10:37 +0000
+++ src/codec.cpp 2014-08-27 16:27:22 +0000
@@ -38,7 +38,9 @@
38#endif // HAS_CRYPTOPP38#endif // HAS_CRYPTOPP
3939
40#include "dccl/codec.h"40#include "dccl/codec.h"
41#include "field_codec_default.h"41#include "dccl/codecs2/field_codec_default.h"
42#include "dccl/codecs3/field_codec_default.h"
43#include "dccl/field_codec_id.h"
4244
43#include "dccl/protobuf/option_extensions.pb.h"45#include "dccl/protobuf/option_extensions.pb.h"
4446
@@ -63,7 +65,7 @@
63dccl::Codec::Codec(const std::string& dccl_id_codec)65dccl::Codec::Codec(const std::string& dccl_id_codec)
64 : id_codec_(dccl_id_codec)66 : id_codec_(dccl_id_codec)
65{67{
66 FieldCodecManager::add<DefaultIdentifierCodec>("_default_id_codec");68 FieldCodecManager::add<DefaultIdentifierCodec>(default_id_codec_name());
67 // make sure the id codec exists69 // make sure the id codec exists
68 id_codec();70 id_codec();
69 set_default_codecs();71 set_default_codecs();
@@ -77,31 +79,59 @@
77 if(!defaults_loaded)79 if(!defaults_loaded)
78 {80 {
79 using google::protobuf::FieldDescriptor;81 using google::protobuf::FieldDescriptor;
8082
81 FieldCodecManager::add<DefaultNumericFieldCodec<double> >(default_codec_name());83 // version 2
82 FieldCodecManager::add<DefaultNumericFieldCodec<float> >(default_codec_name());84 FieldCodecManager::add<v2::DefaultNumericFieldCodec<double> >(default_codec_name());
83 FieldCodecManager::add<DefaultBoolCodec>(default_codec_name());85 FieldCodecManager::add<v2::DefaultNumericFieldCodec<float> >(default_codec_name());
84 FieldCodecManager::add<DefaultNumericFieldCodec<int32> >(default_codec_name());86 FieldCodecManager::add<v2::DefaultBoolCodec>(default_codec_name());
85 FieldCodecManager::add<DefaultNumericFieldCodec<int64> >(default_codec_name());87 FieldCodecManager::add<v2::DefaultNumericFieldCodec<int32> >(default_codec_name());
86 FieldCodecManager::add<DefaultNumericFieldCodec<uint32> >(default_codec_name());88 FieldCodecManager::add<v2::DefaultNumericFieldCodec<int64> >(default_codec_name());
87 FieldCodecManager::add<DefaultNumericFieldCodec<uint64> >(default_codec_name());89 FieldCodecManager::add<v2::DefaultNumericFieldCodec<uint32> >(default_codec_name());
88 FieldCodecManager::add<DefaultStringCodec, FieldDescriptor::TYPE_STRING>(default_codec_name());90 FieldCodecManager::add<v2::DefaultNumericFieldCodec<uint64> >(default_codec_name());
89 FieldCodecManager::add<DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(default_codec_name());91 FieldCodecManager::add<v2::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(default_codec_name());
90 FieldCodecManager::add<DefaultEnumCodec>(default_codec_name());92 FieldCodecManager::add<v2::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(default_codec_name());
91 FieldCodecManager::add<DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(default_codec_name());93 FieldCodecManager::add<v2::DefaultEnumCodec >(default_codec_name());
92 94 FieldCodecManager::add<v2::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(default_codec_name());
93 FieldCodecManager::add<TimeCodec<uint64> >("_time");95
94 FieldCodecManager::add<TimeCodec<int64> >("_time");96 FieldCodecManager::add<v2::TimeCodec<uint64> >("dccl.time2");
95 FieldCodecManager::add<TimeCodec<double> >("_time");97 FieldCodecManager::add<v2::TimeCodec<int64> >("dccl.time2");
96 98 FieldCodecManager::add<v2::TimeCodec<double> >("dccl.time2");
97 FieldCodecManager::add<StaticCodec<std::string> >("_static");99
98 FieldCodecManager::add<StaticCodec<double> >("_static");100 FieldCodecManager::add<v2::StaticCodec<std::string> >("dccl.static2");
99 FieldCodecManager::add<StaticCodec<float> >("_static");101 FieldCodecManager::add<v2::StaticCodec<double> >("dccl.static2");
100 FieldCodecManager::add<StaticCodec<int32> >("_static");102 FieldCodecManager::add<v2::StaticCodec<float> >("dccl.static2");
101 FieldCodecManager::add<StaticCodec<int64> >("_static");103 FieldCodecManager::add<v2::StaticCodec<int32> >("dccl.static2");
102 FieldCodecManager::add<StaticCodec<uint32> >("_static");104 FieldCodecManager::add<v2::StaticCodec<int64> >("dccl.static2");
103 FieldCodecManager::add<StaticCodec<uint64> >("_static");105 FieldCodecManager::add<v2::StaticCodec<uint32> >("dccl.static2");
104106 FieldCodecManager::add<v2::StaticCodec<uint64> >("dccl.static2");
107
108 // version 3
109 FieldCodecManager::add<v3::DefaultNumericFieldCodec<double> >(default_codec_name(3));
110 FieldCodecManager::add<v3::DefaultNumericFieldCodec<float> >(default_codec_name(3));
111 FieldCodecManager::add<v3::DefaultBoolCodec>(default_codec_name(3));
112 FieldCodecManager::add<v3::DefaultNumericFieldCodec<int32> >(default_codec_name(3));
113 FieldCodecManager::add<v3::DefaultNumericFieldCodec<int64> >(default_codec_name(3));
114 FieldCodecManager::add<v3::DefaultNumericFieldCodec<uint32> >(default_codec_name(3));
115 FieldCodecManager::add<v3::DefaultNumericFieldCodec<uint64> >(default_codec_name(3));
116 FieldCodecManager::add<v3::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(default_codec_name(3));
117 FieldCodecManager::add<v3::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(default_codec_name(3));
118 FieldCodecManager::add<v3::DefaultEnumCodec >(default_codec_name(3));
119 FieldCodecManager::add<v3::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(default_codec_name(3));
120
121 // for backwards compatibility
122 FieldCodecManager::add<v2::TimeCodec<uint64> >("_time");
123 FieldCodecManager::add<v2::TimeCodec<int64> >("_time");
124 FieldCodecManager::add<v2::TimeCodec<double> >("_time");
125
126 FieldCodecManager::add<v2::StaticCodec<std::string> >("_static");
127 FieldCodecManager::add<v2::StaticCodec<double> >("_static");
128 FieldCodecManager::add<v2::StaticCodec<float> >("_static");
129 FieldCodecManager::add<v2::StaticCodec<int32> >("_static");
130 FieldCodecManager::add<v2::StaticCodec<int64> >("_static");
131 FieldCodecManager::add<v2::StaticCodec<uint32> >("_static");
132 FieldCodecManager::add<v2::StaticCodec<uint64> >("_static");
133
134
105 defaults_loaded = true;135 defaults_loaded = true;
106 }136 }
107}137}
@@ -326,6 +356,9 @@
326 throw(Exception("Missing message option `(dccl.msg).id`. Specify a unique id (e.g. 3) in the body of your .proto message using \"option (dccl.msg).id = 3\""));356 throw(Exception("Missing message option `(dccl.msg).id`. Specify a unique id (e.g. 3) in the body of your .proto message using \"option (dccl.msg).id = 3\""));
327 if(!desc->options().GetExtension(dccl::msg).has_max_bytes())357 if(!desc->options().GetExtension(dccl::msg).has_max_bytes())
328 throw(Exception("Missing message option `(dccl.msg).max_bytes`. Specify a maximum (encoded) message size in bytes (e.g. 32) in the body of your .proto message using \"option (dccl.msg).max_bytes = 32\""));358 throw(Exception("Missing message option `(dccl.msg).max_bytes`. Specify a maximum (encoded) message size in bytes (e.g. 32) in the body of your .proto message using \"option (dccl.msg).max_bytes = 32\""));
359
360 if(!desc->options().GetExtension(dccl::msg).has_codec_version())
361 dlog.is(WARN) && dlog << "** NOTE: No (dccl.msg).codec_version set for DCCL Message '" << desc->full_name() << "'. Unless you need backwards compatibility with Goby 2.0 (DCCL2), we highly recommend setting 'option (dccl.msg).codec_version = 3' in the message definition for " << desc->full_name() << " to use the default DCCL3 codecs. If you need compatibility with Goby 2.0, ignore this warning, or set 'option (dccl.msg).codec_version = 2' to remove this warning. **" << std::endl;
329 362
330 boost::shared_ptr<FieldCodecBase> codec = FieldCodecManager::find(desc);363 boost::shared_ptr<FieldCodecBase> codec = FieldCodecManager::find(desc);
331364
@@ -419,7 +452,8 @@
419 const unsigned allowed_byte_size = desc->options().GetExtension(dccl::msg).max_bytes();452 const unsigned allowed_byte_size = desc->options().GetExtension(dccl::msg).max_bytes();
420 const unsigned allowed_bit_size = allowed_byte_size * BITS_IN_BYTE;453 const unsigned allowed_bit_size = allowed_byte_size * BITS_IN_BYTE;
421454
422 std::string guard = std::string((full_width-desc->full_name().size())/2, '=');455 std::string message_name = boost::lexical_cast<std::string>(dccl_id) + ": " + desc->full_name();
456 std::string guard = std::string((full_width-message_name.size())/2, '=');
423457
424 std::string bits_dccl_head_str = "dccl.id head";458 std::string bits_dccl_head_str = "dccl.id head";
425 std::string bits_user_head_str = "user head";459 std::string bits_user_head_str = "user head";
@@ -430,7 +464,7 @@
430 const int spaces = 8;464 const int spaces = 8;
431 std::string indent = std::string(spaces,' ');465 std::string indent = std::string(spaces,' ');
432 466
433 *os << guard << " " << desc->full_name() << " " << guard << "\n"467 *os << guard << " " << message_name << " " << guard << "\n"
434 << "Actual maximum size of message: " << byte_size << " bytes / "468 << "Actual maximum size of message: " << byte_size << " bytes / "
435 << byte_size*BITS_IN_BYTE << " bits\n"469 << byte_size*BITS_IN_BYTE << " bits\n"
436 << indent << bits_dccl_head_str << std::setfill('.') << std::setw(bits_width-bits_dccl_head_str.size()) << id_bit_size << "\n"470 << indent << bits_dccl_head_str << std::setfill('.') << std::setw(bits_width-bits_dccl_head_str.size()) << id_bit_size << "\n"
@@ -443,7 +477,7 @@
443 std::string header_str = "Header";477 std::string header_str = "Header";
444 std::string header_guard = std::string((full_width-header_str.size())/2, '-');478 std::string header_guard = std::string((full_width-header_str.size())/2, '-');
445 *os << header_guard << " " << header_str << " " << header_guard << std::endl;479 *os << header_guard << " " << header_str << " " << header_guard << std::endl;
446 *os << bits_dccl_head_str << std::setfill('.') << std::setw(bits_width-bits_dccl_head_str.size()+spaces) << id_bit_size << "\n";480 *os << bits_dccl_head_str << std::setfill('.') << std::setw(bits_width-bits_dccl_head_str.size()+spaces) << id_bit_size << " {" << id_codec()->name() << "}\n";
447 codec->base_info(os, desc, MessageStack::HEAD);481 codec->base_info(os, desc, MessageStack::HEAD);
448// *os << std::string(header_str.size() + 2 + 2*header_guard.size(), '-') << std::endl;482// *os << std::string(header_str.size() + 2 + 2*header_guard.size(), '-') << std::endl;
449 483
@@ -459,6 +493,9 @@
459 {493 {
460 dlog.is(DEBUG1) && dlog << "Message " << desc->full_name() << " cannot provide information due to invalid configuration. Reason: " << e.what() << std::endl;494 dlog.is(DEBUG1) && dlog << "Message " << desc->full_name() << " cannot provide information due to invalid configuration. Reason: " << e.what() << std::endl;
461 }495 }
496
497 os->flush();
498
462 }499 }
463 500
464}501}
@@ -564,4 +601,5 @@
564 601
565// *os << std::string(codec_str.size() + 2 + 2*codec_guard.size(), '|') << std::endl;602// *os << std::string(codec_str.size() + 2 + 2*codec_guard.size(), '|') << std::endl;
566 }603 }
604
567}605}
568606
=== modified file 'src/codec.h'
--- src/codec.h 2014-04-22 20:10:37 +0000
+++ src/codec.h 2014-08-27 16:27:22 +0000
@@ -42,7 +42,9 @@
42#include "exception.h"42#include "exception.h"
43#include "field_codec.h"43#include "field_codec.h"
44#include "field_codec_fixed.h"44#include "field_codec_fixed.h"
45#include "field_codec_default.h"45
46#include "codecs2/field_codec_default_message.h"
47#include "codecs3/field_codec_default_message.h"
46#include "type_helper.h"48#include "type_helper.h"
47#include "field_codec_manager.h"49#include "field_codec_manager.h"
48 50
@@ -84,7 +86,7 @@
84 class Codec86 class Codec
85 {87 {
86 public: 88 public:
87 Codec(const std::string& dccl_id_codec = "_default_id_codec");89 Codec(const std::string& dccl_id_codec = default_id_codec_name());
88 virtual ~Codec()90 virtual ~Codec()
89 {91 {
90 for(std::vector<void *>::iterator it = dl_handles_.begin(),92 for(std::vector<void *>::iterator it = dl_handles_.begin(),
@@ -181,6 +183,9 @@
181 return desc->options().GetExtension(dccl::msg).id();183 return desc->options().GetExtension(dccl::msg).id();
182 } 184 }
183185
186 /// \brief Provides a map of all loaded DCCL IDs to the equivalent Protobuf descriptor
187 const std::map<int32, const google::protobuf::Descriptor*>& loaded() const { return id2desc_; }
188
184 //@}189 //@}
185 190
186 /// \brief Provides the encoded size (in bytes) of msg. This is useful if you need to know the size of a message before encoding it (encoding it is generally much more expensive than calling this method)191 /// \brief Provides the encoded size (in bytes) of msg. This is useful if you need to know the size of a message before encoding it (encoding it is generally much more expensive than calling this method)
@@ -237,8 +242,26 @@
237 /// \return pointer to decoded message (a google::protobuf::Message). You are responsible for deleting the memory used by this pointer, so we recommend using a smart pointer here (e.g. boost::shared_ptr or the C++11 equivalent). This message can be examined using the Google Reflection/Descriptor API.242 /// \return pointer to decoded message (a google::protobuf::Message). You are responsible for deleting the memory used by this pointer, so we recommend using a smart pointer here (e.g. boost::shared_ptr or the C++11 equivalent). This message can be examined using the Google Reflection/Descriptor API.
238 template<typename GoogleProtobufMessagePointer>243 template<typename GoogleProtobufMessagePointer>
239 GoogleProtobufMessagePointer decode(std::string* bytes);244 GoogleProtobufMessagePointer decode(std::string* bytes);
240245
241 friend class DefaultMessageCodec;246 static std::string default_id_codec_name()
247 { return "dccl.default.id"; }
248
249
250 static std::string default_codec_name(int version = 2)
251 {
252 switch(version)
253 {
254 case 2:
255 return dccl::DCCLFieldOptions::descriptor()->FindFieldByName("codec")->default_value_string();
256 default:
257 return "dccl.default" + boost::lexical_cast<std::string>(version);
258 }
259
260 }
261
262
263 friend class v2::DefaultMessageCodec;
264 //friend class v3::DefaultMessageCodec;
242 private:265 private:
243 Codec(const Codec&);266 Codec(const Codec&);
244 Codec& operator= (const Codec&);267 Codec& operator= (const Codec&);
@@ -254,11 +277,6 @@
254 id_codec_);277 id_codec_);
255 }278 }
256 279
257 static const std::string& default_codec_name()
258 {
259 return dccl::DCCLFieldOptions::descriptor()->FindFieldByName("codec")->default_value_string();
260 }
261
262 private:280 private:
263 // SHA256 hash of the crypto passphrase281 // SHA256 hash of the crypto passphrase
264 std::string crypto_key_;282 std::string crypto_key_;
@@ -287,7 +305,7 @@
287 unsigned this_id = id(bytes); 305 unsigned this_id = id(bytes);
288306
289 if(!id2desc_.count(this_id))307 if(!id2desc_.count(this_id))
290 throw(Exception("Message id " + boost::lexical_cast<std::string>(this_id) + " has not been validated. Call validate() before decoding this type."));308 throw(Exception("Message id " + boost::lexical_cast<std::string>(this_id) + " has not been loaded. Call load() before decoding this type."));
291 309
292 // ownership of this object goes to the caller of decode()310 // ownership of this object goes to the caller of decode()
293 GoogleProtobufMessagePointer msg =311 GoogleProtobufMessagePointer msg =
294312
=== added directory 'src/codecs2'
=== renamed file 'src/field_codec_default.cpp' => 'src/codecs2/field_codec_default.cpp'
--- src/field_codec_default.cpp 2014-04-22 20:10:37 +0000
+++ src/codecs2/field_codec_default.cpp 2014-08-27 16:27:22 +0000
@@ -25,108 +25,28 @@
25#include <sstream>25#include <sstream>
26#include <algorithm>26#include <algorithm>
2727
28#include "field_codec_default.h"28#include "dccl/codecs2/field_codec_default.h"
29#include "type_helper.h"29#include "dccl/type_helper.h"
30#include "dccl/codec.h"30#include "dccl/codec.h"
3131
32using namespace dccl::logger;32using namespace dccl::logger;
3333
3434
35//35//
36// DefaultIdentifierCodec
37//
38
39dccl::Bitset dccl::DefaultIdentifierCodec::encode()
40{
41 return encode(0);
42}
43
44dccl::Bitset dccl::DefaultIdentifierCodec::encode(const uint32& id)
45{
46 if(id <= ONE_BYTE_MAX_ID)
47 {
48 return(dccl::Bitset(this_size(id), id) << 1);
49 }
50 else
51 {
52 dccl::Bitset return_bits(this_size(id), id);
53 return_bits <<= 1;
54 // set LSB to indicate long header form
55 return_bits.set(0, true);
56
57
58 return return_bits;
59 }
60}
61
62dccl::uint32 dccl::DefaultIdentifierCodec::decode(Bitset* bits)
63{
64 if(bits->test(0))
65 {
66 // long header
67 // grabs more bits to add to the MSB of `bits`
68 bits->get_more_bits((LONG_FORM_ID_BYTES - SHORT_FORM_ID_BYTES)*BITS_IN_BYTE);
69 // discard identifier
70 *(bits) >>= 1;
71 return bits->to_ulong();
72 }
73 else
74 {
75 // short header
76 *(bits) >>= 1;
77 return bits->to_ulong();
78 }
79}
80
81unsigned dccl::DefaultIdentifierCodec::size()
82{
83 return this_size(0);
84}
85
86unsigned dccl::DefaultIdentifierCodec::size(const uint32& id)
87{
88 return this_size(id);
89}
90
91unsigned dccl::DefaultIdentifierCodec::this_size(const uint32& id)
92{
93 if(id > TWO_BYTE_MAX_ID)
94 throw(Exception("dccl.id provided (" + boost::lexical_cast<std::string>(id) + ") exceeds maximum: " + boost::lexical_cast<std::string>(int(TWO_BYTE_MAX_ID))));
95
96 return (id <= ONE_BYTE_MAX_ID) ?
97 SHORT_FORM_ID_BYTES*BITS_IN_BYTE :
98 LONG_FORM_ID_BYTES*BITS_IN_BYTE;
99}
100
101
102unsigned dccl::DefaultIdentifierCodec::max_size()
103{
104 return LONG_FORM_ID_BYTES * BITS_IN_BYTE;
105}
106
107unsigned dccl::DefaultIdentifierCodec::min_size()
108{
109 return SHORT_FORM_ID_BYTES * BITS_IN_BYTE;
110}
111
112
113
114
115//
116// DefaultBoolCodec36// DefaultBoolCodec
117//37//
11838
119dccl::Bitset dccl::DefaultBoolCodec::encode()39dccl::Bitset dccl::v2::DefaultBoolCodec::encode()
120{40{
121 return Bitset(size());41 return Bitset(size());
122}42}
12343
124dccl::Bitset dccl::DefaultBoolCodec::encode(const bool& wire_value)44dccl::Bitset dccl::v2::DefaultBoolCodec::encode(const bool& wire_value)
125{45{
126 return Bitset(size(), this_field()->is_required() ? wire_value : wire_value + 1);46 return Bitset(size(), this_field()->is_required() ? wire_value : wire_value + 1);
127}47}
12848
129bool dccl::DefaultBoolCodec::decode(Bitset* bits)49bool dccl::v2::DefaultBoolCodec::decode(Bitset* bits)
130{50{
131 unsigned long t = bits->to_ulong();51 unsigned long t = bits->to_ulong();
132 if(this_field()->is_required())52 if(this_field()->is_required())
@@ -145,7 +65,7 @@
145}65}
14666
14767
148unsigned dccl::DefaultBoolCodec::size()68unsigned dccl::v2::DefaultBoolCodec::size()
149{ 69{
150 // true and false70 // true and false
151 const unsigned BOOL_VALUES = 2;71 const unsigned BOOL_VALUES = 2;
@@ -155,19 +75,19 @@
155 return dccl::ceil_log2(BOOL_VALUES + NULL_VALUE);75 return dccl::ceil_log2(BOOL_VALUES + NULL_VALUE);
156}76}
15777
158void dccl::DefaultBoolCodec::validate()78void dccl::v2::DefaultBoolCodec::validate()
159{ }79{ }
16080
161//81//
162// DefaultStringCodec82// DefaultStringCodec
163//83//
16484
165dccl::Bitset dccl::DefaultStringCodec::encode()85dccl::Bitset dccl::v2::DefaultStringCodec::encode()
166{86{
167 return Bitset(min_size());87 return Bitset(min_size());
168}88}
16989
170dccl::Bitset dccl::DefaultStringCodec::encode(const std::string& wire_value)90dccl::Bitset dccl::v2::DefaultStringCodec::encode(const std::string& wire_value)
171{91{
172 std::string s = wire_value;92 std::string s = wire_value;
173 if(s.size() > dccl_field_options().max_length())93 if(s.size() > dccl_field_options().max_length())
@@ -197,7 +117,7 @@
197 return length_bits;117 return length_bits;
198}118}
199119
200std::string dccl::DefaultStringCodec::decode(Bitset* bits)120std::string dccl::v2::DefaultStringCodec::decode(Bitset* bits)
201{121{
202 unsigned value_length = bits->to_ulong();122 unsigned value_length = bits->to_ulong();
203 123
@@ -228,30 +148,30 @@
228 148
229}149}
230150
231unsigned dccl::DefaultStringCodec::size()151unsigned dccl::v2::DefaultStringCodec::size()
232{152{
233 return min_size();153 return min_size();
234}154}
235155
236unsigned dccl::DefaultStringCodec::size(const std::string& wire_value)156unsigned dccl::v2::DefaultStringCodec::size(const std::string& wire_value)
237{157{
238 return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size());158 return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size());
239}159}
240160
241161
242unsigned dccl::DefaultStringCodec::max_size()162unsigned dccl::v2::DefaultStringCodec::max_size()
243{163{
244 // string length + actual string164 // string length + actual string
245 return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;165 return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;
246}166}
247167
248unsigned dccl::DefaultStringCodec::min_size()168unsigned dccl::v2::DefaultStringCodec::min_size()
249{169{
250 return dccl::ceil_log2(MAX_STRING_LENGTH+1);170 return dccl::ceil_log2(MAX_STRING_LENGTH+1);
251}171}
252172
253173
254void dccl::DefaultStringCodec::validate()174void dccl::v2::DefaultStringCodec::validate()
255{175{
256 require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");176 require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
257 require(dccl_field_options().max_length() <= MAX_STRING_LENGTH,177 require(dccl_field_options().max_length() <= MAX_STRING_LENGTH,
@@ -261,13 +181,13 @@
261//181//
262// DefaultBytesCodec182// DefaultBytesCodec
263//183//
264dccl::Bitset dccl::DefaultBytesCodec::encode()184dccl::Bitset dccl::v2::DefaultBytesCodec::encode()
265{185{
266 return Bitset(min_size(), 0);186 return Bitset(min_size(), 0);
267}187}
268188
269189
270dccl::Bitset dccl::DefaultBytesCodec::encode(const std::string& wire_value)190dccl::Bitset dccl::v2::DefaultBytesCodec::encode(const std::string& wire_value)
271{191{
272 Bitset bits;192 Bitset bits;
273 bits.from_byte_string(wire_value);193 bits.from_byte_string(wire_value);
@@ -282,19 +202,19 @@
282 return bits;202 return bits;
283}203}
284204
285unsigned dccl::DefaultBytesCodec::size()205unsigned dccl::v2::DefaultBytesCodec::size()
286{206{
287 return min_size(); 207 return min_size();
288}208}
289209
290210
291unsigned dccl::DefaultBytesCodec::size(const std::string& wire_value)211unsigned dccl::v2::DefaultBytesCodec::size(const std::string& wire_value)
292{212{
293 return max_size();213 return max_size();
294}214}
295215
296216
297std::string dccl::DefaultBytesCodec::decode(Bitset* bits)217std::string dccl::v2::DefaultBytesCodec::decode(Bitset* bits)
298{218{
299 if(!this_field()->is_required())219 if(!this_field()->is_required())
300 {220 {
@@ -320,13 +240,13 @@
320 }240 }
321}241}
322242
323unsigned dccl::DefaultBytesCodec::max_size()243unsigned dccl::v2::DefaultBytesCodec::max_size()
324{244{
325 return dccl_field_options().max_length() * BITS_IN_BYTE +245 return dccl_field_options().max_length() * BITS_IN_BYTE +
326 (this_field()->is_required() ? 0 : 1); // presence bit?246 (this_field()->is_required() ? 0 : 1); // presence bit?
327}247}
328248
329unsigned dccl::DefaultBytesCodec::min_size()249unsigned dccl::v2::DefaultBytesCodec::min_size()
330{250{
331 if(this_field()->is_required())251 if(this_field()->is_required())
332 return max_size();252 return max_size();
@@ -334,7 +254,7 @@
334 return 1; // presence bit254 return 1; // presence bit
335}255}
336256
337void dccl::DefaultBytesCodec::validate()257void dccl::v2::DefaultBytesCodec::validate()
338{258{
339 require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");259 require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
340}260}
@@ -342,12 +262,12 @@
342//262//
343// DefaultEnumCodec263// DefaultEnumCodec
344//264//
345dccl::int32 dccl::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value)265dccl::int32 dccl::v2::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value)
346{266{
347 return field_value->index();267 return field_value->index();
348}268}
349269
350const google::protobuf::EnumValueDescriptor* dccl::DefaultEnumCodec::post_decode(const dccl::int32& wire_value)270const google::protobuf::EnumValueDescriptor* dccl::v2::DefaultEnumCodec::post_decode(const dccl::int32& wire_value)
351{271{
352 const google::protobuf::EnumDescriptor* e = this_field()->enum_type();272 const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
353273
354274
=== renamed file 'src/field_codec_default.h' => 'src/codecs2/field_codec_default.h'
--- src/field_codec_default.h 2014-04-22 20:10:37 +0000
+++ src/codecs2/field_codec_default.h 2014-08-27 16:27:22 +0000
@@ -2,6 +2,7 @@
2// GobySoft, LLC (2013-)2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)3// Massachusetts Institute of Technology (2007-2014)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
5//6//
6// This file is part of the Dynamic Compact Control Language Library7// This file is part of the Dynamic Compact Control Language Library
7// ("DCCL").8// ("DCCL").
@@ -39,328 +40,307 @@
3940
40#include "dccl/protobuf/option_extensions.pb.h"41#include "dccl/protobuf/option_extensions.pb.h"
4142
42#include "field_codec_default_message.h"43#include "dccl/codecs2/field_codec_default_message.h"
43#include "field_codec_fixed.h"44#include "dccl/field_codec_fixed.h"
44#include "field_codec.h"45#include "dccl/field_codec.h"
45#include "binary.h"46#include "dccl/binary.h"
4647
47namespace dccl48namespace dccl
48{49{
49 /// \brief Provides the default 1 byte or 2 byte DCCL ID codec50 namespace v2
50 class DefaultIdentifierCodec : public TypedFieldCodec<uint32>51 {
51 {52 /// \brief Provides a basic bounded arbitrary length numeric (double, float, uint32, uint64, int32, int64) encoder.
52 protected:53 ///
53 virtual Bitset encode();54 /// Takes ceil(log2((max-min)*10^precision)+1) bits for required fields, ceil(log2((max-min)*10^precision)+2) for optional fields.
54 virtual Bitset encode(const uint32& wire_value);55 template<typename WireType, typename FieldType = WireType>
55 virtual uint32 decode(Bitset* bits);56 class DefaultNumericFieldCodec : public TypedFixedFieldCodec<WireType, FieldType>
56 virtual unsigned size();57 {
57 virtual unsigned size(const uint32& wire_value);58 protected:
58 virtual unsigned max_size();59
59 virtual unsigned min_size();60 virtual double max()
60 virtual void validate() { }61 { return FieldCodecBase::dccl_field_options().max(); }
6162
62 private:63 virtual double min()
63 unsigned this_size(const uint32& wire_value);64 { return FieldCodecBase::dccl_field_options().min(); }
64 // maximum id we can fit in short or long header (MSB reserved to indicate65
65 // short or long header)66 virtual double precision()
66 enum { ONE_BYTE_MAX_ID = (1 << 7) - 1,67 { return FieldCodecBase::dccl_field_options().precision(); }
67 TWO_BYTE_MAX_ID = (1 << 15) - 1};68
68 69 virtual void validate()
69 enum { SHORT_FORM_ID_BYTES = 1,70 {
70 LONG_FORM_ID_BYTES = 2 };71 FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_min(),
71 };72 "missing (dccl.field).min");
7273 FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_max(),
73 74 "missing (dccl.field).max");
7475
75 /// \brief Provides a basic bounded arbitrary length numeric (double, float, uint32, uint64, int32, int64) encoder.76 validate_numeric_bounds();
76 ///77 }
77 /// Takes ceil(log2((max-min)*10^precision)+1) bits for required fields, ceil(log2((max-min)*10^precision)+2) for optional fields.78
78 template<typename WireType, typename FieldType = WireType>79 void validate_numeric_bounds()
79 class DefaultNumericFieldCodec : public TypedFixedFieldCodec<WireType, FieldType>80 {
80 {81
81 protected:82 // ensure given max and min fit within WireType ranges
8283 FieldCodecBase::require(min() >= boost::numeric::bounds<WireType>::lowest(),
83 virtual double max()84 "(dccl.field).min must be >= minimum of this field type.");
84 { return FieldCodecBase::dccl_field_options().max(); }85 FieldCodecBase::require(max() <= boost::numeric::bounds<WireType>::highest(),
8586 "(dccl.field).max must be <= maximum of this field type.");
86 virtual double min()87
87 { return FieldCodecBase::dccl_field_options().min(); }88
8889 // ensure value fits into double
89 virtual double precision()90 FieldCodecBase::require((precision() + std::ceil(std::log10(max() - min()))) <= std::numeric_limits<double>::digits10,
90 { return FieldCodecBase::dccl_field_options().precision(); }91 "[(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.");
91 92
92 virtual void validate()93 }
93 {94
94 FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_min(),95
95 "missing (dccl.field).min");96 Bitset encode()
96 FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_max(),97 {
97 "missing (dccl.field).max");98 return Bitset(size());
9899 }
99 validate_numeric_bounds();100
100 }101
101102 virtual Bitset encode(const WireType& value)
102 void validate_numeric_bounds()103 {
103 {104 // round first, before checking bounds
104105 WireType wire_value = dccl::round(value, precision());
105 // ensure given max and min fit within WireType ranges106
106 FieldCodecBase::require(min() >= boost::numeric::bounds<WireType>::lowest(),107 // check bounds, if out-of-bounds, send as zeros
107 "(dccl.field).min must be >= minimum of this field type.");108 if(wire_value < min() || wire_value > max())
108 FieldCodecBase::require(max() <= boost::numeric::bounds<WireType>::highest(),109 return Bitset(size());
109 "(dccl.field).max must be <= maximum of this field type.");110
110111 wire_value -= dccl::round((WireType)min(), precision());
111 112
112 // ensure value fits into double113 if (precision() < 0) {
113 FieldCodecBase::require((precision() + std::ceil(std::log10(max() - min()))) <= std::numeric_limits<double>::digits10,114 wire_value /= (WireType)std::pow(10.0, -precision());
114 "[(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.");115 } else if (precision() > 0) {
115 116 wire_value *= (WireType)std::pow(10.0, precision());
116 }117 }
117 118
118 119 dccl::uint64 uint_value = boost::numeric_cast<dccl::uint64>(dccl::round(wire_value, 0));
119 Bitset encode()120
120 {121 // "presence" value (0)
121 return Bitset(size());122 if(!FieldCodecBase::this_field()->is_required())
122 }123 uint_value += 1;
123 124
124 125
125 virtual Bitset encode(const WireType& value)126 Bitset encoded;
126 {127 encoded.from(uint_value, size());
127 WireType wire_value = value;128 return encoded;
128 129 }
129 if(wire_value < min() || wire_value > max())130
130 return Bitset(size()); 131 virtual WireType decode(Bitset* bits)
131 132 {
132 wire_value -= (WireType)min();133 // The line below SHOULD BE:
133134 // dccl::uint64 t = bits->to<dccl::uint64>();
134 wire_value = dccl::round(wire_value, precision());135 // But GCC3.3 requires an explicit template modifier on the method.
135 if (precision() < 0) {136 // See, e.g., http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10959
136 wire_value /= (WireType)std::pow(10.0, -precision());137 dccl::uint64 uint_value = (bits->template to<dccl::uint64>)();
137 } else if (precision() > 0) {138
138 wire_value *= (WireType)std::pow(10.0, precision());139 if(!FieldCodecBase::this_field()->is_required())
139 }140 {
140141 if(!uint_value) throw NullValueException();
141 // "presence" value (0)142 --uint_value;
142 if(!FieldCodecBase::this_field()->is_required())143 }
143 wire_value += 1;144
144 145 WireType wire_value = (WireType)uint_value;
145146
146 Bitset encoded;147 if (precision() < 0) {
147 encoded.from(boost::numeric_cast<dccl::uint64>(dccl::round(wire_value, 0)), size());148 wire_value *= (WireType)std::pow(10.0, -precision());
148 return encoded;149 } else if (precision() > 0) {
149 }150 wire_value /= (WireType)std::pow(10.0, precision());
150 151 }
151 virtual WireType decode(Bitset* bits)152
152 {153 // round values again to properly handle cases where double precision
153 // The line below SHOULD BE:154 // leads to slightly off values (e.g. 2.099999999 instead of 2.1)
154 // dccl::uint64 t = bits->to<dccl::uint64>();155 wire_value = dccl::round(wire_value + dccl::round((WireType)min(), precision()),
155 // But GCC3.3 requires an explicit template modifier on the method.156 precision());
156 // See, e.g., http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10959157
157 dccl::uint64 uint_value = (bits->template to<dccl::uint64>)();158 return wire_value;
158159 }
159 if(!FieldCodecBase::this_field()->is_required())160
160 {161 unsigned size()
161 if(!uint_value) throw NullValueException();162 {
162 --uint_value;163 // if not required field, leave one value for unspecified (always encoded as 0)
163 }164 const unsigned NULL_VALUE = FieldCodecBase::this_field()->is_required() ? 0 : 1;
164 165
165 WireType wire_value = (WireType)uint_value;166 return dccl::ceil_log2((max()-min())*std::pow(10.0, precision())+1 + NULL_VALUE);
166167 }
167 if (precision() < 0) {168
168 wire_value *= (WireType)std::pow(10.0, -precision());169 };
169 } else if (precision() > 0) {170
170 wire_value /= (WireType)std::pow(10.0, precision());171 /// \brief Provides a bool encoder. Uses 1 bit if field is `required`, 2 bits if `optional`
171 }172 ///
172173 /// [presence bit (0 bits if required, 1 bit if optional)][value (1 bit)]
173 // round values again to properly handle cases where double precision174 class DefaultBoolCodec : public TypedFixedFieldCodec<bool>
174 // leads to slightly off values (e.g. 2.099999999 instead of 2.1)175 {
175 wire_value = dccl::round(wire_value + (WireType)min(),176 private:
176 precision()); 177 Bitset encode(const bool& wire_value);
177178 Bitset encode();
178 return wire_value;179 bool decode(Bitset* bits);
179 }180 unsigned size();
180181 void validate();
181 unsigned size()182 };
182 {183
183 // if not required field, leave one value for unspecified (always encoded as 0)184 /// \brief Provides an variable length ASCII string encoder. Can encode strings up to 255 bytes by using a length byte preceeding the string.
184 const unsigned NULL_VALUE = FieldCodecBase::this_field()->is_required() ? 0 : 1;185 ///
185 186 /// [length of following string (1 byte)][string (0-255 bytes)]
186 return dccl::ceil_log2((max()-min())*std::pow(10.0, precision())+1 + NULL_VALUE);187 class DefaultStringCodec : public TypedFieldCodec<std::string>
187 }188 {
188 189 private:
189 };190 Bitset encode();
190191 Bitset encode(const std::string& wire_value);
191 /// \brief Provides a bool encoder. Uses 1 bit if field is `required`, 2 bits if `optional`192 std::string decode(Bitset* bits);
192 ///193 unsigned size();
193 /// [presence bit (0 bits if required, 1 bit if optional)][value (1 bit)]194 unsigned size(const std::string& wire_value);
194 class DefaultBoolCodec : public TypedFixedFieldCodec<bool>195 unsigned max_size();
195 {196 unsigned min_size();
196 private:197 void validate();
197 Bitset encode(const bool& wire_value);198 private:
198 Bitset encode();199 enum { MAX_STRING_LENGTH = 255 };
199 bool decode(Bitset* bits);200
200 unsigned size();201 };
201 void validate();202
202 };203
203 204 /// \brief Provides an fixed length byte string encoder.
204 /// \brief Provides an variable length ASCII string encoder. Can encode strings up to 255 bytes by using a length byte preceeding the string.205 class DefaultBytesCodec : public TypedFieldCodec<std::string>
205 ///206 {
206 /// [length of following string (1 byte)][string (0-255 bytes)]207 private:
207 class DefaultStringCodec : public TypedFieldCodec<std::string>208 Bitset encode();
208 {209 Bitset encode(const std::string& wire_value);
209 private:210 std::string decode(Bitset* bits);
210 Bitset encode();211 unsigned size();
211 Bitset encode(const std::string& wire_value);212 unsigned size(const std::string& wire_value);
212 std::string decode(Bitset* bits);213 unsigned max_size();
213 unsigned size();214 unsigned min_size();
214 unsigned size(const std::string& wire_value);215 void validate();
215 unsigned max_size();216 };
216 unsigned min_size();217
217 void validate();218 /// \brief Provides an enum encoder. This converts the enumeration to an integer (based on the enumeration <i>index</i> (<b>not</b> its <i>value</i>) and uses DefaultNumericFieldCodec to encode the integer.
218 private:219 class DefaultEnumCodec
219 enum { MAX_STRING_LENGTH = 255 };220 : public DefaultNumericFieldCodec<int32, const google::protobuf::EnumValueDescriptor*>
220 221 {
221 };222 public:
222223 int32 pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value);
223224 const google::protobuf::EnumValueDescriptor* post_decode(const int32& wire_value);
224 /// \brief Provides an fixed length byte string encoder. 225
225 class DefaultBytesCodec : public TypedFieldCodec<std::string>226 private:
226 {227 void validate() { }
227 private:228
228 Bitset encode();229 double max()
229 Bitset encode(const std::string& wire_value);230 {
230 std::string decode(Bitset* bits);231 const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
231 unsigned size();232 return e->value_count()-1;
232 unsigned size(const std::string& wire_value);233 }
233 unsigned max_size();234 double min()
234 unsigned min_size();235 { return 0; }
235 void validate();236 };
236 };237
237238
238 /// \brief Provides an enum encoder. This converts the enumeration to an integer (based on the enumeration <i>index</i> (<b>not</b> its <i>value</i>) and uses DefaultNumericFieldCodec to encode the integer.239 /// \brief Encodes time of day (default: second precision, but can be set with (dccl.field).precision extension)
239 class DefaultEnumCodec240 ///
240 : public DefaultNumericFieldCodec<int32, const google::protobuf::EnumValueDescriptor*>241 /// \tparam TimeType A type representing time: See the various specializations of this class for allowed types.
241 {242
242 public:243 typedef double time_wire_type;
243 int32 pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value);244 template<typename TimeType, int conversion_factor>
244 const google::protobuf::EnumValueDescriptor* post_decode(const int32& wire_value);245 class TimeCodecBase : public DefaultNumericFieldCodec<time_wire_type, TimeType>
245246 {
246 private:247 public:
247 void validate() { }248 time_wire_type pre_encode(const TimeType& time_of_day) {
248 249 time_wire_type max_secs = max();
249 double max()250 return std::fmod(time_of_day / static_cast<time_wire_type>(conversion_factor), max_secs);
250 {251 }
251 const google::protobuf::EnumDescriptor* e = this_field()->enum_type();252
252 return e->value_count()-1;253 TimeType post_decode(const time_wire_type& encoded_time) {
253 }254
254 double min()255 int64 max_secs = (int64)max();
255 { return 0; }256 timeval t;
256 };257 gettimeofday(&t, 0);
257 258 int64 now = t.tv_sec;
258 259 int64 daystart = now - (now % max_secs);
259 /// \brief Encodes time of day (default: second precision, but can be set with (dccl.field).precision extension) 260 int64 today_time = now - daystart;
260 ///261
261 /// \tparam TimeType A type representing time: See the various specializations of this class for allowed types.262 // If time is more than 12 hours ahead of now, assume it's yesterday.
262263 if ((encoded_time - today_time) > (max_secs/2)) {
263 typedef double time_wire_type;264 daystart -= max_secs;
264 template<typename TimeType, int conversion_factor>265 } else if ((today_time - encoded_time) > (max_secs/2)) {
265 class TimeCodecBase : public DefaultNumericFieldCodec<time_wire_type, TimeType>266 daystart += max_secs;
266 {267 }
267 public:268
268 time_wire_type pre_encode(const TimeType& time_of_day) {269 return (TimeType)(conversion_factor * (daystart + encoded_time));
269 time_wire_type max_secs = max();270 }
270 return std::fmod(time_of_day / static_cast<time_wire_type>(conversion_factor), max_secs);271
271 }272 private:
272273 void validate()
273 TimeType post_decode(const time_wire_type& encoded_time) {274 {
274275 DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds();
275 int64 max_secs = (int64)max();276 }
276 timeval t;277
277 gettimeofday(&t, 0);278 double max() {
278 int64 now = t.tv_sec;279 return FieldCodecBase::dccl_field_options().num_days() * SECONDS_IN_DAY;
279 int64 daystart = now - (now % max_secs);280 }
280 int64 today_time = now - daystart;281
281282 double min() { return 0; }
282 // If time is more than 12 hours ahead of now, assume it's yesterday.283 double precision()
283 if ((encoded_time - today_time) > (max_secs/2)) {284 {
284 daystart -= max_secs;285 if(!FieldCodecBase::dccl_field_options().has_precision())
285 } else if ((today_time - encoded_time) > (max_secs/2)) {286 return 0; // default to second precision
286 daystart += max_secs;287 else
287 }288 {
288289 return FieldCodecBase::dccl_field_options().precision() + (double)std::log10((double)conversion_factor);
289 return (TimeType)(conversion_factor * (daystart + encoded_time));290 }
290 }291
291292 }
292 private:293
293 void validate()294
294 {295 private:
295 DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds();296 enum { SECONDS_IN_DAY = 86400 };
296 }297 };
297298
298 double max() { 299 template<typename TimeType>
299 return FieldCodecBase::dccl_field_options().num_days() * SECONDS_IN_DAY;300 class TimeCodec : public TimeCodecBase<TimeType, 0>
300 }301 { BOOST_STATIC_ASSERT(sizeof(TimeCodec) == 0); };
301302
302 double min() { return 0; }303 template<> class TimeCodec<uint64> : public TimeCodecBase<uint64, 1000000> { };
303 double precision() 304 template<> class TimeCodec<int64> : public TimeCodecBase<int64, 1000000> { };
304 {305 template<> class TimeCodec<double> : public TimeCodecBase<double, 1> { };
305 if(!FieldCodecBase::dccl_field_options().has_precision())306
306 return 0; // default to second precision307
307 else308 /// \brief Placeholder codec that takes no space on the wire (0 bits).
308 {309 template<typename T>
309 return FieldCodecBase::dccl_field_options().precision() + (double)std::log10((double)conversion_factor);310 class StaticCodec : public TypedFixedFieldCodec<T>
310 }311 {
311 312 Bitset encode(const T&)
312 }313 { return Bitset(size()); }
313 314
314315 Bitset encode()
315 private:316 { return Bitset(size()); }
316 enum { SECONDS_IN_DAY = 86400 };317
317 };318 T decode(Bitset* bits)
318 319 {
319 template<typename TimeType>320 return boost::lexical_cast<T>(
320 class TimeCodec : public TimeCodecBase<TimeType, 0>321 FieldCodecBase::dccl_field_options().static_value());
321 { BOOST_STATIC_ASSERT(sizeof(TimeCodec) == 0); };322 }
322 323
323 template<> class TimeCodec<uint64> : public TimeCodecBase<uint64, 1000000> { };324 unsigned size()
324 template<> class TimeCodec<int64> : public TimeCodecBase<int64, 1000000> { };325 { return 0; }
325 template<> class TimeCodec<double> : public TimeCodecBase<double, 1> { };326
326 327 void validate()
327 328 {
328 /// \brief Placeholder codec that takes no space on the wire (0 bits).329 FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_static_value(), "missing (dccl.field).static_value");
329 template<typename T>330
330 class StaticCodec : public TypedFixedFieldCodec<T>331 std::string t = FieldCodecBase::dccl_field_options().static_value();
331 {332 try
332 Bitset encode(const T&)333 {
333 { return Bitset(size()); }334 boost::lexical_cast<T>(t);
334335 }
335 Bitset encode()336 catch(boost::bad_lexical_cast&)
336 { return Bitset(size()); }337 {
337338 FieldCodecBase::require(false, "invalid static_value for this type.");
338 T decode(Bitset* bits)339 }
339 {340 }
340 return boost::lexical_cast<T>(341
341 FieldCodecBase::dccl_field_options().static_value());342 };
342 }343 }
343
344 unsigned size()
345 { return 0; }
346
347 void validate()
348 {
349 FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_static_value(), "missing (dccl.field).static_value");
350
351 std::string t = FieldCodecBase::dccl_field_options().static_value();
352 try
353 {
354 boost::lexical_cast<T>(t);
355 }
356 catch(boost::bad_lexical_cast&)
357 {
358 FieldCodecBase::require(false, "invalid static_value for this type.");
359 }
360 }
361
362 };
363
364}344}
365345
366346
367347
=== renamed file 'src/field_codec_default_message.cpp' => 'src/codecs2/field_codec_default_message.cpp'
--- src/field_codec_default_message.cpp 2014-04-22 20:10:37 +0000
+++ src/codecs2/field_codec_default_message.cpp 2014-08-27 16:27:22 +0000
@@ -30,17 +30,17 @@
30// DefaultMessageCodec30// DefaultMessageCodec
31//31//
3232
33void dccl::DefaultMessageCodec::any_encode(Bitset* bits, const boost::any& wire_value)33void dccl::v2::DefaultMessageCodec::any_encode(Bitset* bits, const boost::any& wire_value)
34{34{
35 if(wire_value.empty())35 if(wire_value.empty())
36 *bits = Bitset(min_size());36 *bits = Bitset(min_size());
37 else37 else
38 *bits = traverse_const_message<Encoder, Bitset>(wire_value);38 *bits = traverse_const_message<Encoder, Bitset>(wire_value);
39}39}
40 40
4141
42 42
43unsigned dccl::DefaultMessageCodec::any_size(const boost::any& wire_value)43unsigned dccl::v2::DefaultMessageCodec::any_size(const boost::any& wire_value)
44{44{
45 if(wire_value.empty())45 if(wire_value.empty())
46 return min_size();46 return min_size();
@@ -49,7 +49,7 @@
49}49}
5050
5151
52void dccl::DefaultMessageCodec::any_decode(Bitset* bits, boost::any* wire_value)52void dccl::v2::DefaultMessageCodec::any_decode(Bitset* bits, boost::any* wire_value)
53{53{
54 try54 try
55 {55 {
@@ -67,8 +67,8 @@
67 if(!check_field(field_desc))67 if(!check_field(field_desc))
68 continue;68 continue;
6969
70 boost::shared_ptr<FieldCodecBase> codec =70
71 FieldCodecManager::find(field_desc);71 boost::shared_ptr<FieldCodecBase> codec = find(field_desc);
72 boost::shared_ptr<FromProtoCppTypeBase> helper =72 boost::shared_ptr<FromProtoCppTypeBase> helper =
73 TypeHelper::find(field_desc);73 TypeHelper::find(field_desc);
7474
@@ -127,14 +127,14 @@
127}127}
128128
129129
130unsigned dccl::DefaultMessageCodec::max_size()130unsigned dccl::v2::DefaultMessageCodec::max_size()
131{131{
132 unsigned u = 0;132 unsigned u = 0;
133 traverse_descriptor<MaxSize>(&u);133 traverse_descriptor<MaxSize>(&u);
134 return u;134 return u;
135}135}
136136
137unsigned dccl::DefaultMessageCodec::min_size()137unsigned dccl::v2::DefaultMessageCodec::min_size()
138{138{
139 unsigned u = 0;139 unsigned u = 0;
140 traverse_descriptor<MinSize>(&u);140 traverse_descriptor<MinSize>(&u);
@@ -142,20 +142,20 @@
142}142}
143143
144144
145void dccl::DefaultMessageCodec::validate()145void dccl::v2::DefaultMessageCodec::validate()
146{146{
147 bool b = false;147 bool b = false;
148 traverse_descriptor<Validate>(&b);148 traverse_descriptor<Validate>(&b);
149}149}
150150
151std::string dccl::DefaultMessageCodec::info()151std::string dccl::v2::DefaultMessageCodec::info()
152{152{
153 std::stringstream ss;153 std::stringstream ss;
154 traverse_descriptor<Info>(&ss);154 traverse_descriptor<Info>(&ss);
155 return ss.str();155 return ss.str();
156}156}
157157
158bool dccl::DefaultMessageCodec::check_field(const google::protobuf::FieldDescriptor* field)158bool dccl::v2::DefaultMessageCodec::check_field(const google::protobuf::FieldDescriptor* field)
159{159{
160 if(!field)160 if(!field)
161 {161 {
@@ -171,7 +171,7 @@
171 else if(MessageStack::current_part() == MessageStack::UNKNOWN) // part not yet explicitly specified171 else if(MessageStack::current_part() == MessageStack::UNKNOWN) // part not yet explicitly specified
172 {172 {
173 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&173 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
174 FieldCodecManager::find(field)->name() == Codec::default_codec_name()) // default message codec will expand174 find(field)->name() == Codec::default_codec_name()) // default message codec will expand
175 return true;175 return true;
176 else if((part() == MessageStack::HEAD && !dccl_field_options.in_head())176 else if((part() == MessageStack::HEAD && !dccl_field_options.in_head())
177 || (part() == MessageStack::BODY && dccl_field_options.in_head()))177 || (part() == MessageStack::BODY && dccl_field_options.in_head()))
178178
=== renamed file 'src/field_codec_default_message.h' => 'src/codecs2/field_codec_default_message.h'
--- src/field_codec_default_message.h 2014-04-22 20:10:37 +0000
+++ src/codecs2/field_codec_default_message.h 2014-08-27 16:27:22 +0000
@@ -24,225 +24,183 @@
24#ifndef DCCLFIELDCODECDEFAULTMESSAGE20110510H24#ifndef DCCLFIELDCODECDEFAULTMESSAGE20110510H
25#define DCCLFIELDCODECDEFAULTMESSAGE20110510H25#define DCCLFIELDCODECDEFAULTMESSAGE20110510H
2626
27#include "field_codec.h"27#include "dccl/field_codec.h"
28#include "field_codec_manager.h"28#include "dccl/field_codec_manager.h"
2929
30#include "dccl/protobuf/option_extensions.pb.h"30#include "dccl/protobuf/option_extensions.pb.h"
3131
32namespace dccl32namespace dccl
33{33{
34 /// \brief Provides the default codec for encoding a base Google Protobuf message or an embedded message by calling the appropriate field codecs for every field.34 namespace v2
35 class DefaultMessageCodec : public FieldCodecBase
36 {35 {
37 private:36 /// \brief Provides the default codec for encoding a base Google Protobuf message or an embedded message by calling the appropriate field codecs for every field.
38 37 class DefaultMessageCodec : public FieldCodecBase
39 void any_encode(Bitset* bits, const boost::any& wire_value);38 {
40 void any_decode(Bitset* bits, boost::any* wire_value); 39 private:
41 unsigned max_size();40
42 unsigned min_size();41 void any_encode(Bitset* bits, const boost::any& wire_value);
43 unsigned any_size(const boost::any& wire_value);42 void any_decode(Bitset* bits, boost::any* wire_value);
4443 unsigned max_size();
45 44 unsigned min_size();
46 void validate();45 unsigned any_size(const boost::any& wire_value);
47 std::string info();46
48 bool check_field(const google::protobuf::FieldDescriptor* field);47
4948 boost::shared_ptr<FieldCodecBase> find(const google::protobuf::FieldDescriptor* field_desc)
50 struct Size49 {
51 {50 return FieldCodecManager::find(field_desc, has_codec_group(), codec_group());
52 static void repeated(boost::shared_ptr<FieldCodecBase> codec,51 }
53 unsigned* return_value,52
54 const std::vector<boost::any>& field_values,53
55 const google::protobuf::FieldDescriptor* field_desc)54 void validate();
56 {55 std::string info();
57 codec->field_size_repeated(return_value, field_values, field_desc);56 bool check_field(const google::protobuf::FieldDescriptor* field);
58 }57
59 58 struct Size
60 static void single(boost::shared_ptr<FieldCodecBase> codec,59 {
61 unsigned* return_value,60 static void repeated(boost::shared_ptr<FieldCodecBase> codec,
62 const boost::any& field_value,61 unsigned* return_value,
63 const google::protobuf::FieldDescriptor* field_desc)62 const std::vector<boost::any>& field_values,
64 {63 const google::protobuf::FieldDescriptor* field_desc)
65 codec->field_size(return_value, field_value, field_desc);64 {
66 }65 codec->field_size_repeated(return_value, field_values, field_desc);
67 66 }
68 };67
69 68 static void single(boost::shared_ptr<FieldCodecBase> codec,
70 struct Encoder69 unsigned* return_value,
71 {70 const boost::any& field_value,
72 static void repeated(boost::shared_ptr<FieldCodecBase> codec,71 const google::protobuf::FieldDescriptor* field_desc)
73 Bitset* return_value,72 {
74 const std::vector<boost::any>& field_values,73 codec->field_size(return_value, field_value, field_desc);
75 const google::protobuf::FieldDescriptor* field_desc)74 }
76 {75
77 codec->field_encode_repeated(return_value, field_values, field_desc);76 };
78 }77
79 78 struct Encoder
80 static void single(boost::shared_ptr<FieldCodecBase> codec,79 {
81 Bitset* return_value,80 static void repeated(boost::shared_ptr<FieldCodecBase> codec,
82 const boost::any& field_value,81 Bitset* return_value,
83 const google::protobuf::FieldDescriptor* field_desc)82 const std::vector<boost::any>& field_values,
84 {83 const google::protobuf::FieldDescriptor* field_desc)
85 codec->field_encode(return_value, field_value, field_desc);84 {
86 }85 codec->field_encode_repeated(return_value, field_values, field_desc);
87 };86 }
8887
89 struct MaxSize88 static void single(boost::shared_ptr<FieldCodecBase> codec,
90 {89 Bitset* return_value,
91 static void field(boost::shared_ptr<FieldCodecBase> codec,90 const boost::any& field_value,
92 unsigned* return_value,91 const google::protobuf::FieldDescriptor* field_desc)
93 const google::protobuf::FieldDescriptor* field_desc)92 {
94 {93 codec->field_encode(return_value, field_value, field_desc);
95 codec->field_max_size(return_value, field_desc);94 }
96 }95 };
97 };96
9897 struct MaxSize
99 struct MinSize98 {
100 {99 static void field(boost::shared_ptr<FieldCodecBase> codec,
101 static void field(boost::shared_ptr<FieldCodecBase> codec,100 unsigned* return_value,
102 unsigned* return_value,101 const google::protobuf::FieldDescriptor* field_desc)
103 const google::protobuf::FieldDescriptor* field_desc)102 {
104 {103 codec->field_max_size(return_value, field_desc);
105 codec->field_min_size(return_value, field_desc);104 }
106 }105 };
107 };106
108 107 struct MinSize
109 108 {
110 struct Validate109 static void field(boost::shared_ptr<FieldCodecBase> codec,
111 {110 unsigned* return_value,
112 static void field(boost::shared_ptr<FieldCodecBase> codec,111 const google::protobuf::FieldDescriptor* field_desc)
113 bool* return_value,112 {
114 const google::protobuf::FieldDescriptor* field_desc)113 codec->field_min_size(return_value, field_desc);
115 {114 }
116 codec->field_validate(return_value, field_desc);115 };
117 }116
118 };117
119118 struct Validate
120 struct Info119 {
121 {120 static void field(boost::shared_ptr<FieldCodecBase> codec,
122 static void field(boost::shared_ptr<FieldCodecBase> codec,121 bool* return_value,
123 std::stringstream* return_value,122 const google::protobuf::FieldDescriptor* field_desc)
124 const google::protobuf::FieldDescriptor* field_desc)123 {
125 {124 codec->field_validate(return_value, field_desc);
126 codec->field_info(return_value, field_desc);125 }
127 }126 };
128 };127
129 128 struct Info
130 129 {
131 template<typename Action, typename ReturnType>130 static void field(boost::shared_ptr<FieldCodecBase> codec,
132 void traverse_descriptor(ReturnType* return_value)131 std::stringstream* return_value,
133 {132 const google::protobuf::FieldDescriptor* field_desc)
134 const google::protobuf::Descriptor* desc =133 {
135 FieldCodecBase::this_descriptor();134 codec->field_info(return_value, field_desc);
136 for(int i = 0, n = desc->field_count(); i < n; ++i)135 }
137 {136 };
138 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);137
138
139 template<typename Action, typename ReturnType>
140 void traverse_descriptor(ReturnType* return_value)
141 {
142 const google::protobuf::Descriptor* desc =
143 FieldCodecBase::this_descriptor();
144 for(int i = 0, n = desc->field_count(); i < n; ++i)
145 {
146 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
139 147
140 if(!check_field(field_desc))148 if(!check_field(field_desc))
141 continue;149 continue;
142150
143 Action::field(FieldCodecManager::find(field_desc),151 Action::field(find(field_desc), return_value, field_desc);
144 return_value, field_desc); 152 }
145 }153 }
146 }
147 154
148155
149 template<typename Action, typename ReturnType>156 template<typename Action, typename ReturnType>
150 ReturnType traverse_const_message(const boost::any& wire_value)157 ReturnType traverse_const_message(const boost::any& wire_value)
151 {
152 try
153 {158 {
154 ReturnType return_value = ReturnType();159 try
160 {
161 ReturnType return_value = ReturnType();
155 162
156 const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value);163 const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value);
157 const google::protobuf::Descriptor* desc = msg->GetDescriptor();164 const google::protobuf::Descriptor* desc = msg->GetDescriptor();
158 const google::protobuf::Reflection* refl = msg->GetReflection();165 const google::protobuf::Reflection* refl = msg->GetReflection();
159 for(int i = 0, n = desc->field_count(); i < n; ++i)166 for(int i = 0, n = desc->field_count(); i < n; ++i)
160 { 167 {
161 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);168 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
162169
163 if(!check_field(field_desc))170 if(!check_field(field_desc))
164 continue;171 continue;
165 172
166 boost::shared_ptr<FieldCodecBase> codec =173 boost::shared_ptr<FieldCodecBase> codec = find(field_desc);
167 FieldCodecManager::find(field_desc);174 boost::shared_ptr<FromProtoCppTypeBase> helper =
168 boost::shared_ptr<FromProtoCppTypeBase> helper =175 TypeHelper::find(field_desc);
169 TypeHelper::find(field_desc);176
170 177
171 178 if(field_desc->is_repeated())
172 if(field_desc->is_repeated())179 {
173 {180 std::vector<boost::any> field_values;
174 std::vector<boost::any> field_values;181 for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
175 for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)182 field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
176 field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
177 183
178 Action::repeated(codec, &return_value, field_values, field_desc);184 Action::repeated(codec, &return_value, field_values, field_desc);
179 }185 }
180 else186 else
181 {187 {
182 Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc);188 Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc);
183 }189 }
184 }190 }
185 return return_value;191 return return_value;
186 }192 }
187 catch(boost::bad_any_cast& e)193 catch(boost::bad_any_cast& e)
188 {194 {
189 throw(Exception("Bad type given to traverse const, expecting const google::protobuf::Message*, got " + std::string(wire_value.type().name())));195 throw(Exception("Bad type given to traverse const, expecting const google::protobuf::Message*, got " + std::string(wire_value.type().name())));
190 }196 }
191 197
192 }198 }
193199 };
194 template<typename Action, typename ReturnType>200
195 ReturnType traverse_mutable_message(const boost::any& wire_value)201 }
196 {
197 try
198 {
199 ReturnType return_value = ReturnType();
200
201 const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value);
202 const google::protobuf::Descriptor* desc = msg->GetDescriptor();
203 const google::protobuf::Reflection* refl = msg->GetReflection();
204 for(int i = 0, n = desc->field_count(); i < n; ++i)
205 {
206 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
207
208 if(!check_field(field_desc))
209 continue;
210
211 boost::shared_ptr<FieldCodecBase> codec =
212 FieldCodecManager::find(field_desc);
213 boost::shared_ptr<FromProtoCppTypeBase> helper =
214 TypeHelper::find(field_desc);
215
216
217 if(field_desc->is_repeated())
218 {
219 std::vector<boost::any> field_values;
220 for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
221 field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
222
223 Action::repeated(codec, &return_value, field_values, field_desc);
224 }
225 else
226 {
227 Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc);
228 }
229 }
230 return return_value;
231 }
232 catch(boost::bad_any_cast& e)
233 {
234 throw(Exception("Bad type given to traverse, expecting const google::protobuf::Message*"));
235 }
236
237 }
238
239
240
241 };
242
243}202}
244203
245
246//encode, size, etc.204//encode, size, etc.
247205
248206
249207
=== added directory 'src/codecs3'
=== added file 'src/codecs3/field_codec_default.cpp'
--- src/codecs3/field_codec_default.cpp 1970-01-01 00:00:00 +0000
+++ src/codecs3/field_codec_default.cpp 2014-08-27 16:27:22 +0000
@@ -0,0 +1,122 @@
1// Copyright 2009-2014 Toby Schneider (https://launchpad.net/~tes)
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6// This file is part of the Dynamic Compact Control Language Library
7// ("DCCL").
8//
9// DCCL is free software: you can redistribute them and/or modify
10// them under the terms of the GNU Lesser General Public License as published by
11// the Free Software Foundation, either version 2.1 of the License, or
12// (at your option) any later version.
13//
14// DCCL is distributed in the hope that they will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public License
20// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
21
22#include "dccl/codecs3/field_codec_default.h"
23
24using namespace dccl::logger;
25
26//
27// DefaultStringCodec
28//
29
30dccl::Bitset dccl::v3::DefaultStringCodec::encode()
31{
32 return Bitset(min_size());
33}
34
35dccl::Bitset dccl::v3::DefaultStringCodec::encode(const std::string& wire_value)
36{
37 std::string s = wire_value;
38 if(s.size() > dccl_field_options().max_length())
39 {
40 dccl::dlog.is(DEBUG2) && dccl::dlog << "String " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
41 s.resize(dccl_field_options().max_length());
42 }
43
44
45 Bitset value_bits;
46 value_bits.from_byte_string(s);
47
48 Bitset length_bits(min_size(), s.length());
49
50 dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec value_bits: " << value_bits << std::endl;
51
52
53 dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec length_bits: " << length_bits << std::endl;
54
55 // adds to MSBs
56 for(int i = 0, n = value_bits.size(); i < n; ++i)
57 length_bits.push_back(value_bits[i]);
58
59 dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec created: " << length_bits << std::endl;
60
61
62 return length_bits;
63}
64
65std::string dccl::v3::DefaultStringCodec::decode(Bitset* bits)
66{
67 unsigned value_length = bits->to_ulong();
68
69 if(value_length)
70 {
71
72 unsigned header_length = min_size();
73
74 dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl;
75
76 dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
77
78 // grabs more bits to add to the MSBs of `bits`
79 bits->get_more_bits(value_length*BITS_IN_BYTE);
80
81
82 dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
83 Bitset string_body_bits = *bits;
84 string_body_bits >>= header_length;
85 string_body_bits.resize(bits->size() - header_length);
86
87 return string_body_bits.to_byte_string();
88 }
89 else
90 {
91 throw NullValueException();
92 }
93
94}
95
96unsigned dccl::v3::DefaultStringCodec::size()
97{
98 return min_size();
99}
100
101unsigned dccl::v3::DefaultStringCodec::size(const std::string& wire_value)
102{
103 return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size());
104}
105
106
107unsigned dccl::v3::DefaultStringCodec::max_size()
108{
109 // string length + actual string
110 return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;
111}
112
113unsigned dccl::v3::DefaultStringCodec::min_size()
114{
115 return dccl::ceil_log2(dccl_field_options().max_length()+1);
116}
117
118
119void dccl::v3::DefaultStringCodec::validate()
120{
121 require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
122}
0123
=== added file 'src/codecs3/field_codec_default.h'
--- src/codecs3/field_codec_default.h 1970-01-01 00:00:00 +0000
+++ src/codecs3/field_codec_default.h 2014-08-27 16:27:22 +0000
@@ -0,0 +1,77 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23
24
25// implements FieldCodecBase for all the basic DCCL types for version 3
26
27#ifndef DCCLV3FIELDCODECDEFAULT20140403H
28#define DCCLV3FIELDCODECDEFAULT20140403H
29
30#include "dccl/codecs2/field_codec_default.h"
31
32namespace dccl
33{
34 namespace v3
35 {
36 // all these are the same as version 2
37 template<typename WireType, typename FieldType = WireType>
38 class DefaultNumericFieldCodec : public v2::DefaultNumericFieldCodec<WireType, FieldType> { };
39
40 typedef v2::DefaultBoolCodec DefaultBoolCodec;
41 typedef v2::DefaultBytesCodec DefaultBytesCodec;
42 typedef v2::DefaultEnumCodec DefaultEnumCodec;
43
44
45 template<typename TimeType>
46 class TimeCodec : public v2::TimeCodecBase<TimeType, 0>
47 { BOOST_STATIC_ASSERT(sizeof(TimeCodec) == 0); };
48
49 template<> class TimeCodec<uint64> : public v2::TimeCodecBase<uint64, 1000000> { };
50 template<> class TimeCodec<int64> : public v2::TimeCodecBase<int64, 1000000> { };
51 template<> class TimeCodec<double> : public v2::TimeCodecBase<double, 1> { };
52
53 template<typename T>
54 class StaticCodec : public v2::StaticCodec<T>
55 { };
56
57
58 /// \brief Provides an variable length ASCII string encoder.
59 ///
60 /// [length of following string size: ceil(log2(max_length))][string]
61 class DefaultStringCodec : public TypedFieldCodec<std::string>
62 {
63 private:
64 Bitset encode();
65 Bitset encode(const std::string& wire_value);
66 std::string decode(Bitset* bits);
67 unsigned size();
68 unsigned size(const std::string& wire_value);
69 unsigned max_size();
70 unsigned min_size();
71 void validate();
72 };
73
74 }
75}
76
77#endif
078
=== added file 'src/codecs3/field_codec_default_message.cpp'
--- src/codecs3/field_codec_default_message.cpp 1970-01-01 00:00:00 +0000
+++ src/codecs3/field_codec_default_message.cpp 2014-08-27 16:27:22 +0000
@@ -0,0 +1,236 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23
24
25#include "dccl/codec.h"
26#include "dccl/codecs3/field_codec_default_message.h"
27
28using dccl::dlog;
29
30//
31// DefaultMessageCodec
32//
33
34void dccl::v3::DefaultMessageCodec::any_encode(Bitset* bits, const boost::any& wire_value)
35{
36 if(wire_value.empty())
37 {
38 *bits = Bitset(min_size());
39 }
40 else
41 {
42 *bits = traverse_const_message<Encoder, Bitset>(wire_value);
43
44 if(is_optional())
45 bits->push_front(true); // presence bit
46
47 }
48}
49
50
51
52unsigned dccl::v3::DefaultMessageCodec::any_size(const boost::any& wire_value)
53{
54 if(wire_value.empty())
55 {
56 return min_size();
57 }
58 else
59 {
60 unsigned size = traverse_const_message<Size, unsigned>(wire_value);
61 if(is_optional())
62 {
63 const unsigned presence_bit = 1;
64 size += presence_bit;
65 }
66
67 return size;
68 }
69}
70
71
72void dccl::v3::DefaultMessageCodec::any_decode(Bitset* bits, boost::any* wire_value)
73{
74 try
75 {
76
77 google::protobuf::Message* msg = boost::any_cast<google::protobuf::Message* >(*wire_value);
78
79 if(is_optional())
80 {
81 if(!bits->to_ulong())
82 {
83 *wire_value = boost::any();
84 return;
85 }
86 else
87 {
88 bits->pop_front(); // presence bit
89 }
90 }
91
92 const google::protobuf::Descriptor* desc = msg->GetDescriptor();
93 const google::protobuf::Reflection* refl = msg->GetReflection();
94
95 for(int i = 0, n = desc->field_count(); i < n; ++i)
96 {
97
98 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
99
100 if(!check_field(field_desc))
101 continue;
102
103
104 boost::shared_ptr<FieldCodecBase> codec = find(field_desc);
105 boost::shared_ptr<FromProtoCppTypeBase> helper =
106 TypeHelper::find(field_desc);
107
108 if(field_desc->is_repeated())
109 {
110 std::vector<boost::any> field_values;
111 if(field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
112 {
113 unsigned max_repeat = field_desc->options().GetExtension(dccl::field).max_repeat();
114 for(unsigned j = 0, m = max_repeat; j < m; ++j)
115 field_values.push_back(refl->AddMessage(msg, field_desc));
116
117 codec->field_decode_repeated(bits, &field_values, field_desc);
118
119 // remove the unused messages
120 for(int j = field_values.size(), m = max_repeat; j < m; ++j)
121 {
122 refl->RemoveLast(msg, field_desc);
123 }
124 }
125 else
126 {
127 // for primitive types
128 codec->field_decode_repeated(bits, &field_values, field_desc);
129 for(int j = 0, m = field_values.size(); j < m; ++j)
130 helper->add_value(field_desc, msg, field_values[j]);
131 }
132 }
133 else
134 {
135 boost::any field_value;
136 if(field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
137 {
138 // allows us to propagate pointers instead of making many copies of entire messages
139 field_value = refl->MutableMessage(msg, field_desc);
140 codec->field_decode(bits, &field_value, field_desc);
141 if(field_value.empty()) refl->ClearField(msg, field_desc);
142 }
143 else
144 {
145 // for primitive types
146 codec->field_decode(bits, &field_value, field_desc);
147 helper->set_value(field_desc, msg, field_value);
148 }
149 }
150 }
151
152 std::vector< const google::protobuf::FieldDescriptor* > set_fields;
153 refl->ListFields(*msg, &set_fields);
154 if(set_fields.empty() && this_field()) *wire_value = boost::any();
155 else *wire_value = msg;
156 }
157 catch(boost::bad_any_cast& e)
158 {
159 throw(Exception("Bad type given to traverse mutable, expecting google::protobuf::Message*, got " + std::string(wire_value->type().name())));
160 }
161
162}
163
164
165unsigned dccl::v3::DefaultMessageCodec::max_size()
166{
167 unsigned u = 0;
168 traverse_descriptor<MaxSize>(&u);
169
170 if(is_optional())
171 {
172 const unsigned presence_bit = 1;
173 u += presence_bit;
174 }
175
176 return u;
177}
178
179unsigned dccl::v3::DefaultMessageCodec::min_size()
180{
181 if(is_optional())
182 {
183 const unsigned presence_bit = 1;
184 return presence_bit;
185 }
186 else
187 {
188 unsigned u = 0;
189 traverse_descriptor<MinSize>(&u);
190 return u;
191 }
192}
193
194
195void dccl::v3::DefaultMessageCodec::validate()
196{
197 bool b = false;
198 traverse_descriptor<Validate>(&b);
199}
200
201std::string dccl::v3::DefaultMessageCodec::info()
202{
203 std::stringstream ss;
204 traverse_descriptor<Info>(&ss);
205 return ss.str();
206}
207
208bool dccl::v3::DefaultMessageCodec::check_field(const google::protobuf::FieldDescriptor* field)
209{
210 if(!field)
211 {
212 return true;
213 }
214 else
215 {
216 dccl::DCCLFieldOptions dccl_field_options = field->options().GetExtension(dccl::field);
217 if(dccl_field_options.omit()) // omit
218 {
219 return false;
220 }
221 else if(MessageStack::current_part() == MessageStack::UNKNOWN) // part not yet explicitly specified
222 {
223 if((part() == MessageStack::HEAD && !dccl_field_options.in_head())
224 || (part() == MessageStack::BODY && dccl_field_options.in_head()))
225 return false;
226 else
227 return true;
228 }
229 else if(MessageStack::current_part() != part()) // part specified and doesn't match
230 return false;
231 else
232 return true;
233 }
234}
235
236
0237
=== added file 'src/codecs3/field_codec_default_message.h'
--- src/codecs3/field_codec_default_message.h 1970-01-01 00:00:00 +0000
+++ src/codecs3/field_codec_default_message.h 2014-08-27 16:27:22 +0000
@@ -0,0 +1,213 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23
24
25#ifndef DCCLFIELDCODECDEFAULTMESSAGEV320140421H
26#define DCCLFIELDCODECDEFAULTMESSAGEV320140421H
27
28#include "dccl/field_codec.h"
29#include "dccl/field_codec_manager.h"
30
31#include "dccl/protobuf/option_extensions.pb.h"
32
33namespace dccl
34{
35 namespace v3
36 {
37 /// \brief Provides the default codec for encoding a base Google Protobuf message or an embedded message by calling the appropriate field codecs for every field.
38 class DefaultMessageCodec : public FieldCodecBase
39 {
40 private:
41
42 void any_encode(Bitset* bits, const boost::any& wire_value);
43 void any_decode(Bitset* bits, boost::any* wire_value);
44 unsigned max_size();
45 unsigned min_size();
46 unsigned any_size(const boost::any& wire_value);
47
48
49 boost::shared_ptr<FieldCodecBase> find(const google::protobuf::FieldDescriptor* field_desc)
50 {
51 return FieldCodecManager::find(field_desc, has_codec_group(), codec_group());
52 }
53
54 bool is_optional()
55 { return this_field() && this_field()->is_optional(); }
56
57
58 void validate();
59 std::string info();
60 bool check_field(const google::protobuf::FieldDescriptor* field);
61
62 struct Size
63 {
64 static void repeated(boost::shared_ptr<FieldCodecBase> codec,
65 unsigned* return_value,
66 const std::vector<boost::any>& field_values,
67 const google::protobuf::FieldDescriptor* field_desc)
68 {
69 codec->field_size_repeated(return_value, field_values, field_desc);
70 }
71
72 static void single(boost::shared_ptr<FieldCodecBase> codec,
73 unsigned* return_value,
74 const boost::any& field_value,
75 const google::protobuf::FieldDescriptor* field_desc)
76 {
77 codec->field_size(return_value, field_value, field_desc);
78 }
79
80 };
81
82 struct Encoder
83 {
84 static void repeated(boost::shared_ptr<FieldCodecBase> codec,
85 Bitset* return_value,
86 const std::vector<boost::any>& field_values,
87 const google::protobuf::FieldDescriptor* field_desc)
88 {
89 codec->field_encode_repeated(return_value, field_values, field_desc);
90 }
91
92 static void single(boost::shared_ptr<FieldCodecBase> codec,
93 Bitset* return_value,
94 const boost::any& field_value,
95 const google::protobuf::FieldDescriptor* field_desc)
96 {
97 codec->field_encode(return_value, field_value, field_desc);
98 }
99 };
100
101 struct MaxSize
102 {
103 static void field(boost::shared_ptr<FieldCodecBase> codec,
104 unsigned* return_value,
105 const google::protobuf::FieldDescriptor* field_desc)
106 {
107 codec->field_max_size(return_value, field_desc);
108 }
109 };
110
111 struct MinSize
112 {
113 static void field(boost::shared_ptr<FieldCodecBase> codec,
114 unsigned* return_value,
115 const google::protobuf::FieldDescriptor* field_desc)
116 {
117 codec->field_min_size(return_value, field_desc);
118 }
119 };
120
121
122 struct Validate
123 {
124 static void field(boost::shared_ptr<FieldCodecBase> codec,
125 bool* return_value,
126 const google::protobuf::FieldDescriptor* field_desc)
127 {
128 codec->field_validate(return_value, field_desc);
129 }
130 };
131
132 struct Info
133 {
134 static void field(boost::shared_ptr<FieldCodecBase> codec,
135 std::stringstream* return_value,
136 const google::protobuf::FieldDescriptor* field_desc)
137 {
138 codec->field_info(return_value, field_desc);
139 }
140 };
141
142
143 template<typename Action, typename ReturnType>
144 void traverse_descriptor(ReturnType* return_value)
145 {
146 const google::protobuf::Descriptor* desc =
147 FieldCodecBase::this_descriptor();
148 for(int i = 0, n = desc->field_count(); i < n; ++i)
149 {
150 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
151
152 if(!check_field(field_desc))
153 continue;
154
155 Action::field(find(field_desc), return_value, field_desc);
156 }
157 }
158
159
160 template<typename Action, typename ReturnType>
161 ReturnType traverse_const_message(const boost::any& wire_value)
162 {
163 try
164 {
165 ReturnType return_value = ReturnType();
166
167 const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value);
168 const google::protobuf::Descriptor* desc = msg->GetDescriptor();
169 const google::protobuf::Reflection* refl = msg->GetReflection();
170 for(int i = 0, n = desc->field_count(); i < n; ++i)
171 {
172 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
173
174 if(!check_field(field_desc))
175 continue;
176
177 boost::shared_ptr<FieldCodecBase> codec = find(field_desc);
178 boost::shared_ptr<FromProtoCppTypeBase> helper =
179 TypeHelper::find(field_desc);
180
181
182 if(field_desc->is_repeated())
183 {
184 std::vector<boost::any> field_values;
185 for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
186 field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
187
188 Action::repeated(codec, &return_value, field_values, field_desc);
189 }
190 else
191 {
192 Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc);
193 }
194 }
195 return return_value;
196 }
197 catch(boost::bad_any_cast& e)
198 {
199 throw(Exception("Bad type given to traverse const, expecting const google::protobuf::Message*, got " + std::string(wire_value.type().name())));
200 }
201
202 }
203 };
204
205 }
206}
207
208//encode, size, etc.
209
210
211
212
213#endif
0214
=== modified file 'src/field_codec.cpp'
--- src/field_codec.cpp 2014-04-22 20:10:37 +0000
+++ src/field_codec.cpp 2014-08-27 16:27:22 +0000
@@ -29,6 +29,7 @@
29 dccl::MessageStack::UNKNOWN;29 dccl::MessageStack::UNKNOWN;
3030
31const google::protobuf::Message* dccl::FieldCodecBase::root_message_ = 0;31const google::protobuf::Message* dccl::FieldCodecBase::root_message_ = 0;
32const google::protobuf::Descriptor* dccl::FieldCodecBase::root_descriptor_ = 0;
3233
33using dccl::dlog;34using dccl::dlog;
34using namespace dccl::logger;35using namespace dccl::logger;
@@ -66,6 +67,7 @@
66 67
67 Bitset new_bits;68 Bitset new_bits;
68 any_encode(&new_bits, wire_value);69 any_encode(&new_bits, wire_value);
70 disp_size(field, new_bits, msg_handler.field_.size());
69 bits->append(new_bits);71 bits->append(new_bits);
70}72}
7173
@@ -80,6 +82,7 @@
80 82
81 Bitset new_bits;83 Bitset new_bits;
82 any_encode_repeated(&new_bits, wire_values);84 any_encode_repeated(&new_bits, wire_values);
85 disp_size(field, new_bits, msg_handler.field_.size(), wire_values.size());
83 bits->append(new_bits);86 bits->append(new_bits);
84}87}
8588
@@ -190,7 +193,8 @@
190193
191 std::vector<boost::any> wire_values = *field_values;194 std::vector<boost::any> wire_values = *field_values;
192 any_decode_repeated(&these_bits, &wire_values);195 any_decode_repeated(&these_bits, &wire_values);
193 196
197 field_values->clear();
194 field_post_decode_repeated(wire_values, field_values);198 field_post_decode_repeated(wire_values, field_values);
195}199}
196200
@@ -199,7 +203,7 @@
199 const google::protobuf::Descriptor* desc,203 const google::protobuf::Descriptor* desc,
200 MessageStack::MessagePart part)204 MessageStack::MessagePart part)
201{205{
202 BaseRAII scoped_globals(part);206 BaseRAII scoped_globals(part, desc);
203 *bit_size = 0;207 *bit_size = 0;
204208
205 MessageStack msg_handler;209 MessageStack msg_handler;
@@ -228,7 +232,7 @@
228 const google::protobuf::Descriptor* desc,232 const google::protobuf::Descriptor* desc,
229 MessageStack::MessagePart part)233 MessageStack::MessagePart part)
230{234{
231 BaseRAII scoped_globals(part);235 BaseRAII scoped_globals(part, desc);
232236
233 *bit_size = 0;237 *bit_size = 0;
234238
@@ -257,7 +261,7 @@
257void dccl::FieldCodecBase::base_validate(const google::protobuf::Descriptor* desc,261void dccl::FieldCodecBase::base_validate(const google::protobuf::Descriptor* desc,
258 MessageStack::MessagePart part)262 MessageStack::MessagePart part)
259{263{
260 BaseRAII scoped_globals(part);264 BaseRAII scoped_globals(part, desc);
261265
262 MessageStack msg_handler;266 MessageStack msg_handler;
263 if(desc)267 if(desc)
@@ -283,7 +287,7 @@
283 287
284void dccl::FieldCodecBase::base_info(std::ostream* os, const google::protobuf::Descriptor* desc, MessageStack::MessagePart part)288void dccl::FieldCodecBase::base_info(std::ostream* os, const google::protobuf::Descriptor* desc, MessageStack::MessagePart part)
285{289{
286 BaseRAII scoped_globals(part);290 BaseRAII scoped_globals(part, desc);
287291
288 MessageStack msg_handler;292 MessageStack msg_handler;
289 if(desc)293 if(desc)
@@ -337,7 +341,11 @@
337 }341 }
338342
339 int width = this_field() ? full_width-name.size() : full_width-name.size()+spaces;343 int width = this_field() ? full_width-name.size() : full_width-name.size()+spaces;
340 ss << indent << name << std::setfill('.') << std::setw(std::max(1, width)) << range.str();344 ss << indent << name <<
345 std::setfill('.') << std::setw(std::max(1, width)) << range.str()
346 << " {" << (this_field() ? FieldCodecManager::find(this_field(), has_codec_group(), codec_group())->name() : FieldCodecManager::find(root_descriptor_)->name()) << "}";
347
348
341 349
342// std::string s = ss.str();350// std::string s = ss.str();
343// boost::replace_all(s, "\n", "\n" + indent); 351// boost::replace_all(s, "\n", "\n" + indent);
@@ -353,6 +361,14 @@
353361
354}362}
355363
364std::string dccl::FieldCodecBase::codec_group(const google::protobuf::Descriptor* desc)
365{
366 if(desc->options().GetExtension(dccl::msg).has_codec_group())
367 return desc->options().GetExtension(dccl::msg).codec_group();
368 else
369 return Codec::default_codec_name(desc->options().GetExtension(dccl::msg).codec_version());
370}
371
356372
357//373//
358// FieldCodecBase protected374// FieldCodecBase protected
@@ -366,7 +382,18 @@
366void dccl::FieldCodecBase::any_encode_repeated(dccl::Bitset* bits, const std::vector<boost::any>& wire_values)382void dccl::FieldCodecBase::any_encode_repeated(dccl::Bitset* bits, const std::vector<boost::any>& wire_values)
367{383{
368 // out_bits = [field_values[2]][field_values[1]][field_values[0]]384 // out_bits = [field_values[2]][field_values[1]][field_values[0]]
369 for(unsigned i = 0, n = dccl_field_options().max_repeat(); i < n; ++i)385
386 unsigned wire_vector_size = dccl_field_options().max_repeat();
387
388 // for DCCL3 and beyond, add a prefix numeric field giving the vector size (rather than always going to max_repeat
389 if(codec_version() > 2)
390 {
391 wire_vector_size = std::min((int)dccl_field_options().max_repeat(), (int)wire_values.size());
392 Bitset size_bits(repeated_vector_field_size(dccl_field_options().max_repeat()), wire_values.size());
393 bits->append(size_bits);
394 }
395
396 for(unsigned i = 0, n = wire_vector_size; i < n; ++i)
370 {397 {
371 Bitset new_bits;398 Bitset new_bits;
372 if(i < wire_values.size())399 if(i < wire_values.size())
@@ -379,27 +406,41 @@
379}406}
380407
381408
409
382void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* wire_values)410void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* wire_values)
383{411{
384 for(unsigned i = 0, n = dccl_field_options().max_repeat(); i < n; ++i)412
413 unsigned wire_vector_size = dccl_field_options().max_repeat();
414 if(codec_version() > 2)
415 {
416 Bitset size_bits(repeated_bits);
417 size_bits.get_more_bits(repeated_vector_field_size(dccl_field_options().max_repeat()));
418
419 wire_vector_size = size_bits.to_ulong();
420 }
421
422 wire_values->resize(wire_vector_size);
423
424 for(unsigned i = 0, n = wire_vector_size; i < n; ++i)
385 {425 {
386 Bitset these_bits(repeated_bits); 426 Bitset these_bits(repeated_bits);
387 these_bits.get_more_bits(min_size());427 these_bits.get_more_bits(min_size());
388 428 any_decode(&these_bits, &(*wire_values)[i]);
389 boost::any value;
390
391 if(wire_values->size() > i)
392 value = (*wire_values)[i];
393
394 any_decode(&these_bits, &value);
395 wire_values->push_back(value);
396 }429 }
397}430}
398431
399unsigned dccl::FieldCodecBase::any_size_repeated(const std::vector<boost::any>& wire_values)432unsigned dccl::FieldCodecBase::any_size_repeated(const std::vector<boost::any>& wire_values)
400{433{
401 unsigned out = 0;434 unsigned out = 0;
402 for(unsigned i = 0, n = dccl_field_options().max_repeat(); i < n; ++i)435 unsigned wire_vector_size = dccl_field_options().max_repeat();
436
437 if(codec_version() > 2)
438 {
439 wire_vector_size = std::min((int)dccl_field_options().max_repeat(), (int)wire_values.size());
440 out += repeated_vector_field_size(dccl_field_options().max_repeat());
441 }
442
443 for(unsigned i = 0, n = wire_vector_size; i < n; ++i)
403 {444 {
404 if(i < wire_values.size())445 if(i < wire_values.size())
405 out += any_size(wire_values[i]);446 out += any_size(wire_values[i]);
@@ -413,6 +454,8 @@
413{ 454{
414 if(!dccl_field_options().has_max_repeat())455 if(!dccl_field_options().has_max_repeat())
415 throw(Exception("Missing (dccl.field).max_repeat option on `repeated` field: " + this_field()->DebugString()));456 throw(Exception("Missing (dccl.field).max_repeat option on `repeated` field: " + this_field()->DebugString()));
457 else if(codec_version() > 2)
458 return repeated_vector_field_size(dccl_field_options().max_repeat()) + max_size() * dccl_field_options().max_repeat();
416 else459 else
417 return max_size() * dccl_field_options().max_repeat();460 return max_size() * dccl_field_options().max_repeat();
418}461}
@@ -421,6 +464,8 @@
421{ 464{
422 if(!dccl_field_options().has_max_repeat())465 if(!dccl_field_options().has_max_repeat())
423 throw(Exception("Missing (dccl.field).max_repeat option on `repeated` field " + this_field()->DebugString()));466 throw(Exception("Missing (dccl.field).max_repeat option on `repeated` field " + this_field()->DebugString()));
467 else if(codec_version() > 2)
468 return repeated_vector_field_size(dccl_field_options().max_repeat());
424 else469 else
425 return min_size() * dccl_field_options().max_repeat();470 return min_size() * dccl_field_options().max_repeat();
426}471}
@@ -453,3 +498,22 @@
453// FieldCodecBase private498// FieldCodecBase private
454//499//
455500
501void dccl::FieldCodecBase::disp_size(const google::protobuf::FieldDescriptor* field, const Bitset& new_bits, int depth, int vector_size /* = -1 */)
502{
503 if(!root_descriptor_)
504 return;
505
506 if(dlog.is(INFO, SIZE))
507 {
508 std::string name = ((field) ? field->name() : root_descriptor_->full_name());
509 if(vector_size >= 0)
510 name += "[" + boost::lexical_cast<std::string>(vector_size) + "]";
511
512
513 dlog << std::string(depth, '|') << name << std::setfill('.') << std::setw(40-name.size()-depth) << new_bits.size() << std::endl;
514
515 if(!field)
516 dlog << std::endl;
517
518 }
519}
456520
=== modified file 'src/field_codec.h'
--- src/field_codec.h 2014-04-22 20:10:37 +0000
+++ src/field_codec.h 2014-08-27 16:27:22 +0000
@@ -28,6 +28,7 @@
28#include <string>28#include <string>
2929
30#include <boost/any.hpp>30#include <boost/any.hpp>
31#include <boost/lexical_cast.hpp>
3132
32#include <google/protobuf/message.h>33#include <google/protobuf/message.h>
33#include <google/protobuf/descriptor.pb.h>34#include <google/protobuf/descriptor.pb.h>
@@ -38,6 +39,7 @@
38#include "dccl/protobuf/option_extensions.pb.h"39#include "dccl/protobuf/option_extensions.pb.h"
39#include "type_helper.h"40#include "type_helper.h"
40#include "field_codec_message_stack.h"41#include "field_codec_message_stack.h"
42#include "dccl/binary.h"
4143
42namespace dccl44namespace dccl
43{45{
@@ -94,7 +96,25 @@
94 // currently encoded or (partially) decoded root message96 // currently encoded or (partially) decoded root message
95 static const google::protobuf::Message* root_message()97 static const google::protobuf::Message* root_message()
96 { return root_message_; }98 { return root_message_; }
97 99
100 static bool has_codec_group()
101 {
102 if(root_descriptor_)
103 {
104 return root_descriptor_->options().GetExtension(dccl::msg).has_codec_group() ||
105 root_descriptor_->options().GetExtension(dccl::msg).has_codec_version();
106 }
107 else
108 return false;
109 }
110
111 static std::string codec_group(const google::protobuf::Descriptor* desc);
112
113 static std::string codec_group()
114 { return codec_group(root_descriptor_); }
115
116 static int codec_version()
117 { return root_descriptor_->options().GetExtension(dccl::msg).codec_version(); }
98 118
99 /// \brief the part of the message currently being encoded (head or body).119 /// \brief the part of the message currently being encoded (head or body).
100 static MessageStack::MessagePart part() { return part_; }120 static MessageStack::MessagePart part() { return part_; }
@@ -379,7 +399,6 @@
379 ///399 ///
380 /// \return Minimum size of this field (in bits).400 /// \return Minimum size of this field (in bits).
381 virtual unsigned min_size() = 0;401 virtual unsigned min_size() = 0;
382
383402
384 virtual void any_encode_repeated(Bitset* bits, const std::vector<boost::any>& wire_values);403 virtual void any_encode_repeated(Bitset* bits, const std::vector<boost::any>& wire_values);
385 virtual void any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* field_values);404 virtual void any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* field_values);
@@ -404,29 +423,52 @@
404 void set_wire_type(google::protobuf::FieldDescriptor::CppType type)423 void set_wire_type(google::protobuf::FieldDescriptor::CppType type)
405 { wire_type_ = type; }424 { wire_type_ = type; }
406425
407 bool variable_size() { return max_size() != min_size(); } 426 bool variable_size()
408 427 {
428 if(this_field() && this_field()->is_repeated())
429 return max_size_repeated() != min_size_repeated();
430 else
431 return max_size() != min_size();
432 }
433
434 int repeated_vector_field_size(int max_repeat)
435 { return dccl::ceil_log2(max_repeat+1); }
436
437 void disp_size(const google::protobuf::FieldDescriptor* field, const Bitset& new_bits, int depth, int vector_size = -1);
438
439
409 private:440 private:
410 // sets global statics relating the current message begin processed441 // sets global statics relating the current message begin processed
411 // and unsets them on destruction442 // and unsets them on destruction
412 struct BaseRAII443 struct BaseRAII
413 {444 {
414 BaseRAII(MessageStack::MessagePart part,445 BaseRAII(MessageStack::MessagePart part,
415 const google::protobuf::Message* root_message = 0)446 const google::protobuf::Descriptor* root_descriptor)
447 {
448 FieldCodecBase::part_ = part;
449 FieldCodecBase::root_message_ = 0;
450 FieldCodecBase::root_descriptor_ = root_descriptor;
451 }
452
453 BaseRAII(MessageStack::MessagePart part,
454 const google::protobuf::Message* root_message)
416 {455 {
417 FieldCodecBase::part_ = part;456 FieldCodecBase::part_ = part;
418 FieldCodecBase::root_message_ = root_message;457 FieldCodecBase::root_message_ = root_message;
458 FieldCodecBase::root_descriptor_ = root_message->GetDescriptor();
419 }459 }
420 ~BaseRAII()460 ~BaseRAII()
421 {461 {
422 FieldCodecBase::part_ = dccl::MessageStack::UNKNOWN;462 FieldCodecBase::part_ = dccl::MessageStack::UNKNOWN;
423 FieldCodecBase::root_message_ = 0;463 FieldCodecBase::root_message_ = 0;
464 FieldCodecBase::root_descriptor_ = 0;
424 }465 }
425 };466 };
426 467
427 468
428 static MessageStack::MessagePart part_;469 static MessageStack::MessagePart part_;
429 static const google::protobuf::Message* root_message_;470 static const google::protobuf::Message* root_message_;
471 static const google::protobuf::Descriptor* root_descriptor_;
430 472
431 std::string name_;473 std::string name_;
432 google::protobuf::FieldDescriptor::Type field_type_;474 google::protobuf::FieldDescriptor::Type field_type_;
433475
=== added file 'src/field_codec_id.cpp'
--- src/field_codec_id.cpp 1970-01-01 00:00:00 +0000
+++ src/field_codec_id.cpp 2014-08-27 16:27:22 +0000
@@ -0,0 +1,100 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23#include "field_codec_id.h"
24
25//
26// DefaultIdentifierCodec
27//
28
29dccl::Bitset dccl::DefaultIdentifierCodec::encode()
30{
31 return encode(0);
32}
33
34dccl::Bitset dccl::DefaultIdentifierCodec::encode(const uint32& id)
35{
36 if(id <= ONE_BYTE_MAX_ID)
37 {
38 return(dccl::Bitset(this_size(id), id) << 1);
39 }
40 else
41 {
42 dccl::Bitset return_bits(this_size(id), id);
43 return_bits <<= 1;
44 // set LSB to indicate long header form
45 return_bits.set(0, true);
46
47
48 return return_bits;
49 }
50}
51
52dccl::uint32 dccl::DefaultIdentifierCodec::decode(Bitset* bits)
53{
54 if(bits->test(0))
55 {
56 // long header
57 // grabs more bits to add to the MSB of `bits`
58 bits->get_more_bits((LONG_FORM_ID_BYTES - SHORT_FORM_ID_BYTES)*BITS_IN_BYTE);
59 // discard identifier
60 *(bits) >>= 1;
61 return bits->to_ulong();
62 }
63 else
64 {
65 // short header
66 *(bits) >>= 1;
67 return bits->to_ulong();
68 }
69}
70
71unsigned dccl::DefaultIdentifierCodec::size()
72{
73 return this_size(0);
74}
75
76unsigned dccl::DefaultIdentifierCodec::size(const uint32& id)
77{
78 return this_size(id);
79}
80
81unsigned dccl::DefaultIdentifierCodec::this_size(const uint32& id)
82{
83 if(id > TWO_BYTE_MAX_ID)
84 throw(Exception("dccl.id provided (" + boost::lexical_cast<std::string>(id) + ") exceeds maximum: " + boost::lexical_cast<std::string>(int(TWO_BYTE_MAX_ID))));
85
86 return (id <= ONE_BYTE_MAX_ID) ?
87 SHORT_FORM_ID_BYTES*BITS_IN_BYTE :
88 LONG_FORM_ID_BYTES*BITS_IN_BYTE;
89}
90
91
92unsigned dccl::DefaultIdentifierCodec::max_size()
93{
94 return LONG_FORM_ID_BYTES * BITS_IN_BYTE;
95}
96
97unsigned dccl::DefaultIdentifierCodec::min_size()
98{
99 return SHORT_FORM_ID_BYTES * BITS_IN_BYTE;
100}
0101
=== added file 'src/field_codec_id.h'
--- src/field_codec_id.h 1970-01-01 00:00:00 +0000
+++ src/field_codec_id.h 2014-08-27 16:27:22 +0000
@@ -0,0 +1,50 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23#include "field_codec_fixed.h"
24
25namespace dccl
26{
27 /// \brief Provides the default 1 byte or 2 byte DCCL ID codec
28 class DefaultIdentifierCodec : public TypedFieldCodec<uint32>
29 {
30 protected:
31 virtual Bitset encode();
32 virtual Bitset encode(const uint32& wire_value);
33 virtual uint32 decode(Bitset* bits);
34 virtual unsigned size();
35 virtual unsigned size(const uint32& wire_value);
36 virtual unsigned max_size();
37 virtual unsigned min_size();
38 virtual void validate() { }
39
40 private:
41 unsigned this_size(const uint32& wire_value);
42 // maximum id we can fit in short or long header (MSB reserved to indicate
43 // short or long header)
44 enum { ONE_BYTE_MAX_ID = (1 << 7) - 1,
45 TWO_BYTE_MAX_ID = (1 << 15) - 1};
46
47 enum { SHORT_FORM_ID_BYTES = 1,
48 LONG_FORM_ID_BYTES = 2 };
49 };
50}
051
=== modified file 'src/field_codec_manager.h'
--- src/field_codec_manager.h 2014-04-22 20:10:37 +0000
+++ src/field_codec_manager.h 2014-08-27 16:27:22 +0000
@@ -81,12 +81,49 @@
81 template<class Codec, google::protobuf::FieldDescriptor::Type type>81 template<class Codec, google::protobuf::FieldDescriptor::Type type>
82 static void add(const std::string& name);82 static void add(const std::string& name);
8383
84 /// \brief Remove a new field codec (used for codecs operating on statically generated Protobuf messages, that is, children of google::protobuf::Message but not google::protobuf::Message itself).
85 ///
86 /// \tparam Codec A child of FieldCodecBase
87 /// \param name Name to use for this codec. Corresponds to (dccl.field).codec="name" in .proto file.
88 /// \return nothing (void). Return templates are used for template metaprogramming selection of the proper remove() overload.
89 template<class Codec>
90 typename boost::enable_if<
91 boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
92 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
93 >,
94 void>::type
95 static remove(const std::string& name, dummy_fcm<0> dummy_fcm = 0);
96
97 /// \brief Remove a new field codec (used for codecs operating on all types except statically generated Protobuf messages).
98 ///
99 /// \tparam Codec A child of FieldCodecBase
100 /// \param name Name to use for this codec. Corresponds to (dccl.field).codec="name" in .proto file.
101 /// \return nothing (void). Return templates are used for template metaprogramming selection of the proper remove() overload.
102 template<class Codec>
103 typename boost::disable_if<
104 boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
105 boost::mpl::not_<boost::is_same<google::protobuf::Message,typename Codec::wire_type> >
106 >,
107 void>::type
108 static remove(const std::string& name, dummy_fcm<1> dummy_fcm = 0);
109
110 /// \brief Remove a new field codec only valid for a specific google::protobuf::FieldDescriptor::Type. This is useful if a given codec is designed to work with only a specific Protobuf type that shares an underlying C++ type (e.g. Protobuf types `bytes` and `string`)
111 ///
112 /// \tparam Codec A child of FieldCodecBase
113 /// \tparam type The google::protobuf::FieldDescriptor::Type enumeration that this codec works on.
114 /// \param name Name to use for this codec. Corresponds to (dccl.field).codec="name" in .proto file.
115 template<class Codec, google::protobuf::FieldDescriptor::Type type>
116 static void remove(const std::string& name);
117
118
84 /// \brief Find the codec for a given field. For embedded messages, prefers (dccl.field).codec (inside field) over (dccl.msg).codec (inside embedded message).119 /// \brief Find the codec for a given field. For embedded messages, prefers (dccl.field).codec (inside field) over (dccl.msg).codec (inside embedded message).
85 static boost::shared_ptr<FieldCodecBase> find(120 static boost::shared_ptr<FieldCodecBase> find(
86 const google::protobuf::FieldDescriptor* field)121 const google::protobuf::FieldDescriptor* field,
122 bool has_codec_group,
123 const std::string& codec_group)
87 {124 {
88 std::string name = __find_codec(field);125 std::string name = __find_codec(field, has_codec_group, codec_group);
89 126
90 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)127 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
91 return find(field->message_type(), name);128 return find(field->message_type(), name);
92 else129 else
@@ -101,9 +138,16 @@
101 const google::protobuf::Descriptor* desc,138 const google::protobuf::Descriptor* desc,
102 std::string name = "")139 std::string name = "")
103 {140 {
141 // this was called on the root message
104 if(name.empty())142 if(name.empty())
105 name = desc->options().GetExtension(dccl::msg).codec();143 {
106144 // explicitly declared codec takes precedence over group
145 if(desc->options().GetExtension(dccl::msg).has_codec())
146 name = desc->options().GetExtension(dccl::msg).codec();
147 else
148 name = FieldCodecBase::codec_group(desc);
149 }
150
107 return __find(google::protobuf::FieldDescriptor::TYPE_MESSAGE,151 return __find(google::protobuf::FieldDescriptor::TYPE_MESSAGE,
108 name, desc->full_name());152 name, desc->full_name());
109 }153 }
@@ -115,6 +159,11 @@
115 return __find(type, name);159 return __find(type, name);
116 }160 }
117161
162 static void clear()
163 {
164 TypeHelper::reset();
165 codecs_.clear();
166 }
118 167
119 168
120 private:169 private:
@@ -132,27 +181,41 @@
132 181
133 static std::string __mangle_name(const std::string& codec_name,182 static std::string __mangle_name(const std::string& codec_name,
134 const std::string& type_name) 183 const std::string& type_name)
135 { return type_name.empty() ? codec_name : codec_name + "@@" + type_name; }184 { return type_name.empty() ? codec_name : codec_name + "[" + type_name + "]"; }
136 185
137186
138 template<typename WireType, typename FieldType, class Codec> 187 template<typename WireType, typename FieldType, class Codec>
139 static void __add(const std::string& name); 188 static void add_all_types(const std::string& name);
140189
141 template<class Codec>190 template<class Codec>
142 static void __add(const std::string& name,191 static void add_single_type(const std::string& name,
143 google::protobuf::FieldDescriptor::Type field_type,192 google::protobuf::FieldDescriptor::Type field_type,
144 google::protobuf::FieldDescriptor::CppType wire_type);193 google::protobuf::FieldDescriptor::CppType wire_type);
145194
146195 template<typename WireType, typename FieldType, class Codec>
147 static std::string __find_codec(const google::protobuf::FieldDescriptor* field)196 static void remove_all_types(const std::string& name);
197
198 template<class Codec>
199 static void remove_single_type(const std::string& name,
200 google::protobuf::FieldDescriptor::Type field_type,
201 google::protobuf::FieldDescriptor::CppType wire_type);
202
203
204 static std::string __find_codec(const google::protobuf::FieldDescriptor* field,
205 bool has_codec_group, const std::string& codec_group)
148 {206 {
149 dccl::DCCLFieldOptions dccl_field_options = field->options().GetExtension(dccl::field);207 dccl::DCCLFieldOptions dccl_field_options = field->options().GetExtension(dccl::field);
150 208
151 // prefer the codec listed as a field extension209 // prefer the codec listed as a field extension
152 if(dccl_field_options.has_codec())210 if(dccl_field_options.has_codec())
153 return dccl_field_options.codec();211 return dccl_field_options.codec();
154 else if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)212 // then, the codec embedded in the message option extension
213 else if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE && field->message_type()->options().GetExtension(dccl::msg).has_codec())
155 return field->message_type()->options().GetExtension(dccl::msg).codec();214 return field->message_type()->options().GetExtension(dccl::msg).codec();
215 // then the overarching codec group
216 else if(has_codec_group)
217 return codec_group;
218 // finally the default
156 else219 else
157 return dccl_field_options.codec();220 return dccl_field_options.codec();
158 }221 }
@@ -173,9 +236,9 @@
173dccl::FieldCodecManager::add(const std::string& name, dummy_fcm<0> dummy_fcm)236dccl::FieldCodecManager::add(const std::string& name, dummy_fcm<0> dummy_fcm)
174{237{
175 TypeHelper::add<typename Codec::wire_type>();238 TypeHelper::add<typename Codec::wire_type>();
176 __add<Codec>(__mangle_name(name, Codec::wire_type::descriptor()->full_name()),239 add_single_type<Codec>(__mangle_name(name, Codec::wire_type::descriptor()->full_name()),
177 google::protobuf::FieldDescriptor::TYPE_MESSAGE,240 google::protobuf::FieldDescriptor::TYPE_MESSAGE,
178 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);241 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
179}242}
180243
181template<class Codec>244template<class Codec>
@@ -187,18 +250,18 @@
187 void>::type250 void>::type
188 dccl::FieldCodecManager::add(const std::string& name, dummy_fcm<1> dummy_fcm)251 dccl::FieldCodecManager::add(const std::string& name, dummy_fcm<1> dummy_fcm)
189{252{
190 __add<typename Codec::wire_type, typename Codec::field_type, Codec>(name);253 add_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name);
191}254}
192255
193template<class Codec, google::protobuf::FieldDescriptor::Type type> 256template<class Codec, google::protobuf::FieldDescriptor::Type type>
194 void dccl::FieldCodecManager::add(const std::string& name) 257 void dccl::FieldCodecManager::add(const std::string& name)
195{ 258{
196 __add<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));259 add_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));
197}260}
198261
199262
200template<typename WireType, typename FieldType, class Codec>263template<typename WireType, typename FieldType, class Codec>
201 void dccl::FieldCodecManager::__add(const std::string& name)264 void dccl::FieldCodecManager::add_all_types(const std::string& name)
202{265{
203 using google::protobuf::FieldDescriptor;266 using google::protobuf::FieldDescriptor;
204 const FieldDescriptor::CppType cpp_field_type = ToProtoCppType<FieldType>::as_enum();267 const FieldDescriptor::CppType cpp_field_type = ToProtoCppType<FieldType>::as_enum();
@@ -209,17 +272,17 @@
209 FieldDescriptor::Type field_type = static_cast<FieldDescriptor::Type>(i);272 FieldDescriptor::Type field_type = static_cast<FieldDescriptor::Type>(i);
210 if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)273 if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)
211 { 274 {
212 __add<Codec>(name, field_type, cpp_wire_type);275 add_single_type<Codec>(name, field_type, cpp_wire_type);
213 }276 }
214 }277 }
215}278}
216279
217template<class Codec>280template<class Codec>
218void dccl::FieldCodecManager::__add(const std::string& name,281void dccl::FieldCodecManager::add_single_type(const std::string& name,
219 google::protobuf::FieldDescriptor::Type field_type,282 google::protobuf::FieldDescriptor::Type field_type,
220 google::protobuf::FieldDescriptor::CppType wire_type)283 google::protobuf::FieldDescriptor::CppType wire_type)
221{284{
222 using google::protobuf::FieldDescriptor; 285 using google::protobuf::FieldDescriptor;
223 if(!codecs_[field_type].count(name))286 if(!codecs_[field_type].count(name))
224 {287 {
225 boost::shared_ptr<FieldCodecBase> new_field_codec(new Codec());288 boost::shared_ptr<FieldCodecBase> new_field_codec(new Codec());
@@ -246,4 +309,82 @@
246309
247310
248311
312template<class Codec>
313typename boost::enable_if<
314boost::mpl::and_<
315boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
316boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
317>,
318void>::type
319dccl::FieldCodecManager::remove(const std::string& name, dummy_fcm<0> dummy_fcm)
320{
321 TypeHelper::remove<typename Codec::wire_type>();
322 remove_single_type<Codec>(__mangle_name(name, Codec::wire_type::descriptor()->full_name()),
323 google::protobuf::FieldDescriptor::TYPE_MESSAGE,
324 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
325}
326
327template<class Codec>
328typename boost::disable_if<
329boost::mpl::and_<
330boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
331 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
332 >,
333 void>::type
334 dccl::FieldCodecManager::remove(const std::string& name, dummy_fcm<1> dummy_fcm)
335{
336 remove_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name);
337}
338
339template<class Codec, google::protobuf::FieldDescriptor::Type type>
340 void dccl::FieldCodecManager::remove(const std::string& name)
341{
342 remove_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));
343}
344
345
346template<typename WireType, typename FieldType, class Codec>
347 void dccl::FieldCodecManager::remove_all_types(const std::string& name)
348{
349 using google::protobuf::FieldDescriptor;
350 const FieldDescriptor::CppType cpp_field_type = ToProtoCppType<FieldType>::as_enum();
351 const FieldDescriptor::CppType cpp_wire_type = ToProtoCppType<WireType>::as_enum();
352
353 for(int i = 1, n = FieldDescriptor::MAX_TYPE; i <= n; ++i)
354 {
355 FieldDescriptor::Type field_type = static_cast<FieldDescriptor::Type>(i);
356 if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)
357 {
358 remove_single_type<Codec>(name, field_type, cpp_wire_type);
359 }
360 }
361}
362
363template<class Codec>
364void dccl::FieldCodecManager::remove_single_type(const std::string& name,
365 google::protobuf::FieldDescriptor::Type field_type,
366 google::protobuf::FieldDescriptor::CppType wire_type)
367{
368 using google::protobuf::FieldDescriptor;
369 if(codecs_[field_type].count(name))
370 {
371 dccl::dlog.is(dccl::logger::DEBUG1) && dccl::dlog << "Removing codec " << *codecs_[field_type][name] << std::endl;
372 codecs_[field_type].erase(name);
373 }
374 else
375 {
376 boost::shared_ptr<FieldCodecBase> new_field_codec(new Codec());
377 new_field_codec->set_name(name);
378 new_field_codec->set_field_type(field_type);
379 new_field_codec->set_wire_type(wire_type);
380
381 dccl::dlog.is(dccl::logger::DEBUG1) && dccl::dlog << "Trying to remove: " << *new_field_codec
382 << ", but no such codec exists"
383 << std::endl;
384 }
385}
386
387
388
389
249#endif390#endif
250391
=== modified file 'src/field_codec_message_stack.cpp'
--- src/field_codec_message_stack.cpp 2014-04-22 20:10:37 +0000
+++ src/field_codec_message_stack.cpp 2014-08-27 16:27:22 +0000
@@ -26,7 +26,7 @@
2626
27std::vector<const google::protobuf::FieldDescriptor*> dccl::MessageStack::field_;27std::vector<const google::protobuf::FieldDescriptor*> dccl::MessageStack::field_;
28std::vector<const google::protobuf::Descriptor*> dccl::MessageStack::desc_;28std::vector<const google::protobuf::Descriptor*> dccl::MessageStack::desc_;
29dccl::MessageStack::MessagePart dccl::MessageStack::current_part_ = dccl::MessageStack::UNKNOWN;29std::vector<dccl::MessageStack::MessagePart> dccl::MessageStack::parts_;
3030
31//31//
32// MessageStack32// MessageStack
@@ -45,6 +45,12 @@
45 ++fields_pushed_;45 ++fields_pushed_;
46}46}
4747
48void dccl::MessageStack::push(MessagePart part)
49{
50 parts_.push_back(part);
51 ++parts_pushed_;
52}
53
4854
49void dccl::MessageStack::__pop_desc()55void dccl::MessageStack::__pop_desc()
50{56{
@@ -58,17 +64,34 @@
58 field_.pop_back();64 field_.pop_back();
59}65}
6066
67void dccl::MessageStack::__pop_parts()
68{
69 if(!parts_.empty())
70 parts_.pop_back();
71}
72
73
61dccl::MessageStack::MessageStack(const google::protobuf::FieldDescriptor* field)74dccl::MessageStack::MessageStack(const google::protobuf::FieldDescriptor* field)
62 : descriptors_pushed_(0),75 : descriptors_pushed_(0),
63 fields_pushed_(0)76 fields_pushed_(0),
77 parts_pushed_(0)
64{78{
65 if(field)79 if(field)
66 {80 {
67 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)81 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
68 {82 {
69 // if explicitly set, set part (HEAD or BODY) of message for all children of this message83 MessagePart part = UNKNOWN;
70 if(field->options().GetExtension(dccl::field).has_in_head())84 if(field->options().GetExtension(dccl::field).has_in_head())
71 current_part_ = field->options().GetExtension(dccl::field).in_head() ? HEAD : BODY;85 {
86 // if explicitly set, set part (HEAD or BODY) of message for all children of this message
87 part = field->options().GetExtension(dccl::field).in_head() ? HEAD : BODY;
88 }
89 else
90 {
91 // use the parent's current part
92 part = current_part();
93 }
94 push(part);
72 95
73 push(field->message_type());96 push(field->message_type());
74 }97 }
@@ -77,3 +100,14 @@
77 100
78}101}
79102
103dccl::MessageStack::~MessageStack()
104{
105 for(int i = 0; i < fields_pushed_; ++i)
106 __pop_field();
107
108 for(int i = 0; i < descriptors_pushed_; ++i)
109 __pop_desc();
110
111 for(int i = 0; i < parts_pushed_; ++i)
112 __pop_parts();
113}
80114
=== modified file 'src/field_codec_message_stack.h'
--- src/field_codec_message_stack.h 2014-04-22 20:10:37 +0000
+++ src/field_codec_message_stack.h 2014-08-27 16:27:22 +0000
@@ -34,19 +34,7 @@
34 public:34 public:
35 MessageStack(const google::protobuf::FieldDescriptor* field = 0);35 MessageStack(const google::protobuf::FieldDescriptor* field = 0);
36 36
37 ~MessageStack()37 ~MessageStack();
38 {
39 for(int i = 0; i < descriptors_pushed_; ++i)
40 __pop_desc();
41
42 for(int i = 0; i < fields_pushed_; ++i)
43 __pop_field();
44
45 if(desc_.empty())
46 {
47 current_part_ = UNKNOWN;
48 }
49 }
5038
51 enum MessagePart { HEAD, BODY, UNKNOWN };39 enum MessagePart { HEAD, BODY, UNKNOWN };
52 40
@@ -57,19 +45,22 @@
5745
58 void push(const google::protobuf::Descriptor* desc);46 void push(const google::protobuf::Descriptor* desc);
59 void push(const google::protobuf::FieldDescriptor* field);47 void push(const google::protobuf::FieldDescriptor* field);
48 void push(MessagePart part);
6049
61 static MessagePart current_part() { return current_part_; }50 static MessagePart current_part() { return parts_.empty() ? UNKNOWN : parts_.back(); }
62 51
63 friend class FieldCodecBase;52 friend class FieldCodecBase;
64 private:53 private:
65 void __pop_desc();54 void __pop_desc();
66 void __pop_field();55 void __pop_field();
56 void __pop_parts();
67 57
68 static std::vector<const google::protobuf::Descriptor*> desc_;58 static std::vector<const google::protobuf::Descriptor*> desc_;
69 static std::vector<const google::protobuf::FieldDescriptor*> field_;59 static std::vector<const google::protobuf::FieldDescriptor*> field_;
60 static std::vector<MessagePart> parts_;
70 int descriptors_pushed_;61 int descriptors_pushed_;
71 int fields_pushed_;62 int fields_pushed_;
72 static MessagePart current_part_;63 int parts_pushed_;
73 };64 };
74}65}
7566
7667
=== modified file 'src/field_codec_typed.h'
--- src/field_codec_typed.h 2014-04-22 20:10:37 +0000
+++ src/field_codec_typed.h 2014-08-27 16:27:22 +0000
@@ -24,6 +24,9 @@
24#ifndef DCCLFIELDCODECTYPED20120312H24#ifndef DCCLFIELDCODECTYPED20120312H
25#define DCCLFIELDCODECTYPED20120312H25#define DCCLFIELDCODECTYPED20120312H
2626
27
28#include <boost/type_traits.hpp>
29
27#include "field_codec.h"30#include "field_codec.h"
2831
29namespace dccl32namespace dccl
@@ -72,7 +75,7 @@
72 class TypedFieldCodec : public FieldCodecSelector<WireType, FieldType>75 class TypedFieldCodec : public FieldCodecSelector<WireType, FieldType>
73 {76 {
74 public:77 public:
75 typedef WireType wire_type;78typedef WireType wire_type;
76 typedef FieldType field_type;79 typedef FieldType field_type;
7780
78 public:81 public:
@@ -256,8 +259,14 @@
256 ///259 ///
257 /// \param bits Bits to use for decoding.260 /// \param bits Bits to use for decoding.
258 /// \return the decoded value.261 /// \return the decoded value.
259 virtual WireType decode(Bitset* bits)262 virtual WireType decode(dccl::Bitset* bits)
260 { return decode_repeated(bits).at(0); } 263 {
264 std::vector<WireType> return_vec = decode_repeated(bits);
265 if(return_vec.empty())
266 throw dccl::NullValueException();
267 else
268 return return_vec.at(0);
269 }
261270
262 /// \brief Calculate the size (in bits) of an empty field.271 /// \brief Calculate the size (in bits) of an empty field.
263 ///272 ///
264273
=== modified file 'src/logger.cpp'
--- src/logger.cpp 2014-04-22 20:10:37 +0000
+++ src/logger.cpp 2014-08-27 16:27:22 +0000
@@ -55,6 +55,7 @@
55 case logger::GENERAL: break;55 case logger::GENERAL: break;
56 case logger::ENCODE: grp_str = "{encode}: "; break;56 case logger::ENCODE: grp_str = "{encode}: "; break;
57 case logger::DECODE: grp_str = "{decode}: "; break;57 case logger::DECODE: grp_str = "{decode}: "; break;
58 case logger::SIZE: grp_str = "{size}: "; break;
58 }59 }
59 60
60 std::time_t now = std::time(0);61 std::time_t now = std::time(0);
@@ -64,11 +65,12 @@
64 {65 {
65 *os << "[ " << (t->tm_year+1900) << "-"66 *os << "[ " << (t->tm_year+1900) << "-"
66 << std::setw(2) << std::setfill('0') << (t->tm_mon+1) << "-"67 << std::setw(2) << std::setfill('0') << (t->tm_mon+1) << "-"
67 << std::setw(2) << std::setfill('0') << t->tm_mday68 << std::setw(2) << t->tm_mday
68 << " "69 << " "
69 << std::setw(2) << std::setfill('0') << t->tm_hour << ":"70 << std::setw(2) << t->tm_hour << ":"
70 << std::setw(2) << std::setfill('0') << t->tm_min << ":"71 << std::setw(2) << t->tm_min << ":"
71 << std::setw(2) << std::setfill('0') << t->tm_sec << " ]: ";72 << std::setw(2) << t->tm_sec << " ]: "
73 << std::setfill(' ');
72 }74 }
73 75
74 *os << grp_str << msg << std::endl;76 *os << grp_str << msg << std::endl;
7577
=== modified file 'src/logger.h'
--- src/logger.h 2014-04-22 20:10:37 +0000
+++ src/logger.h 2014-08-27 16:27:22 +0000
@@ -47,10 +47,11 @@
47 DEBUG3_PLUS = DEBUG3 | (DEBUG3 - 1)47 DEBUG3_PLUS = DEBUG3 | (DEBUG3 - 1)
48 };48 };
49 enum Group 49 enum Group
50 { GENERAL, ENCODE, DECODE };50 { GENERAL, ENCODE, DECODE, SIZE };
51 51
52 }52 }
5353
54
5455
55 void to_ostream(const std::string& msg, dccl::logger::Verbosity vrb,56 void to_ostream(const std::string& msg, dccl::logger::Verbosity vrb,
56 dccl::logger::Group grp, std::ostream* os, bool add_timestamp);57 dccl::logger::Group grp, std::ostream* os, bool add_timestamp);
5758
=== modified file 'src/protobuf/option_extensions.proto'
--- src/protobuf/option_extensions.proto 2013-08-20 16:17:28 +0000
+++ src/protobuf/option_extensions.proto 2014-08-27 16:27:22 +0000
@@ -25,7 +25,7 @@
25message DCCLFieldOptions25message DCCLFieldOptions
26{26{
27 // what encoder / decoder should we use?27 // what encoder / decoder should we use?
28 optional string codec = 1 [default = "dccl.default"];28 optional string codec = 1 [default = "dccl.default2"];
29 // leave this field out of DCCL transmissions (has_field() will be false on receipt)29 // leave this field out of DCCL transmissions (has_field() will be false on receipt)
30 optional bool omit = 2 [default = false];30 optional bool omit = 2 [default = false];
31 // set true for fields in the header (will *not* be encrypte)d31 // set true for fields in the header (will *not* be encrypte)d
@@ -60,9 +60,12 @@
6060
61message DCCLMessageOptions61message DCCLMessageOptions
62{62{
63 required int32 id = 1;63 optional int32 id = 1;
64 required uint32 max_bytes = 2;64 optional uint32 max_bytes = 2;
6565
66 optional string codec = 3 [default = "dccl.default"];66 optional string codec = 3 [default = "dccl.default2"];
67
68 optional string codec_group = 4 [default = "dccl.default2"];
69 optional int32 codec_version = 5 [default = 2];
67}70}
6871
6972
=== modified file 'src/test/CMakeLists.txt'
--- src/test/CMakeLists.txt 2014-03-26 16:25:12 +0000
+++ src/test/CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -10,6 +10,8 @@
10add_subdirectory(dccl_static_methods)10add_subdirectory(dccl_static_methods)
11add_subdirectory(dccl_custom_id)11add_subdirectory(dccl_custom_id)
12add_subdirectory(dccl_numeric_bounds)12add_subdirectory(dccl_numeric_bounds)
13add_subdirectory(dccl_codec_group)
14add_subdirectory(dccl_message_fix)
1315
14if(build_ccl)16if(build_ccl)
15 add_subdirectory(dccl_ccl)17 add_subdirectory(dccl_ccl)
@@ -19,6 +21,9 @@
19 add_subdirectory(dccl_arithmetic)21 add_subdirectory(dccl_arithmetic)
20endif()22endif()
2123
24add_subdirectory(dccl_v2_all_fields)
25add_subdirectory(dccl_v2_header)
26
22add_subdirectory(bitset1)27add_subdirectory(bitset1)
2328
24add_subdirectory(logger1)29add_subdirectory(logger1)
2530
=== modified file 'src/test/dccl_all_fields/test.cpp'
--- src/test/dccl_all_fields/test.cpp 2014-04-22 20:13:39 +0000
+++ src/test/dccl_all_fields/test.cpp 2014-08-27 16:27:22 +0000
@@ -136,7 +136,9 @@
136 decode_check(bytes);136 decode_check(bytes);
137137
138 // make sure DCCL defaults stay wire compatible138 // make sure DCCL defaults stay wire compatible
139 decode_check(dccl::hex_decode("047f277b9628060000b95660c0b0188000d8c0132858800008000dc2c4c6626466024488cca8ee324bd05c3f23af0000ad9112a09509788013e0820b18e0005ed0204c6c2c4666062042644675975982c65235f10a00ad718a5801000000905f27121600000000a0170050640300309201001a0b00007d320a0000a61a0070b20100a81b00d09c6f0000a0401026361643102636160300f0dfbd5b2280ea2e330f3da59a2100aabfa55a000000000000000000000000"));139
140 // v3
141 decode_check(dccl::hex_decode("047f277b16b95660c0b0188000d8c0132858800008002d4c6c2c4666264084c88cea2eb304cdeb67cc2b00b4464a805626e0014e800b2e60800378410b131b8b91990188109951dd6596a0b154cd7805506b9c2256caaf13094ba0978a6c248a692493c682fa6454a69a4e36a16e6ace37a918263616c330b1b118fd77ef9608a0bacbac574fa9cd1050fd6daa0500"));
140142
141 // run a bunch of tests with random strings143 // run a bunch of tests with random strings
142 std::string random = bytes;144 std::string random = bytes;
143145
=== modified file 'src/test/dccl_all_fields/test.proto'
--- src/test/dccl_all_fields/test.proto 2012-10-19 16:41:36 +0000
+++ src/test/dccl_all_fields/test.proto 2014-08-27 16:27:22 +0000
@@ -29,6 +29,7 @@
29{29{
30 option (dccl.msg).id = 2;30 option (dccl.msg).id = 2;
31 option (dccl.msg).max_bytes = 512;31 option (dccl.msg).max_bytes = 512;
32 option (dccl.msg).codec_version = 3;
3233
33 // test default enc/dec34 // test default enc/dec
34 optional double double_default_optional = 1 [(dccl.field).min=-100,35 optional double double_default_optional = 1 [(dccl.field).min=-100,
@@ -123,8 +124,7 @@
123 (dccl.field).max_repeat=4];124 (dccl.field).max_repeat=4];
124 repeated uint32 uint32_default_repeat = 105 [(dccl.field).min=0,125 repeated uint32 uint32_default_repeat = 105 [(dccl.field).min=0,
125 (dccl.field).max=100,126 (dccl.field).max=100,
126 (dccl.field).max_repeat=4,127 (dccl.field).max_repeat=4];
127 (dccl.field).in_head=true];
128 repeated uint64 uint64_default_repeat = 106 [(dccl.field).min=0,128 repeated uint64 uint64_default_repeat = 106 [(dccl.field).min=0,
129 (dccl.field).max=100,129 (dccl.field).max=100,
130 (dccl.field).max_repeat=4];130 (dccl.field).max_repeat=4];
131131
=== modified file 'src/test/dccl_arithmetic/test.proto'
--- src/test/dccl_arithmetic/test.proto 2012-10-23 00:46:12 +0000
+++ src/test/dccl_arithmetic/test.proto 2014-08-27 16:27:22 +0000
@@ -25,7 +25,8 @@
25{25{
26 option (dccl.msg).id = 1;26 option (dccl.msg).id = 1;
27 option (dccl.msg).max_bytes = 512;27 option (dccl.msg).max_bytes = 512;
28 28 option (dccl.msg).codec_version = 3;
29
29 repeated double value = 101 [(dccl.field).codec = "_arithmetic",30 repeated double value = 101 [(dccl.field).codec = "_arithmetic",
30 (dccl.field).(arithmetic).model = "model",31 (dccl.field).(arithmetic).model = "model",
31 (dccl.field).(arithmetic).debug_assert = true,32 (dccl.field).(arithmetic).debug_assert = true,
@@ -35,6 +36,7 @@
35{36{
36 option (dccl.msg).id = 2;37 option (dccl.msg).id = 2;
37 option (dccl.msg).max_bytes = 512;38 option (dccl.msg).max_bytes = 512;
39 option (dccl.msg).codec_version = 3;
38 40
39 repeated Enum1 value = 114 [(dccl.field).codec = "_arithmetic",41 repeated Enum1 value = 114 [(dccl.field).codec = "_arithmetic",
40 (dccl.field).(arithmetic).model = "model",42 (dccl.field).(arithmetic).model = "model",
@@ -47,6 +49,7 @@
47{49{
48 option (dccl.msg).id = 3;50 option (dccl.msg).id = 3;
49 option (dccl.msg).max_bytes = 512;51 option (dccl.msg).max_bytes = 512;
52 option (dccl.msg).codec_version = 3;
50 53
51 required Enum1 value = 114 [(dccl.field).codec = "_arithmetic",54 required Enum1 value = 114 [(dccl.field).codec = "_arithmetic",
52 (dccl.field).(arithmetic).model = "model",55 (dccl.field).(arithmetic).model = "model",
@@ -58,6 +61,7 @@
58{61{
59 option (dccl.msg).id = 4;62 option (dccl.msg).id = 4;
60 option (dccl.msg).max_bytes = 512;63 option (dccl.msg).max_bytes = 512;
64 option (dccl.msg).codec_version = 3;
61 65
62 repeated Enum2 value = 114 [(dccl.field).codec = "_arithmetic",66 repeated Enum2 value = 114 [(dccl.field).codec = "_arithmetic",
63 (dccl.field).(arithmetic).model = "model",67 (dccl.field).(arithmetic).model = "model",
@@ -70,6 +74,7 @@
70{74{
71 option (dccl.msg).id = 5;75 option (dccl.msg).id = 5;
72 option (dccl.msg).max_bytes = 10000;76 option (dccl.msg).max_bytes = 10000;
77 option (dccl.msg).codec_version = 3;
73 78
74 repeated int32 value = 101 [(dccl.field).codec = "_arithmetic",79 repeated int32 value = 101 [(dccl.field).codec = "_arithmetic",
75 (dccl.field).(arithmetic).model = "model",80 (dccl.field).(arithmetic).model = "model",
@@ -82,6 +87,7 @@
82{87{
83 option (dccl.msg).id = 6;88 option (dccl.msg).id = 6;
84 option (dccl.msg).max_bytes = 10000;89 option (dccl.msg).max_bytes = 10000;
90 option (dccl.msg).codec_version = 3;
85 91
86 repeated int32 value = 101 [(dccl.field).codec = "_arithmetic",92 repeated int32 value = 101 [(dccl.field).codec = "_arithmetic",
87 (dccl.field).(arithmetic).model = "model",93 (dccl.field).(arithmetic).model = "model",
8894
=== modified file 'src/test/dccl_ccl/test.cpp'
--- src/test/dccl_ccl/test.cpp 2014-04-22 20:13:39 +0000
+++ src/test/dccl_ccl/test.cpp 2014-08-27 16:27:22 +0000
@@ -48,11 +48,9 @@
48{48{
49 dccl::dlog.connect(dccl::logger::ALL, &std::cerr); 49 dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
5050
51 { 51 {
52 dccl::FieldCodecManager::add<dccl::LegacyCCLIdentifierCodec>("ccl_id_codec");
53 dccl::Codec codec("ccl_id_codec");
54
55 void* dl_handle = dlopen("libdccl_ccl_compat" SHARED_LIBRARY_SUFFIX, RTLD_LAZY);52 void* dl_handle = dlopen("libdccl_ccl_compat" SHARED_LIBRARY_SUFFIX, RTLD_LAZY);
53 dccl::Codec codec("dccl.ccl.id");
5654
57 if(!dl_handle)55 if(!dl_handle)
58 {56 {
5957
=== modified file 'src/test/dccl_ccl/test.proto'
--- src/test/dccl_ccl/test.proto 2012-10-24 14:10:06 +0000
+++ src/test/dccl_ccl/test.proto 2014-08-27 16:27:22 +0000
@@ -4,6 +4,7 @@
4{4{
5 option (dccl.msg).id = 1;5 option (dccl.msg).id = 1;
6 option (dccl.msg).max_bytes = 32;6 option (dccl.msg).max_bytes = 32;
7 option (dccl.msg).codec_version = 3;
78
8 required int32 a = 1 [(dccl.field).min=0,9 required int32 a = 1 [(dccl.field).min=0,
9 (dccl.field).max=0xFFFF];10 (dccl.field).max=0xFFFF];
1011
=== added directory 'src/test/dccl_codec_group'
=== added file 'src/test/dccl_codec_group/CMakeLists.txt'
--- src/test/dccl_codec_group/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/test/dccl_codec_group/CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -0,0 +1,6 @@
1protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto)
2
3add_executable(dccl_test_codec_group test.cpp ${PROTO_SRCS} ${PROTO_HDRS})
4target_link_libraries(dccl_test_codec_group dccl)
5
6add_test(dccl_test_codec_group ${dccl_BIN_DIR}/dccl_test_codec_group)
07
=== added file 'src/test/dccl_codec_group/test.cpp'
--- src/test/dccl_codec_group/test.cpp 1970-01-01 00:00:00 +0000
+++ src/test/dccl_codec_group/test.cpp 2014-08-27 16:27:22 +0000
@@ -0,0 +1,104 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23
24// tests all protobuf types with _default codecs, repeat and non repeat
25
26#include <fstream>
27
28#include <google/protobuf/descriptor.pb.h>
29
30#include "dccl/codec.h"
31#include "dccl/codecs3/field_codec_default.h"
32
33#include "test.pb.h"
34#include "dccl/binary.h"
35
36template <typename Msg>
37void check(double val, bool should_pass);
38dccl::Codec codec;
39TestMsg msg_in;
40TestMsgGroup msg_group_in;
41
42class TestCodec : public dccl::v3::DefaultNumericFieldCodec<double>
43{
44 double max() { return 100; }
45 double min() { return -100; }
46 double precision() { return 1; }
47 void validate() { }
48};
49
50
51
52
53int main(int argc, char* argv[])
54{
55// dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
56
57 dccl::FieldCodecManager::add<TestCodec>("test.grouptest");
58 dccl::FieldCodecManager::add<dccl::v3::DefaultMessageCodec, google::protobuf::FieldDescriptor::TYPE_MESSAGE>("test.grouptest");
59
60 check<TestMsg>(50, true);
61 check<TestMsg>(-50, false);
62 check<TestMsgGroup>(50, true);
63 check<TestMsgGroup>(-50, true);
64 check<TestMsgVersion>(50, true);
65
66 std::cout << "all tests passed" << std::endl;
67}
68
69
70template <typename Msg>
71void check(double val, bool should_pass)
72{
73 Msg msg_in;
74 int i = 0;
75 msg_in.set_d(++i + 0.1);
76 msg_in.add_d_repeat(12.1);
77 msg_in.add_d_repeat(12.2);
78 msg_in.add_d_repeat(12.3);
79
80 msg_in.mutable_msg()->set_val(val);
81 msg_in.mutable_msg()->mutable_msg()->set_val(val);
82 codec.info(msg_in.GetDescriptor(), &std::cout);
83
84 std::cout << "Message in:\n" << msg_in.DebugString() << std::endl;
85
86 codec.load(msg_in.GetDescriptor());
87
88 std::cout << "Try encode..." << std::endl;
89 std::string bytes;
90 codec.encode(&bytes, msg_in);
91 std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl;
92
93 std::cout << "Try decode..." << std::endl;
94
95 Msg msg_out;
96 codec.decode(bytes, &msg_out);
97
98 std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl;
99
100 if(should_pass)
101 assert(msg_in.SerializeAsString() == msg_out.SerializeAsString());
102 else
103 assert(msg_in.SerializeAsString() != msg_out.SerializeAsString());
104}
0105
=== added file 'src/test/dccl_codec_group/test.proto'
--- src/test/dccl_codec_group/test.proto 1970-01-01 00:00:00 +0000
+++ src/test/dccl_codec_group/test.proto 2014-08-27 16:27:22 +0000
@@ -0,0 +1,77 @@
1import "dccl/protobuf/option_extensions.proto";
2
3
4message EmbeddedMsg1
5{
6 option (dccl.msg).codec="dccl.default3";
7
8 optional double val = 1 [(dccl.field).min=0,
9 (dccl.field).max=100,
10 (dccl.field).precision=3];
11
12
13 optional EmbeddedMsg2 msg = 2;
14}
15
16message EmbeddedMsg2
17{
18 optional double val = 1 [(dccl.field).min=0,
19 (dccl.field).max=100,
20 (dccl.field).precision=2];
21
22}
23
24message TestMsg
25{
26 option (dccl.msg).id = 1;
27 option (dccl.msg).max_bytes = 32;
28 option (dccl.msg).codec_version = 3;
29
30 optional double d = 1 [(dccl.field).min=-100,
31 (dccl.field).max=126,
32 (dccl.field).precision=1,
33 (dccl.field).codec="dccl.default3"];
34
35
36
37 repeated double d_repeat = 3 [(dccl.field).max_repeat=5,
38 (dccl.field).codec="test.grouptest"];
39 optional EmbeddedMsg1 msg = 2;
40}
41
42message TestMsgGroup
43{
44 option (dccl.msg).id = 2;
45 option (dccl.msg).max_bytes = 32;
46 option (dccl.msg).codec_group = "test.grouptest";
47 option (dccl.msg).codec_version = 3;
48
49 optional double d = 1 [(dccl.field).min=-100,
50 (dccl.field).max=126,
51 (dccl.field).precision=1,
52 (dccl.field).codec="dccl.default3"];
53
54 repeated double d_repeat = 3 [(dccl.field).max_repeat=5];
55 optional EmbeddedMsg1 msg = 2;
56
57}
58
59
60message TestMsgVersion
61{
62 option (dccl.msg).id = 3;
63 option (dccl.msg).max_bytes = 32;
64 option (dccl.msg).codec_version = 2;
65
66 optional double d = 1 [(dccl.field).min=-100,
67 (dccl.field).max=126,
68 (dccl.field).precision=2];
69
70 repeated double d_repeat = 3 [(dccl.field).min=12.0,
71 (dccl.field).max=13.6,
72 (dccl.field).precision=1,
73 (dccl.field).max_repeat=5];
74
75 optional EmbeddedMsg1 msg = 2;
76
77}
078
=== modified file 'src/test/dccl_custom_id/test.proto'
--- src/test/dccl_custom_id/test.proto 2012-10-24 14:10:06 +0000
+++ src/test/dccl_custom_id/test.proto 2014-08-27 16:27:22 +0000
@@ -4,6 +4,7 @@
4{4{
5 option (dccl.msg).id = 1000001;5 option (dccl.msg).id = 1000001;
6 option (dccl.msg).max_bytes = 2;6 option (dccl.msg).max_bytes = 2;
7 option (dccl.msg).codec_version = 3;
7 8
8 required uint32 user = 1 [(dccl.field).min=0,9 required uint32 user = 1 [(dccl.field).min=0,
9 (dccl.field).max=0x03FF,10 (dccl.field).max=0x03FF,
@@ -14,6 +15,7 @@
14{15{
15 option (dccl.msg).id = 1000002;16 option (dccl.msg).id = 1000002;
16 option (dccl.msg).max_bytes = 2;17 option (dccl.msg).max_bytes = 2;
18 option (dccl.msg).codec_version = 3;
17 19
18 required uint32 clock_mode = 1 [(dccl.field).min=0,20 required uint32 clock_mode = 1 [(dccl.field).min=0,
19 (dccl.field).max=3,21 (dccl.field).max=3,
@@ -32,6 +34,7 @@
32{34{
33 option (dccl.msg).id = 1000003;35 option (dccl.msg).id = 1000003;
34 option (dccl.msg).max_bytes = 2;36 option (dccl.msg).max_bytes = 2;
37 option (dccl.msg).codec_version = 3;
35 38
36 required uint32 user = 1 [(dccl.field).min=0,39 required uint32 user = 1 [(dccl.field).min=0,
37 (dccl.field).max=0x03FF,40 (dccl.field).max=0x03FF,
3841
=== modified file 'src/test/dccl_custom_message/test.proto'
--- src/test/dccl_custom_message/test.proto 2012-10-19 16:41:36 +0000
+++ src/test/dccl_custom_message/test.proto 2014-08-27 16:27:22 +0000
@@ -6,6 +6,7 @@
6 option (dccl.msg).id = 3;6 option (dccl.msg).id = 3;
7 option (dccl.msg).max_bytes = 256;7 option (dccl.msg).max_bytes = 256;
8 option (dccl.msg).codec = "custom_codec";8 option (dccl.msg).codec = "custom_codec";
9 option (dccl.msg).codec_version = 3;
9 10
10 optional uint32 a = 1;11 optional uint32 a = 1;
11 optional bool b = 2;12 optional bool b = 2;
@@ -16,6 +17,7 @@
16{17{
17 option (dccl.msg).id = 4;18 option (dccl.msg).id = 4;
18 option (dccl.msg).max_bytes = 256;19 option (dccl.msg).max_bytes = 256;
20 option (dccl.msg).codec_version = 3;
1921
20 optional CustomMsg msg = 1;22 optional CustomMsg msg = 1;
21 repeated int32 c = 3 [(dccl.field).max=100,23 repeated int32 c = 3 [(dccl.field).max=100,
2224
=== modified file 'src/test/dccl_default_id/test.proto'
--- src/test/dccl_default_id/test.proto 2012-10-19 16:41:36 +0000
+++ src/test/dccl_default_id/test.proto 2014-08-27 16:27:22 +0000
@@ -4,12 +4,14 @@
4{4{
5 option (dccl.msg).id = 2;5 option (dccl.msg).id = 2;
6 option (dccl.msg).max_bytes = 1;6 option (dccl.msg).max_bytes = 1;
7 option (dccl.msg).codec_version = 3;
7}8}
89
9message ShortIDMsgWithData10message ShortIDMsgWithData
10{11{
11 option (dccl.msg).id = 3;12 option (dccl.msg).id = 3;
12 option (dccl.msg).max_bytes = 10;13 option (dccl.msg).max_bytes = 10;
14 option (dccl.msg).codec_version = 3;
1315
14 optional int32 in_head = 1 [(dccl.field).in_head=true, (dccl.field).min=0, (dccl.field).max=100];16 optional int32 in_head = 1 [(dccl.field).in_head=true, (dccl.field).min=0, (dccl.field).max=100];
15 optional int32 in_body = 2 [(dccl.field).in_head=true, (dccl.field).min=0, (dccl.field).max=100];17 optional int32 in_body = 2 [(dccl.field).in_head=true, (dccl.field).min=0, (dccl.field).max=100];
@@ -17,23 +19,28 @@
1719
18message LongIDMsg20message LongIDMsg
19{21{
20 option (dccl.msg).id = 10000; option (dccl.msg).max_bytes = 2;22 option (dccl.msg).id = 10000;
23 option (dccl.msg).max_bytes = 2;
24 option (dccl.msg).codec_version = 3;
21}25}
2226
23message TooLongIDMsg27message TooLongIDMsg
24{28{
25 option (dccl.msg).id = 32768;29 option (dccl.msg).id = 32768;
26 option (dccl.msg).max_bytes = 32;30 option (dccl.msg).max_bytes = 32;
31 option (dccl.msg).codec_version = 3;
27}32}
2833
29message LongIDEdgeMsg34message LongIDEdgeMsg
30{35{
31 option (dccl.msg).id = 128;36 option (dccl.msg).id = 128;
32 option (dccl.msg).max_bytes = 2;37 option (dccl.msg).max_bytes = 2;
38 option (dccl.msg).codec_version = 3;
33}39}
3440
35message ShortIDEdgeMsg41message ShortIDEdgeMsg
36{42{
37 option (dccl.msg).id = 127;43 option (dccl.msg).id = 127;
38 option (dccl.msg).max_bytes = 1;44 option (dccl.msg).max_bytes = 1;
45 option (dccl.msg).codec_version = 3;
39}46}
4047
=== modified file 'src/test/dccl_header/header.proto'
--- src/test/dccl_header/header.proto 2013-08-22 18:58:12 +0000
+++ src/test/dccl_header/header.proto 2014-08-27 16:27:22 +0000
@@ -11,44 +11,35 @@
11 // microseconds since Unix11 // microseconds since Unix
1212
13 // second precision (default)13 // second precision (default)
14 required uint64 time = 10 [(dccl.field).codec="_time",14 required uint64 time = 10 [(dccl.field).codec="_time"];
15 (dccl.field).in_head=true];15
1616 optional int64 time_signed = 20 [(dccl.field).codec="_time"];
17 optional int64 time_signed = 20 [(dccl.field).codec="_time",17 optional double time_double = 21 [(dccl.field).codec="_time"];
18 (dccl.field).in_head=true];
19 optional double time_double = 21 [(dccl.field).codec="_time",
20 (dccl.field).in_head=true];
21 optional double pasttime_double = 22 [(dccl.field).codec="_time",18 optional double pasttime_double = 22 [(dccl.field).codec="_time",
22 (dccl.field).num_days=6,19 (dccl.field).num_days=6];
23 (dccl.field).in_head=true];
24 optional double futuretime_double = 23 [(dccl.field).codec="_time",20 optional double futuretime_double = 23 [(dccl.field).codec="_time",
25 (dccl.field).num_days=6,21 (dccl.field).num_days=6];
26 (dccl.field).in_head=true];
2722
28 // microsecond precision23 // microsecond precision
29 optional int64 time_precision = 24 [(dccl.field).codec="_time",24 optional int64 time_precision = 24 [(dccl.field).codec="_time",
30 (dccl.field).in_head=true,
31 (dccl.field).precision=-3];25 (dccl.field).precision=-3];
32 optional double time_double_precision = 25 [(dccl.field).codec="_time",26 optional double time_double_precision = 25 [(dccl.field).codec="_time",
33 (dccl.field).in_head=true,
34 (dccl.field).precision=6];27 (dccl.field).precision=6];
35 28
36 //29 //
37 // source30 // source
38 //31 //
39 required int32 source_platform = 11 [(dccl.field).min = 0,32 required int32 source_platform = 11 [(dccl.field).min = 0,
40 (dccl.field).max = 31,33 (dccl.field).max = 31];
41 (dccl.field).in_head=true];
42 optional string source_app = 12 [(dccl.field).omit=true];34 optional string source_app = 12 [(dccl.field).omit=true];
43 35
44 //36 //
45 // destination37 // destination
46 //38 //
47 enum PublishDestination { PUBLISH_SELF = 1; PUBLISH_OTHER = 2; PUBLISH_ALL = 3; }39 enum PublishDestination { PUBLISH_SELF = 1; PUBLISH_OTHER = 2; PUBLISH_ALL = 3; }
48 optional PublishDestination dest_type = 13 [default = PUBLISH_SELF, (dccl.field).in_head=true];40 optional PublishDestination dest_type = 13 [default = PUBLISH_SELF];
49 41
50 optional int32 dest_platform = 14 [(dccl.field).min = 0,42 optional int32 dest_platform = 14 [(dccl.field).min = 0,
51 (dccl.field).max = 31,43 (dccl.field).max = 31]; // required if dest_type == other
52 (dccl.field).in_head=true]; // required if dest_type == other
5344
54}45}
5546
=== modified file 'src/test/dccl_header/test.cpp'
--- src/test/dccl_header/test.cpp 2014-04-22 20:13:39 +0000
+++ src/test/dccl_header/test.cpp 2014-08-27 16:27:22 +0000
@@ -24,9 +24,9 @@
24// tests proper encoding of standard Goby header24// tests proper encoding of standard Goby header
2525
26#include "dccl/codec.h"26#include "dccl/codec.h"
27#include "dccl/field_codec_default.h"
28#include "test.pb.h"27#include "test.pb.h"
2928
29#include <sys/time.h>
3030
31#include "dccl/binary.h"31#include "dccl/binary.h"
3232
3333
=== modified file 'src/test/dccl_header/test.proto'
--- src/test/dccl_header/test.proto 2013-08-22 18:24:42 +0000
+++ src/test/dccl_header/test.proto 2014-08-27 16:27:22 +0000
@@ -5,9 +5,10 @@
5{5{
6 option (dccl.msg).id = 4;6 option (dccl.msg).id = 4;
7 option (dccl.msg).max_bytes = 64;7 option (dccl.msg).max_bytes = 64;
8 option (dccl.msg).codec_version = 3;
8 9
9 required string telegram = 1 [(dccl.field).max_length=10]; 10 required string telegram = 1 [(dccl.field).max_length=10];
10 required Header header = 2;11 required Header header = 2 [(dccl.field).in_head = true];
1112
12 optional int32 const_int =3 [(dccl.field).static_value="3", (dccl.field).codec="_static"];13 optional int32 const_int =3 [(dccl.field).static_value="3", (dccl.field).codec="_static"];
13}14}
1415
=== added directory 'src/test/dccl_message_fix'
=== added file 'src/test/dccl_message_fix/CMakeLists.txt'
--- src/test/dccl_message_fix/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/test/dccl_message_fix/CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -0,0 +1,6 @@
1protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto)
2
3add_executable(dccl_test_message_fix test.cpp ${PROTO_SRCS} ${PROTO_HDRS})
4target_link_libraries(dccl_test_message_fix dccl)
5
6add_test(dccl_test_message_fix ${dccl_BIN_DIR}/dccl_test_message_fix)
07
=== added file 'src/test/dccl_message_fix/test.cpp'
--- src/test/dccl_message_fix/test.cpp 1970-01-01 00:00:00 +0000
+++ src/test/dccl_message_fix/test.cpp 2014-08-27 16:27:22 +0000
@@ -0,0 +1,110 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23
24// tests all protobuf types with _default codecs, repeat and non repeat
25
26#include <fstream>
27
28#include <google/protobuf/descriptor.pb.h>
29
30#include "dccl/codec.h"
31#include "dccl/codecs2/field_codec_default.h"
32
33#include "test.pb.h"
34#include "dccl/binary.h"
35
36
37int main(int argc, char* argv[])
38{
39// dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
40 // check the empty messages
41 dccl::Codec codec;
42
43 codec.info<TestMsg>(&std::cout);
44 codec.load<TestMsg>();
45
46 {
47 TestMsg msg_in, msg_out;
48 int i = 0;
49
50
51 std::cout << "Message in:\n" << msg_in.DebugString() << std::endl;
52
53 codec.load(msg_in.GetDescriptor());
54
55 std::cout << "Try encode..." << std::endl;
56 std::string bytes;
57 codec.encode(&bytes, msg_in);
58 std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl;
59
60 std::cout << "Try decode..." << std::endl;
61
62 codec.decode(bytes, &msg_out);
63
64 std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl;
65
66 assert(!msg_out.has_msg1());
67 assert(!msg_out.msg1_repeat_size());
68 assert(!msg_out.has_msg2());
69 assert(!msg_out.msg2_repeat_size());
70 assert(msg_in.SerializeAsString() == msg_out.SerializeAsString());
71 }
72
73
74 // check partially full messages
75 {
76 TestMsg msg_in, msg_out;
77
78 msg_in.mutable_msg1()->set_val(0.1);
79 msg_in.add_msg1_repeat()->set_val(0.11);
80 msg_in.add_msg1_repeat()->set_val(0.12);
81 msg_in.add_msg1_repeat()->set_val(0.13);
82 msg_in.mutable_msg2()->set_val(0.2);
83 msg_in.add_msg2_repeat()->set_val(0.21);
84 msg_in.add_msg2_repeat()->set_val(0.22);
85 msg_in.add_msg2_repeat()->set_val(0.23);
86
87 std::cout << "Message in:\n" << msg_in.DebugString() << std::endl;
88
89 std::cout << "Try encode..." << std::endl;
90 std::string bytes;
91 codec.encode(&bytes, msg_in);
92 std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl;
93
94 std::cout << "Try decode..." << std::endl;
95
96 codec.decode(bytes, &msg_out);
97
98 std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl;
99
100 assert(msg_out.has_msg1());
101 assert(msg_out.msg1_repeat_size() == 3);
102 assert(msg_out.has_msg2());
103 assert(msg_out.msg2_repeat_size() == 3);
104 assert(msg_in.SerializeAsString() == msg_out.SerializeAsString());
105 }
106
107
108 std::cout << "all tests passed" << std::endl;
109}
110
0111
=== added file 'src/test/dccl_message_fix/test.proto'
--- src/test/dccl_message_fix/test.proto 1970-01-01 00:00:00 +0000
+++ src/test/dccl_message_fix/test.proto 2014-08-27 16:27:22 +0000
@@ -0,0 +1,31 @@
1import "dccl/protobuf/option_extensions.proto";
2
3message EmbeddedMsgOptional
4{
5 optional double val = 1 [(dccl.field).min=0,
6 (dccl.field).max=126,
7 (dccl.field).precision=3];
8}
9
10message EmbeddedMsgRequired
11{
12 required double val = 1 [(dccl.field).min=0,
13 (dccl.field).max=126,
14 (dccl.field).precision=3];
15}
16
17message TestMsg
18{
19 option (dccl.msg).id = 1;
20 option (dccl.msg).max_bytes = 32;
21 option (dccl.msg).codec_version = 3;
22
23 optional EmbeddedMsgOptional msg1 = 1;
24 repeated EmbeddedMsgOptional msg1_repeat = 3 [(dccl.field).max_repeat=5];
25
26 // in DCCL v2, these will always be set upon receipt since it has required children. This test validates the fix in v3
27 optional EmbeddedMsgRequired msg2 = 2;
28 repeated EmbeddedMsgRequired msg2_repeat = 4 [(dccl.field).max_repeat=5];
29
30}
31
032
=== modified file 'src/test/dccl_numeric_bounds/test.proto'
--- src/test/dccl_numeric_bounds/test.proto 2014-03-26 17:27:11 +0000
+++ src/test/dccl_numeric_bounds/test.proto 2014-08-27 16:27:22 +0000
@@ -4,6 +4,7 @@
4{4{
5 option (dccl.msg).id = 10;5 option (dccl.msg).id = 10;
6 option (dccl.msg).max_bytes = 32;6 option (dccl.msg).max_bytes = 32;
7 option (dccl.msg).codec_version = 3;
78
8 optional double a = 1 [(dccl.field).max = 180,9 optional double a = 1 [(dccl.field).max = 180,
9 (dccl.field).min = -180,10 (dccl.field).min = -180,
@@ -30,6 +31,7 @@
30{31{
31 option (dccl.msg).id = 10;32 option (dccl.msg).id = 10;
32 option (dccl.msg).max_bytes = 32;33 option (dccl.msg).max_bytes = 32;
34 option (dccl.msg).codec_version = 3;
3335
34 optional double a = 1 [(dccl.field).min = -20,36 optional double a = 1 [(dccl.field).min = -20,
35 (dccl.field).max = 20,37 (dccl.field).max = 20,
@@ -45,6 +47,7 @@
45{47{
46 option (dccl.msg).id = 11;48 option (dccl.msg).id = 11;
47 option (dccl.msg).max_bytes = 32;49 option (dccl.msg).max_bytes = 32;
50 option (dccl.msg).codec_version = 3;
4851
49 optional double a = 1 [(dccl.field).max = 180,52 optional double a = 1 [(dccl.field).max = 180,
50 (dccl.field).min = -180,53 (dccl.field).min = -180,
5154
=== modified file 'src/test/dccl_repeated/test.cpp'
--- src/test/dccl_repeated/test.cpp 2014-04-22 20:13:39 +0000
+++ src/test/dccl_repeated/test.cpp 2014-08-27 16:27:22 +0000
@@ -25,7 +25,6 @@
2525
2626
27#include "dccl/codec.h"27#include "dccl/codec.h"
28#include "dccl/field_codec_default.h"
29#include "dccl/binary.h"28#include "dccl/binary.h"
3029
31#include "test.pb.h"30#include "test.pb.h"
3231
=== modified file 'src/test/dccl_repeated/test.proto'
--- src/test/dccl_repeated/test.proto 2012-10-23 00:46:12 +0000
+++ src/test/dccl_repeated/test.proto 2014-08-27 16:27:22 +0000
@@ -5,6 +5,7 @@
5{5{
6 option (dccl.msg).id = 4;6 option (dccl.msg).id = 4;
7 option (dccl.msg).max_bytes = 32;7 option (dccl.msg).max_bytes = 32;
8 option (dccl.msg).codec_version = 3;
89
9 optional int32 int32_val = 1 [(dccl.field).min=0, (dccl.field).max=20];10 optional int32 int32_val = 1 [(dccl.field).min=0, (dccl.field).max=20];
10}11}
@@ -13,6 +14,7 @@
13{14{
14 option (dccl.msg).id = 5;15 option (dccl.msg).id = 5;
15 option (dccl.msg).max_bytes = 32;16 option (dccl.msg).max_bytes = 32;
17 option (dccl.msg).codec_version = 3;
1618
17 optional bool bool_val = 1;19 optional bool bool_val = 1;
18}20}
@@ -21,6 +23,7 @@
21{23{
22 option (dccl.msg).id = 6;24 option (dccl.msg).id = 6;
23 option (dccl.msg).max_bytes = 32;25 option (dccl.msg).max_bytes = 32;
26 option (dccl.msg).codec_version = 3;
2427
25 optional string string_val = 1 [(dccl.field).max_length=10];28 optional string string_val = 1 [(dccl.field).max_length=10];
26}29}
2730
=== modified file 'src/test/dccl_required_optional/test.proto'
--- src/test/dccl_required_optional/test.proto 2012-10-19 16:41:36 +0000
+++ src/test/dccl_required_optional/test.proto 2014-08-27 16:27:22 +0000
@@ -4,6 +4,7 @@
4{4{
5 option (dccl.msg).id = 10;5 option (dccl.msg).id = 10;
6 option (dccl.msg).max_bytes = 32;6 option (dccl.msg).max_bytes = 32;
7 option (dccl.msg).codec_version = 3;
78
8 required bytes req_bytes = 1 [(dccl.field).max_length=8];9 required bytes req_bytes = 1 [(dccl.field).max_length=8];
9 optional bytes opt_bytes = 2 [(dccl.field).max_length=8]; 10 optional bytes opt_bytes = 2 [(dccl.field).max_length=8];
1011
=== modified file 'src/test/dccl_static_methods/test.proto'
--- src/test/dccl_static_methods/test.proto 2012-10-23 00:46:12 +0000
+++ src/test/dccl_static_methods/test.proto 2014-08-27 16:27:22 +0000
@@ -5,6 +5,7 @@
5{5{
6 option (dccl.msg).id = 4;6 option (dccl.msg).id = 4;
7 option (dccl.msg).max_bytes = 32;7 option (dccl.msg).max_bytes = 32;
8 option (dccl.msg).codec_version = 3;
89
9 optional int32 int32_val = 1 [(dccl.field).min=0, (dccl.field).max=20];10 optional int32 int32_val = 1 [(dccl.field).min=0, (dccl.field).max=20];
10}11}
@@ -13,6 +14,7 @@
13{14{
14 option (dccl.msg).id = 5;15 option (dccl.msg).id = 5;
15 option (dccl.msg).max_bytes = 32;16 option (dccl.msg).max_bytes = 32;
17 option (dccl.msg).codec_version = 3;
1618
17 optional bool bool_val = 1;19 optional bool bool_val = 1;
18}20}
@@ -21,6 +23,7 @@
21{23{
22 option (dccl.msg).id = 6;24 option (dccl.msg).id = 6;
23 option (dccl.msg).max_bytes = 32;25 option (dccl.msg).max_bytes = 32;
26 option (dccl.msg).codec_version = 3;
2427
25 optional string string_val = 1 [(dccl.field).max_length=10];28 optional string string_val = 1 [(dccl.field).max_length=10];
26}29}
2730
=== added directory 'src/test/dccl_v2_all_fields'
=== added file 'src/test/dccl_v2_all_fields/CMakeLists.txt'
--- src/test/dccl_v2_all_fields/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/test/dccl_v2_all_fields/CMakeLists.txt 2014-08-27 16:27:22 +0000
@@ -0,0 +1,6 @@
1protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto)
2
3add_executable(dccl_test_v2_all_fields test.cpp ${PROTO_SRCS} ${PROTO_HDRS})
4target_link_libraries(dccl_test_v2_all_fields dccl)
5
6add_test(dccl_test_v2_all_fields ${dccl_BIN_DIR}/dccl_test_v2_all_fields)
07
=== added file 'src/test/dccl_v2_all_fields/test.cpp'
--- src/test/dccl_v2_all_fields/test.cpp 1970-01-01 00:00:00 +0000
+++ src/test/dccl_v2_all_fields/test.cpp 2014-08-27 16:27:22 +0000
@@ -0,0 +1,175 @@
1// Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes)
2// Massachusetts Institute of Technology (2007-)
3// Woods Hole Oceanographic Institution (2007-)
4// DCCL Developers Team (https://launchpad.net/~dccl-dev)
5//
6//
7// This file is part of the Dynamic Compact Control Language Library
8// ("DCCL").
9//
10// DCCL is free software: you can redistribute them and/or modify
11// them under the terms of the GNU Lesser General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// DCCL is distributed in the hope that they will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22
23
24// tests all protobuf types with _default codecs, repeat and non repeat
25
26#include <fstream>
27
28#include <google/protobuf/descriptor.pb.h>
29
30#include "dccl/codec.h"
31#include "test.pb.h"
32#include "dccl/binary.h"
33
34void decode_check(const std::string& encoded);
35dccl::Codec codec;
36TestMsg msg_in;
37
38int main(int argc, char* argv[])
39{
40 dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
41
42 int i = 0;
43 msg_in.set_double_default_optional(++i + 0.1);
44 msg_in.set_float_default_optional(++i + 0.2);
45
46 msg_in.set_int32_default_optional(++i);
47 msg_in.set_int64_default_optional(-++i);
48 msg_in.set_uint32_default_optional(++i);
49 msg_in.set_uint64_default_optional(++i);
50 msg_in.set_sint32_default_optional(-++i);
51 msg_in.set_sint64_default_optional(++i);
52 msg_in.set_fixed32_default_optional(++i);
53 msg_in.set_fixed64_default_optional(++i);
54 msg_in.set_sfixed32_default_optional(++i);
55 msg_in.set_sfixed64_default_optional(-++i);
56
57 msg_in.set_bool_default_optional(true);
58
59 msg_in.set_string_default_optional("abc123");
60 msg_in.set_bytes_default_optional(dccl::hex_decode("00112233aabbcc1234"));
61
62 msg_in.set_enum_default_optional(ENUM_C);
63 msg_in.mutable_msg_default_optional()->set_val(++i + 0.3);
64 msg_in.mutable_msg_default_optional()->mutable_msg()->set_val(++i);
65
66 msg_in.set_double_default_required(++i + 0.1);
67 msg_in.set_float_default_required(++i + 0.2);
68
69 msg_in.set_int32_default_required(++i);
70 msg_in.set_int64_default_required(-++i);
71 msg_in.set_uint32_default_required(++i);
72 msg_in.set_uint64_default_required(++i);
73 msg_in.set_sint32_default_required(-++i);
74 msg_in.set_sint64_default_required(++i);
75 msg_in.set_fixed32_default_required(++i);
76 msg_in.set_fixed64_default_required(++i);
77 msg_in.set_sfixed32_default_required(++i);
78 msg_in.set_sfixed64_default_required(-++i);
79
80 msg_in.set_bool_default_required(true);
81
82 msg_in.set_string_default_required("abc123");
83 msg_in.set_bytes_default_required(dccl::hex_decode("00112233aabbcc1234"));
84
85 msg_in.set_enum_default_required(ENUM_C);
86 msg_in.mutable_msg_default_required()->set_val(++i + 0.3);
87 msg_in.mutable_msg_default_required()->mutable_msg()->set_val(++i);
88
89
90 for(int j = 0; j < 2; ++j)
91 {
92 msg_in.add_double_default_repeat(++i + 0.1);
93 msg_in.add_float_default_repeat(++i + 0.2);
94
95 msg_in.add_int32_default_repeat(++i);
96 msg_in.add_int64_default_repeat(-++i);
97 msg_in.add_uint32_default_repeat(++i);
98 msg_in.add_uint64_default_repeat(++i);
99 msg_in.add_sint32_default_repeat(-++i);
100 msg_in.add_sint64_default_repeat(++i);
101 msg_in.add_fixed32_default_repeat(++i);
102 msg_in.add_fixed64_default_repeat(++i);
103 msg_in.add_sfixed32_default_repeat(++i);
104 msg_in.add_sfixed64_default_repeat(-++i);
105
106 msg_in.add_bool_default_repeat(true);
107
108 msg_in.add_string_default_repeat("abc123");
109
110 if(j)
111 msg_in.add_bytes_default_repeat(dccl::hex_decode("00aabbcc"));
112 else
113 msg_in.add_bytes_default_repeat(dccl::hex_decode("ffeedd12"));
114
115 msg_in.add_enum_default_repeat(static_cast<Enum1>((++i % 3) + 1));
116 EmbeddedMsg1* em_msg = msg_in.add_msg_default_repeat();
117 em_msg->set_val(++i + 0.3);
118 em_msg->mutable_msg()->set_val(++i);
119 }
120
121 codec.info(msg_in.GetDescriptor());
122
123 std::ofstream fout("/tmp/testmessage.pb");
124 msg_in.SerializeToOstream(&fout);
125
126
127 std::cout << "Message in:\n" << msg_in.DebugString() << std::endl;
128
129 codec.load(msg_in.GetDescriptor());
130
131 std::cout << "Try encode..." << std::endl;
132 std::string bytes;
133 codec.encode(&bytes, msg_in);
134 std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl;
135
136 std::cout << "Try decode..." << std::endl;
137 decode_check(bytes);
138
139 // make sure DCCL defaults stay wire compatible
140 decode_check(dccl::hex_decode("047f277b9628060000b95660c0b0188000d8c0132858800008000dc2c4c6626466024488cca8ee324bd05c3f23af0000ad9112a09509788013e0820b18e0005ed0204c6c2c4666062042644675975982c65235f10a00ad718a5801000000905f27121600000000a0170050640300309201001a0b00007d320a0000a61a0070b20100a81b00d09c6f0000a0401026361643102636160300f0dfbd5b2280ea2e330f3da59a2100aabfa55a000000000000000000000000"));
141
142 // run a bunch of tests with random strings
143 std::string random = bytes;
144 for(unsigned i = 0; i < 10; ++i)
145 {
146 random[(rand() % (bytes.size()-1)+1)] = rand() % 256;
147 std::cout << "Using junk bytes: " << dccl::hex_encode(random) << std::endl;
148
149 try
150 {
151 TestMsg msg_out;
152 codec.decode(random, &msg_out);
153 }
154 catch(dccl::Exception&)
155 {
156 }
157 }
158
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches