Merge lp:~tes/dccl/3.0-codec-groups into lp:~dccl-dev/dccl/3.0
- 3.0-codec-groups
- Merge into 3.0
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 |
Related bugs: | |
Related blueprints: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Murphy (community) | Approve | ||
Review via email: mp+216939@code.launchpad.net |
Commit message
Description of the change
Two blueprints implemented:
1. http://
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://
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.
- 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
toby schneider (tes) wrote : | # |
The deprecation warning (1.) is included in this merge.
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2014-01-06 17:25:02 +0000 | |||
3 | +++ CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
4 | @@ -72,7 +72,7 @@ | |||
5 | 72 | install(DIRECTORY ${dccl_INC_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include | 72 | install(DIRECTORY ${dccl_INC_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include |
6 | 73 | FILES_MATCHING PATTERN "*.h" PATTERN "*.proto" PATTERN "test*" EXCLUDE) | 73 | FILES_MATCHING PATTERN "*.h" PATTERN "*.proto" PATTERN "test*" EXCLUDE) |
7 | 74 | 74 | ||
9 | 75 | install(EXPORT dccl-config DESTINATION share/${PROJECTNAME}/cmake) | 75 | install(EXPORT dccl-config DESTINATION share/dccl/cmake) |
10 | 76 | 76 | ||
11 | 77 | ## let cmake know where the headers are | 77 | ## let cmake know where the headers are |
12 | 78 | include_directories(${dccl_INC_DIR}) | 78 | include_directories(${dccl_INC_DIR}) |
13 | @@ -132,10 +132,8 @@ | |||
14 | 132 | include_directories(${Cryptopp_INCLUDE_DIRS}) | 132 | include_directories(${Cryptopp_INCLUDE_DIRS}) |
15 | 133 | endif() | 133 | endif() |
16 | 134 | 134 | ||
17 | 135 | |||
18 | 135 | ## start adding subdirectories | 136 | ## start adding subdirectories |
19 | 136 | add_subdirectory(src) | 137 | add_subdirectory(src) |
20 | 137 | 138 | ||
21 | 138 | ## export a file for folks to use | ||
22 | 139 | export(TARGETS dccl FILE ${CMAKE_BINARY_DIR}/dccl-config.cmake) | ||
23 | 140 | file(APPEND ${CMAKE_BINARY_DIR}/dccl-config.cmake "set(DCCL_INCLUDE_DIR \"${dccl_INC_DIR}\")") | ||
24 | 141 | 139 | ||
25 | 142 | 140 | ||
26 | === modified file 'src/CMakeLists.txt' | |||
27 | --- src/CMakeLists.txt 2014-01-08 22:30:52 +0000 | |||
28 | +++ src/CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
29 | @@ -10,9 +10,12 @@ | |||
30 | 10 | codec.cpp | 10 | codec.cpp |
31 | 11 | field_codec.cpp | 11 | field_codec.cpp |
32 | 12 | field_codec_message_stack.cpp | 12 | field_codec_message_stack.cpp |
33 | 13 | field_codec_default.cpp | ||
34 | 14 | field_codec_default_message.cpp | ||
35 | 15 | field_codec_manager.cpp | 13 | field_codec_manager.cpp |
36 | 14 | field_codec_id.cpp | ||
37 | 15 | codecs2/field_codec_default.cpp | ||
38 | 16 | codecs2/field_codec_default_message.cpp | ||
39 | 17 | codecs3/field_codec_default_message.cpp | ||
40 | 18 | codecs3/field_codec_default.cpp | ||
41 | 16 | type_helper.cpp | 19 | type_helper.cpp |
42 | 17 | bitset.cpp | 20 | bitset.cpp |
43 | 18 | dynamic_protobuf_manager.cpp | 21 | dynamic_protobuf_manager.cpp |
44 | @@ -32,14 +35,21 @@ | |||
45 | 32 | option(build_arithmetic "Build arithmetic coders shared library" ON) | 35 | option(build_arithmetic "Build arithmetic coders shared library" ON) |
46 | 33 | option(build_ccl "Build Compact Control Language (CCL) legacy support shared library" ON) | 36 | option(build_ccl "Build Compact Control Language (CCL) legacy support shared library" ON) |
47 | 34 | 37 | ||
48 | 38 | set(DCCL_EXPORT_TARGETS dccl) | ||
49 | 39 | |||
50 | 35 | if(build_ccl) | 40 | if(build_ccl) |
51 | 36 | add_subdirectory(ccl) | 41 | add_subdirectory(ccl) |
52 | 42 | set(DCCL_EXPORT_TARGETS ${DCCL_EXPORT_TARGETS} dccl_ccl_compat) | ||
53 | 37 | endif() | 43 | endif() |
54 | 38 | 44 | ||
55 | 39 | if(build_arithmetic) | 45 | if(build_arithmetic) |
56 | 40 | add_subdirectory(arithmetic) | 46 | add_subdirectory(arithmetic) |
57 | 47 | set(DCCL_EXPORT_TARGETS ${DCCL_EXPORT_TARGETS} dccl_arithmetic) | ||
58 | 41 | endif() | 48 | endif() |
59 | 42 | 49 | ||
60 | 50 | export(TARGETS ${DCCL_EXPORT_TARGETS} FILE ${CMAKE_BINARY_DIR}/dccl-config.cmake) | ||
61 | 51 | file(APPEND ${CMAKE_BINARY_DIR}/dccl-config.cmake "set(DCCL_INCLUDE_DIR \"${dccl_INC_DIR}\")") | ||
62 | 52 | |||
63 | 43 | if(enable_testing) | 53 | if(enable_testing) |
64 | 44 | add_subdirectory(test) | 54 | add_subdirectory(test) |
65 | 45 | endif() | 55 | endif() |
66 | 46 | 56 | ||
67 | === modified file 'src/apps/dccl/dccl_tool.cpp' | |||
68 | --- src/apps/dccl/dccl_tool.cpp 2014-04-22 20:08:20 +0000 | |||
69 | +++ src/apps/dccl/dccl_tool.cpp 2014-08-27 16:27:22 +0000 | |||
70 | @@ -26,6 +26,8 @@ | |||
71 | 26 | 26 | ||
72 | 27 | 27 | ||
73 | 28 | #include <sstream> | 28 | #include <sstream> |
74 | 29 | #include <fstream> | ||
75 | 30 | |||
76 | 29 | 31 | ||
77 | 30 | #include <google/protobuf/descriptor.h> | 32 | #include <google/protobuf/descriptor.h> |
78 | 31 | #include <google/protobuf/text_format.h> | 33 | #include <google/protobuf/text_format.h> |
79 | @@ -40,13 +42,16 @@ | |||
80 | 40 | #include "dccl_tool.pb.h" | 42 | #include "dccl_tool.pb.h" |
81 | 41 | 43 | ||
82 | 42 | enum Action { NO_ACTION, ENCODE, DECODE, ANALYZE, DISP_PROTO }; | 44 | enum Action { NO_ACTION, ENCODE, DECODE, ANALYZE, DISP_PROTO }; |
84 | 43 | enum Format { TEXTFORMAT, HEX, BASE64 }; | 45 | enum Format { BINARY, TEXTFORMAT, HEX, BASE64 }; |
85 | 44 | 46 | ||
86 | 45 | struct Config | 47 | struct Config |
87 | 46 | { | 48 | { |
88 | 47 | Config() | 49 | Config() |
89 | 48 | : action(NO_ACTION), | 50 | : action(NO_ACTION), |
91 | 49 | format(HEX) | 51 | format(BINARY), |
92 | 52 | id_codec(dccl::Codec::default_id_codec_name()), | ||
93 | 53 | verbose(false), | ||
94 | 54 | omit_prefix(false) | ||
95 | 50 | { } | 55 | { } |
96 | 51 | 56 | ||
97 | 52 | Action action; | 57 | Action action; |
98 | @@ -55,11 +60,14 @@ | |||
99 | 55 | std::set<std::string> message; | 60 | std::set<std::string> message; |
100 | 56 | std::set<std::string> proto_file; | 61 | std::set<std::string> proto_file; |
101 | 57 | Format format; | 62 | Format format; |
102 | 63 | std::string id_codec; | ||
103 | 64 | bool verbose; | ||
104 | 65 | bool omit_prefix; | ||
105 | 58 | }; | 66 | }; |
106 | 59 | 67 | ||
107 | 60 | 68 | ||
108 | 61 | void analyze(dccl::Codec& dccl, const Config& cfg); | 69 | void analyze(dccl::Codec& dccl, const Config& cfg); |
110 | 62 | void encode(dccl::Codec& dccl, const Config& cfg); | 70 | void encode(dccl::Codec& dccl, Config& cfg); |
111 | 63 | void decode(dccl::Codec& dccl, const Config& cfg); | 71 | void decode(dccl::Codec& dccl, const Config& cfg); |
112 | 64 | void disp_proto(dccl::Codec& dccl, const Config& cfg); | 72 | void disp_proto(dccl::Codec& dccl, const Config& cfg); |
113 | 65 | 73 | ||
114 | @@ -67,67 +75,95 @@ | |||
115 | 67 | void load_desc(dccl::Codec* dccl, const google::protobuf::Descriptor* desc, const std::string& name); | 75 | void load_desc(dccl::Codec* dccl, const google::protobuf::Descriptor* desc, const std::string& name); |
116 | 68 | void parse_options(int argc, char* argv[], Config* cfg); | 76 | void parse_options(int argc, char* argv[], Config* cfg); |
117 | 69 | 77 | ||
118 | 78 | |||
119 | 70 | int main(int argc, char* argv[]) | 79 | int main(int argc, char* argv[]) |
120 | 71 | { | 80 | { |
180 | 72 | Config cfg; | 81 | std::vector<void *> dl_handles; |
181 | 73 | parse_options(argc, argv, &cfg); | 82 | { |
182 | 74 | 83 | Config cfg; | |
183 | 75 | dccl::dlog.connect(dccl::logger::WARN_PLUS, &std::cerr); | 84 | parse_options(argc, argv, &cfg); |
184 | 76 | 85 | ||
185 | 77 | dccl::DynamicProtobufManager::enable_compilation(); | 86 | if(!cfg.verbose) |
186 | 78 | 87 | dccl::dlog.connect(dccl::logger::WARN_PLUS, &std::cerr); | |
187 | 79 | for(std::set<std::string>::const_iterator it = cfg.include.begin(), | 88 | else |
188 | 80 | end = cfg.include.end(); it != end; ++it) | 89 | dccl::dlog.connect(dccl::logger::DEBUG1_PLUS, &std::cerr); |
189 | 81 | dccl::DynamicProtobufManager::add_include_path(*it); | 90 | |
190 | 82 | 91 | dccl::DynamicProtobufManager::enable_compilation(); | |
191 | 83 | dccl::Codec dccl; | 92 | |
192 | 84 | for(std::set<std::string>::const_iterator it = cfg.dlopen.begin(), | 93 | for(std::set<std::string>::const_iterator it = cfg.include.begin(), |
193 | 85 | end = cfg.dlopen.end(); it != end; ++it) | 94 | end = cfg.include.end(); it != end; ++it) |
194 | 86 | dccl.load_library(*it); | 95 | dccl::DynamicProtobufManager::add_include_path(*it); |
195 | 87 | 96 | ||
196 | 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(), |
197 | 89 | end = cfg.proto_file.end(); it != end; ++it) | 98 | end = cfg.dlopen.end(); it != end; ++it) |
198 | 90 | { | 99 | { |
199 | 91 | const google::protobuf::FileDescriptor* file_desc = | 100 | void* handle = dlopen(it->c_str(), RTLD_LAZY); |
200 | 92 | dccl::DynamicProtobufManager::load_from_proto_file(*it); | 101 | if(handle) |
201 | 93 | 102 | { | |
202 | 94 | if(!file_desc) | 103 | dl_handles.push_back(handle); |
203 | 95 | { | 104 | } |
204 | 96 | std::cerr << "failed to read in: " << *it << std::endl; | 105 | else |
205 | 97 | exit(EXIT_FAILURE); | 106 | { |
206 | 98 | } | 107 | std::cerr << "Failed to open shared library: " << *it << std::endl; |
207 | 99 | 108 | exit(EXIT_FAILURE); | |
208 | 100 | // if no messages explicity specified, load them all. | 109 | } |
209 | 101 | if(cfg.message.empty()) | 110 | |
210 | 102 | { | 111 | } |
211 | 103 | for(int i = 0, n = file_desc->message_type_count(); i < n; ++i) | 112 | |
212 | 104 | { | 113 | dccl::Codec dccl(cfg.id_codec); |
213 | 105 | const google::protobuf::Descriptor* desc = file_desc->message_type(i); | 114 | for(std::vector<void *>::iterator it = dl_handles.begin(), |
214 | 106 | cfg.message.insert(file_desc->message_type(i)->full_name()); | 115 | n = dl_handles.end(); it != n; ++it) |
215 | 107 | } | 116 | dccl.load_library(*it); |
216 | 108 | } | 117 | |
217 | 109 | } | 118 | bool no_messages_specified = cfg.message.empty(); |
218 | 110 | 119 | for(std::set<std::string>::const_iterator it = cfg.proto_file.begin(), | |
219 | 111 | // Load up all the messages | 120 | end = cfg.proto_file.end(); it != end; ++it) |
220 | 112 | for(std::set<std::string>::const_iterator it = cfg.message.begin(), | 121 | { |
221 | 113 | end = cfg.message.end(); it != end; ++it) | 122 | const google::protobuf::FileDescriptor* file_desc = |
222 | 114 | { | 123 | dccl::DynamicProtobufManager::load_from_proto_file(*it); |
223 | 115 | const google::protobuf::Descriptor* desc = | 124 | |
224 | 116 | dccl::DynamicProtobufManager::find_descriptor(*it); | 125 | if(!file_desc) |
225 | 117 | load_desc(&dccl, desc, *it); | 126 | { |
226 | 118 | } | 127 | std::cerr << "failed to read in: " << *it << std::endl; |
227 | 119 | 128 | exit(EXIT_FAILURE); | |
228 | 120 | switch(cfg.action) | 129 | } |
229 | 121 | { | 130 | |
230 | 122 | case ENCODE: encode(dccl, cfg); break; | 131 | // if no messages explicitly specified, load them all. |
231 | 123 | case DECODE: decode(dccl, cfg); break; | 132 | if(no_messages_specified && cfg.action != ENCODE) |
232 | 124 | case ANALYZE: analyze(dccl, cfg); break; | 133 | { |
233 | 125 | case DISP_PROTO: disp_proto(dccl, cfg); break; | 134 | for(int i = 0, n = file_desc->message_type_count(); i < n; ++i) |
234 | 126 | default: | 135 | { |
235 | 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()); |
236 | 128 | exit(EXIT_SUCCESS); | 137 | } |
237 | 129 | 138 | } | |
238 | 130 | } | 139 | } |
239 | 140 | |||
240 | 141 | // Load up all the messages | ||
241 | 142 | for(std::set<std::string>::const_iterator it = cfg.message.begin(), | ||
242 | 143 | end = cfg.message.end(); it != end; ++it) | ||
243 | 144 | { | ||
244 | 145 | const google::protobuf::Descriptor* desc = | ||
245 | 146 | dccl::DynamicProtobufManager::find_descriptor(*it); | ||
246 | 147 | load_desc(&dccl, desc, *it); | ||
247 | 148 | } | ||
248 | 149 | |||
249 | 150 | switch(cfg.action) | ||
250 | 151 | { | ||
251 | 152 | case ENCODE: encode(dccl, cfg); break; | ||
252 | 153 | case DECODE: decode(dccl, cfg); break; | ||
253 | 154 | case ANALYZE: analyze(dccl, cfg); break; | ||
254 | 155 | case DISP_PROTO: disp_proto(dccl, cfg); break; | ||
255 | 156 | default: | ||
256 | 157 | std::cerr << "No action specified (e.g. analyze, decode, encode). Try --help." << std::endl; | ||
257 | 158 | exit(EXIT_SUCCESS); | ||
258 | 159 | |||
259 | 160 | } | ||
260 | 161 | } | ||
261 | 162 | |||
262 | 163 | for(std::vector<void *>::iterator it = dl_handles.begin(), | ||
263 | 164 | n = dl_handles.end(); it != n; ++it) | ||
264 | 165 | dlclose(*it); | ||
265 | 166 | |||
266 | 131 | } | 167 | } |
267 | 132 | 168 | ||
268 | 133 | 169 | ||
269 | @@ -137,16 +173,14 @@ | |||
270 | 137 | dccl.info_all(&std::cout); | 173 | dccl.info_all(&std::cout); |
271 | 138 | } | 174 | } |
272 | 139 | 175 | ||
274 | 140 | void encode(dccl::Codec& dccl, const Config& cfg) | 176 | void encode(dccl::Codec& dccl, Config& cfg) |
275 | 141 | { | 177 | { |
277 | 142 | if(cfg.message.size() != 1) | 178 | if(cfg.message.size() > 1) |
278 | 143 | { | 179 | { |
280 | 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; |
281 | 145 | exit(EXIT_FAILURE); | 181 | exit(EXIT_FAILURE); |
282 | 146 | } | 182 | } |
286 | 147 | const google::protobuf::Descriptor* desc = | 183 | std::string command_line_name = *cfg.message.begin(); |
284 | 148 | dccl::DynamicProtobufManager::find_descriptor(*cfg.message.begin()); | ||
285 | 149 | int dccl_id = dccl.id(desc); | ||
287 | 150 | 184 | ||
288 | 151 | while(!std::cin.eof()) | 185 | while(!std::cin.eof()) |
289 | 152 | { | 186 | { |
290 | @@ -156,6 +190,50 @@ | |||
291 | 156 | boost::trim(input); | 190 | boost::trim(input); |
292 | 157 | if(input.empty()) | 191 | if(input.empty()) |
293 | 158 | continue; | 192 | continue; |
294 | 193 | |||
295 | 194 | std::string name; | ||
296 | 195 | if(input[0] == '|') | ||
297 | 196 | { | ||
298 | 197 | std::string::size_type close_bracket_pos = input.find('|', 1); | ||
299 | 198 | if(close_bracket_pos == std::string::npos) | ||
300 | 199 | { | ||
301 | 200 | std::cerr << "Incorrectly formatted input: expected '|'" << std::endl; | ||
302 | 201 | exit(EXIT_FAILURE); | ||
303 | 202 | } | ||
304 | 203 | |||
305 | 204 | name = input.substr(1, close_bracket_pos-1); | ||
306 | 205 | if(cfg.message.find(name) == cfg.message.end()) | ||
307 | 206 | { | ||
308 | 207 | const google::protobuf::Descriptor* desc = | ||
309 | 208 | dccl::DynamicProtobufManager::find_descriptor(name); | ||
310 | 209 | load_desc(&dccl, desc, name); | ||
311 | 210 | cfg.message.insert(name); | ||
312 | 211 | } | ||
313 | 212 | |||
314 | 213 | |||
315 | 214 | if(input.size() > close_bracket_pos+1) | ||
316 | 215 | input = input.substr(close_bracket_pos+1); | ||
317 | 216 | else | ||
318 | 217 | input.clear(); | ||
319 | 218 | } | ||
320 | 219 | else | ||
321 | 220 | { | ||
322 | 221 | if(cfg.message.size() == 0) | ||
323 | 222 | { | ||
324 | 223 | std::cerr << "Message name not given with -m or in the input (i.e. '[Name] field1: value field2: value')." << std::endl; | ||
325 | 224 | exit(EXIT_FAILURE); | ||
326 | 225 | } | ||
327 | 226 | |||
328 | 227 | name = command_line_name; | ||
329 | 228 | } | ||
330 | 229 | |||
331 | 230 | const google::protobuf::Descriptor* desc = dccl::DynamicProtobufManager::find_descriptor(name); | ||
332 | 231 | if(desc == 0) | ||
333 | 232 | { | ||
334 | 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; | ||
335 | 234 | exit(EXIT_FAILURE); | ||
336 | 235 | } | ||
337 | 236 | |||
338 | 159 | 237 | ||
339 | 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); |
340 | 161 | google::protobuf::TextFormat::ParseFromString(input, msg.get()); | 239 | google::protobuf::TextFormat::ParseFromString(input, msg.get()); |
341 | @@ -167,6 +245,13 @@ | |||
342 | 167 | switch(cfg.format) | 245 | switch(cfg.format) |
343 | 168 | { | 246 | { |
344 | 169 | default: | 247 | default: |
345 | 248 | case BINARY: | ||
346 | 249 | { | ||
347 | 250 | std::ofstream fout("/dev/stdout", std::ios::binary | std::ios::app); | ||
348 | 251 | fout.write(encoded.data(), encoded.size()); | ||
349 | 252 | break; | ||
350 | 253 | } | ||
351 | 254 | |||
352 | 170 | case TEXTFORMAT: | 255 | case TEXTFORMAT: |
353 | 171 | { | 256 | { |
354 | 172 | 257 | ||
355 | @@ -197,49 +282,61 @@ | |||
356 | 197 | 282 | ||
357 | 198 | void decode(dccl::Codec& dccl, const Config& cfg) | 283 | void decode(dccl::Codec& dccl, const Config& cfg) |
358 | 199 | { | 284 | { |
360 | 200 | if(cfg.message.size() != 1) | 285 | std::string input; |
361 | 286 | if(cfg.format == BINARY) | ||
362 | 201 | { | 287 | { |
365 | 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); |
366 | 203 | exit(EXIT_FAILURE); | 289 | std::ostringstream ostrm; |
367 | 290 | ostrm << fin.rdbuf(); | ||
368 | 291 | input = ostrm.str(); | ||
369 | 204 | } | 292 | } |
372 | 205 | 293 | else | |
371 | 206 | while(!std::cin.eof()) | ||
373 | 207 | { | 294 | { |
381 | 208 | std::string input; | 295 | while(!std::cin.eof()) |
375 | 209 | std::getline (std::cin, input); | ||
376 | 210 | |||
377 | 211 | if(boost::trim_copy(input).empty()) | ||
378 | 212 | continue; | ||
379 | 213 | |||
380 | 214 | switch(cfg.format) | ||
382 | 215 | { | 296 | { |
385 | 216 | default: | 297 | std::string line; |
386 | 217 | case TEXTFORMAT: | 298 | std::getline (std::cin, line); |
387 | 299 | |||
388 | 300 | if(boost::trim_copy(line).empty()) | ||
389 | 301 | continue; | ||
390 | 302 | |||
391 | 303 | switch(cfg.format) | ||
392 | 218 | { | 304 | { |
400 | 219 | boost::trim_if(input, boost::is_any_of("\"")); | 305 | default: |
401 | 220 | 306 | case BINARY: | |
402 | 221 | 307 | break; | |
403 | 222 | ByteString s; | 308 | |
404 | 223 | google::protobuf::TextFormat::ParseFieldValueFromString("\"" + input + "\"", s.GetDescriptor()->FindFieldByNumber(1), &s); | 309 | case TEXTFORMAT: |
405 | 224 | input = s.b(); | 310 | { |
406 | 225 | break; | 311 | boost::trim_if(line, boost::is_any_of("\"")); |
407 | 312 | |||
408 | 313 | |||
409 | 314 | ByteString s; | ||
410 | 315 | google::protobuf::TextFormat::ParseFieldValueFromString("\"" + line + "\"", s.GetDescriptor()->FindFieldByNumber(1), &s); | ||
411 | 316 | input += s.b(); | ||
412 | 317 | break; | ||
413 | 318 | } | ||
414 | 319 | case HEX: | ||
415 | 320 | input += dccl::hex_decode(line); | ||
416 | 321 | break; | ||
417 | 322 | case BASE64: | ||
418 | 323 | std::stringstream instream(line); | ||
419 | 324 | std::stringstream outstream; | ||
420 | 325 | base64::decoder D; | ||
421 | 326 | D.decode(instream, outstream); | ||
422 | 327 | input += outstream.str(); | ||
423 | 328 | break; | ||
424 | 226 | } | 329 | } |
425 | 227 | case HEX: | ||
426 | 228 | input = dccl::hex_decode(input); | ||
427 | 229 | break; | ||
428 | 230 | case BASE64: | ||
429 | 231 | std::string in = input; | ||
430 | 232 | std::stringstream instream(input); | ||
431 | 233 | std::stringstream outstream; | ||
432 | 234 | base64::decoder D; | ||
433 | 235 | D.decode(instream, outstream); | ||
434 | 236 | input = outstream.str(); | ||
435 | 237 | break; | ||
436 | 238 | } | 330 | } |
437 | 331 | } | ||
438 | 239 | 332 | ||
440 | 240 | boost::shared_ptr<google::protobuf::Message> msg = dccl.decode<boost::shared_ptr<google::protobuf::Message> >(input); | 333 | while(!input.empty()) |
441 | 334 | { | ||
442 | 335 | boost::shared_ptr<google::protobuf::Message> msg = dccl.decode<boost::shared_ptr<google::protobuf::Message> >(&input); | ||
443 | 336 | if(!cfg.omit_prefix) | ||
444 | 337 | std::cout << "|" << msg->GetDescriptor()->full_name() << "| "; | ||
445 | 241 | std::cout << msg->ShortDebugString() << std::endl; | 338 | std::cout << msg->ShortDebugString() << std::endl; |
447 | 242 | } | 339 | } |
448 | 243 | } | 340 | } |
449 | 244 | 341 | ||
450 | 245 | void disp_proto(dccl::Codec& dccl, const Config& cfg) | 342 | void disp_proto(dccl::Codec& dccl, const Config& cfg) |
451 | @@ -286,7 +383,10 @@ | |||
452 | 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.")); |
453 | 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.")); |
454 | 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.")); |
456 | 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.")); |
457 | 387 | options.push_back(dccl::Option('v', "verbose", no_argument, "Display extra debugging information.")); | ||
458 | 388 | options.push_back(dccl::Option('o', "omit_prefix", no_argument, "Omit the DCCL type name prefix from the output of decode.")); | ||
459 | 389 | options.push_back(dccl::Option('i', "id_codec", required_argument, "(Advanced) name for a nonstandard DCCL ID codec to use")); | ||
460 | 290 | 390 | ||
461 | 291 | std::vector<option> long_options; | 391 | std::vector<option> long_options; |
462 | 292 | std::string opt_string; | 392 | std::string opt_string; |
463 | @@ -314,6 +414,8 @@ | |||
464 | 314 | cfg->format = HEX; | 414 | cfg->format = HEX; |
465 | 315 | else if(!strcmp(optarg, "base64")) | 415 | else if(!strcmp(optarg, "base64")) |
466 | 316 | cfg->format = BASE64; | 416 | cfg->format = BASE64; |
467 | 417 | else if(!strcmp(optarg, "bin")) | ||
468 | 418 | cfg->format = BINARY; | ||
469 | 317 | else | 419 | else |
470 | 318 | { | 420 | { |
471 | 319 | std::cerr << "Invalid format '" << optarg << "'" << std::endl; | 421 | std::cerr << "Invalid format '" << optarg << "'" << std::endl; |
472 | @@ -336,6 +438,9 @@ | |||
473 | 336 | case 'l': cfg->dlopen.insert(optarg); break; | 438 | case 'l': cfg->dlopen.insert(optarg); break; |
474 | 337 | case 'm': cfg->message.insert(optarg); break; | 439 | case 'm': cfg->message.insert(optarg); break; |
475 | 338 | case 'f': cfg->proto_file.insert(optarg); break; | 440 | case 'f': cfg->proto_file.insert(optarg); break; |
476 | 441 | case 'i': cfg->id_codec = optarg; break; | ||
477 | 442 | case 'v': cfg->verbose = true; break; | ||
478 | 443 | case 'o': cfg->omit_prefix = true; break; | ||
479 | 339 | 444 | ||
480 | 340 | case 'h': | 445 | case 'h': |
481 | 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; |
482 | 342 | 447 | ||
483 | === modified file 'src/arithmetic/field_codec_arithmetic.cpp' | |||
484 | --- src/arithmetic/field_codec_arithmetic.cpp 2013-06-18 12:55:43 +0000 | |||
485 | +++ src/arithmetic/field_codec_arithmetic.cpp 2014-08-27 16:27:22 +0000 | |||
486 | @@ -38,9 +38,9 @@ | |||
487 | 38 | 38 | ||
488 | 39 | // shared library load | 39 | // shared library load |
489 | 40 | 40 | ||
491 | 41 | extern "C" | 41 | struct CodecLoader |
492 | 42 | { | 42 | { |
494 | 43 | void dccl3_load(dccl::Codec* dccl) | 43 | CodecLoader() |
495 | 44 | { | 44 | { |
496 | 45 | using namespace dccl; | 45 | using namespace dccl; |
497 | 46 | 46 | ||
498 | @@ -53,6 +53,29 @@ | |||
499 | 53 | FieldCodecManager::add<ArithmeticFieldCodec<bool> >("_arithmetic"); | 53 | FieldCodecManager::add<ArithmeticFieldCodec<bool> >("_arithmetic"); |
500 | 54 | FieldCodecManager::add<ArithmeticFieldCodec<const google::protobuf::EnumValueDescriptor*> >("_arithmetic"); | 54 | FieldCodecManager::add<ArithmeticFieldCodec<const google::protobuf::EnumValueDescriptor*> >("_arithmetic"); |
501 | 55 | } | 55 | } |
502 | 56 | ~CodecLoader() | ||
503 | 57 | { | ||
504 | 58 | using namespace dccl; | ||
505 | 59 | |||
506 | 60 | FieldCodecManager::remove<ArithmeticFieldCodec<int32> >("_arithmetic"); | ||
507 | 61 | FieldCodecManager::remove<ArithmeticFieldCodec<int64> >("_arithmetic"); | ||
508 | 62 | FieldCodecManager::remove<ArithmeticFieldCodec<uint32> >("_arithmetic"); | ||
509 | 63 | FieldCodecManager::remove<ArithmeticFieldCodec<uint64> >("_arithmetic"); | ||
510 | 64 | FieldCodecManager::remove<ArithmeticFieldCodec<double> >("_arithmetic"); | ||
511 | 65 | FieldCodecManager::remove<ArithmeticFieldCodec<float> >("_arithmetic"); | ||
512 | 66 | FieldCodecManager::remove<ArithmeticFieldCodec<bool> >("_arithmetic"); | ||
513 | 67 | FieldCodecManager::remove<ArithmeticFieldCodec<const google::protobuf::EnumValueDescriptor*> >("_arithmetic"); | ||
514 | 68 | } | ||
515 | 69 | }; | ||
516 | 70 | |||
517 | 71 | |||
518 | 72 | static CodecLoader loader; | ||
519 | 73 | |||
520 | 74 | extern "C" | ||
521 | 75 | { | ||
522 | 76 | void dccl3_load(dccl::Codec* dccl) | ||
523 | 77 | { | ||
524 | 78 | } | ||
525 | 56 | } | 79 | } |
526 | 57 | 80 | ||
527 | 58 | dccl::Model::symbol_type dccl::Model::value_to_symbol(value_type value) const | 81 | dccl::Model::symbol_type dccl::Model::value_to_symbol(value_type value) const |
528 | 59 | 82 | ||
529 | === modified file 'src/binary.h' | |||
530 | --- src/binary.h 2014-04-22 20:10:37 +0000 | |||
531 | +++ src/binary.h 2014-08-27 16:27:22 +0000 | |||
532 | @@ -29,6 +29,8 @@ | |||
533 | 29 | #include <sstream> | 29 | #include <sstream> |
534 | 30 | 30 | ||
535 | 31 | #include "dccl/common.h" | 31 | #include "dccl/common.h" |
536 | 32 | #include "dccl/b64/encode.h" | ||
537 | 33 | #include "dccl/b64/decode.h" | ||
538 | 32 | 34 | ||
539 | 33 | namespace dccl | 35 | namespace dccl |
540 | 34 | { | 36 | { |
541 | @@ -124,6 +126,27 @@ | |||
542 | 124 | hex_encode(in, &out); | 126 | hex_encode(in, &out); |
543 | 125 | return out; | 127 | return out; |
544 | 126 | } | 128 | } |
545 | 129 | |||
546 | 130 | |||
547 | 131 | inline std::string b64_encode(const std::string& in) | ||
548 | 132 | { | ||
549 | 133 | std::stringstream instream(in); | ||
550 | 134 | std::stringstream outstream; | ||
551 | 135 | base64::encoder D; | ||
552 | 136 | D.encode(instream, outstream); | ||
553 | 137 | return outstream.str(); | ||
554 | 138 | } | ||
555 | 139 | |||
556 | 140 | inline std::string b64_decode(const std::string& in) | ||
557 | 141 | { | ||
558 | 142 | std::stringstream instream(in); | ||
559 | 143 | std::stringstream outstream; | ||
560 | 144 | base64::decoder D; | ||
561 | 145 | D.decode(instream, outstream); | ||
562 | 146 | return outstream.str(); | ||
563 | 147 | } | ||
564 | 148 | |||
565 | 149 | |||
566 | 127 | 150 | ||
567 | 128 | /// \return ceil(log2(v)) | 151 | /// \return ceil(log2(v)) |
568 | 129 | inline unsigned ceil_log2(dccl::uint64 v) | 152 | inline unsigned ceil_log2(dccl::uint64 v) |
569 | 130 | 153 | ||
570 | === modified file 'src/ccl/CMakeLists.txt' | |||
571 | --- src/ccl/CMakeLists.txt 2014-01-06 17:25:02 +0000 | |||
572 | +++ src/ccl/CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
573 | @@ -17,7 +17,6 @@ | |||
574 | 17 | set_target_properties(dccl_ccl_compat | 17 | set_target_properties(dccl_ccl_compat |
575 | 18 | PROPERTIES VERSION "${DCCL_VERSION}" SOVERSION "${DCCL_SOVERSION}") | 18 | PROPERTIES VERSION "${DCCL_VERSION}" SOVERSION "${DCCL_SOVERSION}") |
576 | 19 | 19 | ||
577 | 20 | |||
578 | 21 | install(TARGETS dccl_ccl_compat EXPORT dccl-config | 20 | install(TARGETS dccl_ccl_compat EXPORT dccl-config |
579 | 22 | LIBRARY DESTINATION lib | 21 | LIBRARY DESTINATION lib |
580 | 23 | ARCHIVE DESTINATION lib) | 22 | ARCHIVE DESTINATION lib) |
581 | 24 | 23 | ||
582 | === modified file 'src/ccl/ccl_compatibility.cpp' | |||
583 | --- src/ccl/ccl_compatibility.cpp 2013-06-18 12:55:43 +0000 | |||
584 | +++ src/ccl/ccl_compatibility.cpp 2014-08-27 16:27:22 +0000 | |||
585 | @@ -31,27 +31,54 @@ | |||
586 | 31 | 31 | ||
587 | 32 | // shared library load | 32 | // shared library load |
588 | 33 | 33 | ||
589 | 34 | struct CodecLoader | ||
590 | 35 | { | ||
591 | 36 | CodecLoader() | ||
592 | 37 | { | ||
593 | 38 | using namespace dccl; | ||
594 | 39 | FieldCodecManager::add<LegacyCCLIdentifierCodec>("dccl.ccl.id"); | ||
595 | 40 | |||
596 | 41 | FieldCodecManager::add<LegacyCCLLatLonCompressedCodec>("_ccl_latloncompressed"); | ||
597 | 42 | FieldCodecManager::add<LegacyCCLFixAgeCodec>("_ccl_fix_age"); | ||
598 | 43 | FieldCodecManager::add<LegacyCCLTimeDateCodec>("_ccl_time_date"); | ||
599 | 44 | FieldCodecManager::add<LegacyCCLHeadingCodec>("_ccl_heading"); | ||
600 | 45 | FieldCodecManager::add<LegacyCCLDepthCodec>("_ccl_depth"); | ||
601 | 46 | FieldCodecManager::add<LegacyCCLVelocityCodec>("_ccl_velocity"); | ||
602 | 47 | FieldCodecManager::add<LegacyCCLWattsCodec>("_ccl_watts"); | ||
603 | 48 | FieldCodecManager::add<LegacyCCLGFIPitchOilCodec>("_ccl_gfi_pitch_oil"); | ||
604 | 49 | FieldCodecManager::add<LegacyCCLSpeedCodec>("_ccl_speed"); | ||
605 | 50 | FieldCodecManager::add<LegacyCCLHiResAltitudeCodec>("_ccl_hires_altitude"); | ||
606 | 51 | FieldCodecManager::add<LegacyCCLTemperatureCodec>("_ccl_temperature"); | ||
607 | 52 | FieldCodecManager::add<LegacyCCLSalinityCodec>("_ccl_salinity"); | ||
608 | 53 | FieldCodecManager::add<LegacyCCLSoundSpeedCodec>("_ccl_sound_speed"); | ||
609 | 54 | } | ||
610 | 55 | ~CodecLoader() | ||
611 | 56 | { | ||
612 | 57 | using namespace dccl; | ||
613 | 58 | FieldCodecManager::remove<LegacyCCLIdentifierCodec>("dccl.ccl.id"); | ||
614 | 59 | |||
615 | 60 | FieldCodecManager::remove<LegacyCCLLatLonCompressedCodec>("_ccl_latloncompressed"); | ||
616 | 61 | FieldCodecManager::remove<LegacyCCLFixAgeCodec>("_ccl_fix_age"); | ||
617 | 62 | FieldCodecManager::remove<LegacyCCLTimeDateCodec>("_ccl_time_date"); | ||
618 | 63 | FieldCodecManager::remove<LegacyCCLHeadingCodec>("_ccl_heading"); | ||
619 | 64 | FieldCodecManager::remove<LegacyCCLDepthCodec>("_ccl_depth"); | ||
620 | 65 | FieldCodecManager::remove<LegacyCCLVelocityCodec>("_ccl_velocity"); | ||
621 | 66 | FieldCodecManager::remove<LegacyCCLWattsCodec>("_ccl_watts"); | ||
622 | 67 | FieldCodecManager::remove<LegacyCCLGFIPitchOilCodec>("_ccl_gfi_pitch_oil"); | ||
623 | 68 | FieldCodecManager::remove<LegacyCCLSpeedCodec>("_ccl_speed"); | ||
624 | 69 | FieldCodecManager::remove<LegacyCCLHiResAltitudeCodec>("_ccl_hires_altitude"); | ||
625 | 70 | FieldCodecManager::remove<LegacyCCLTemperatureCodec>("_ccl_temperature"); | ||
626 | 71 | FieldCodecManager::remove<LegacyCCLSalinityCodec>("_ccl_salinity"); | ||
627 | 72 | FieldCodecManager::remove<LegacyCCLSoundSpeedCodec>("_ccl_sound_speed"); | ||
628 | 73 | } | ||
629 | 74 | }; | ||
630 | 75 | |||
631 | 76 | static CodecLoader loader; | ||
632 | 34 | 77 | ||
633 | 35 | extern "C" | 78 | extern "C" |
634 | 36 | { | 79 | { |
635 | 37 | void dccl3_load(dccl::Codec* dccl) | 80 | void dccl3_load(dccl::Codec* dccl) |
653 | 38 | { | 81 | { |
637 | 39 | using namespace dccl; | ||
638 | 40 | |||
639 | 41 | FieldCodecManager::add<LegacyCCLLatLonCompressedCodec>("_ccl_latloncompressed"); | ||
640 | 42 | FieldCodecManager::add<LegacyCCLFixAgeCodec>("_ccl_fix_age"); | ||
641 | 43 | FieldCodecManager::add<LegacyCCLTimeDateCodec>("_ccl_time_date"); | ||
642 | 44 | FieldCodecManager::add<LegacyCCLHeadingCodec>("_ccl_heading"); | ||
643 | 45 | FieldCodecManager::add<LegacyCCLDepthCodec>("_ccl_depth"); | ||
644 | 46 | FieldCodecManager::add<LegacyCCLVelocityCodec>("_ccl_velocity"); | ||
645 | 47 | FieldCodecManager::add<LegacyCCLWattsCodec>("_ccl_watts"); | ||
646 | 48 | FieldCodecManager::add<LegacyCCLGFIPitchOilCodec>("_ccl_gfi_pitch_oil"); | ||
647 | 49 | FieldCodecManager::add<LegacyCCLSpeedCodec>("_ccl_speed"); | ||
648 | 50 | FieldCodecManager::add<LegacyCCLHiResAltitudeCodec>("_ccl_hires_altitude"); | ||
649 | 51 | FieldCodecManager::add<LegacyCCLTemperatureCodec>("_ccl_temperature"); | ||
650 | 52 | FieldCodecManager::add<LegacyCCLSalinityCodec>("_ccl_salinity"); | ||
651 | 53 | FieldCodecManager::add<LegacyCCLSoundSpeedCodec>("_ccl_sound_speed"); | ||
652 | 54 | |||
654 | 55 | dccl->load<dccl::protobuf::CCLMDATEmpty>(); | 82 | dccl->load<dccl::protobuf::CCLMDATEmpty>(); |
655 | 56 | dccl->load<dccl::protobuf::CCLMDATRedirect>(); | 83 | dccl->load<dccl::protobuf::CCLMDATRedirect>(); |
656 | 57 | dccl->load<dccl::protobuf::CCLMDATBathy>(); | 84 | dccl->load<dccl::protobuf::CCLMDATBathy>(); |
657 | 58 | 85 | ||
658 | === modified file 'src/ccl/ccl_compatibility.h' | |||
659 | --- src/ccl/ccl_compatibility.h 2013-09-12 16:23:45 +0000 | |||
660 | +++ src/ccl/ccl_compatibility.h 2014-08-27 16:27:22 +0000 | |||
661 | @@ -24,7 +24,8 @@ | |||
662 | 24 | #ifndef DCCLCCLCOMPATIBILITY20120426H | 24 | #ifndef DCCLCCLCOMPATIBILITY20120426H |
663 | 25 | #define DCCLCCLCOMPATIBILITY20120426H | 25 | #define DCCLCCLCOMPATIBILITY20120426H |
664 | 26 | 26 | ||
666 | 27 | #include "dccl/field_codec_default.h" | 27 | #include "dccl/codecs2/field_codec_default.h" |
667 | 28 | #include "dccl/field_codec_id.h" | ||
668 | 28 | #include "dccl/ccl/protobuf/ccl.pb.h" | 29 | #include "dccl/ccl/protobuf/ccl.pb.h" |
669 | 29 | #include "dccl/ccl/protobuf/ccl_extensions.pb.h" | 30 | #include "dccl/ccl/protobuf/ccl_extensions.pb.h" |
670 | 30 | 31 | ||
671 | @@ -33,8 +34,6 @@ | |||
672 | 33 | void dccl3_load(dccl::Codec* dccl); | 34 | void dccl3_load(dccl::Codec* dccl); |
673 | 34 | } | 35 | } |
674 | 35 | 36 | ||
675 | 36 | |||
676 | 37 | |||
677 | 38 | namespace dccl | 37 | namespace dccl |
678 | 39 | { | 38 | { |
679 | 40 | const unsigned char DCCL_CCL_HEADER = 32; | 39 | const unsigned char DCCL_CCL_HEADER = 32; |
680 | @@ -117,7 +116,7 @@ | |||
681 | 117 | enum { LATLON_COMPRESSED_BYTE_SIZE = 3 }; | 116 | enum { LATLON_COMPRESSED_BYTE_SIZE = 3 }; |
682 | 118 | }; | 117 | }; |
683 | 119 | 118 | ||
685 | 120 | class LegacyCCLFixAgeCodec : public dccl::DefaultNumericFieldCodec<dccl::uint32> | 119 | class LegacyCCLFixAgeCodec : public dccl::v2::DefaultNumericFieldCodec<dccl::uint32> |
686 | 121 | { | 120 | { |
687 | 122 | private: | 121 | private: |
688 | 123 | dccl::Bitset encode() | 122 | dccl::Bitset encode() |
689 | 124 | 123 | ||
690 | === modified file 'src/codec.cpp' | |||
691 | --- src/codec.cpp 2014-04-22 20:10:37 +0000 | |||
692 | +++ src/codec.cpp 2014-08-27 16:27:22 +0000 | |||
693 | @@ -38,7 +38,9 @@ | |||
694 | 38 | #endif // HAS_CRYPTOPP | 38 | #endif // HAS_CRYPTOPP |
695 | 39 | 39 | ||
696 | 40 | #include "dccl/codec.h" | 40 | #include "dccl/codec.h" |
698 | 41 | #include "field_codec_default.h" | 41 | #include "dccl/codecs2/field_codec_default.h" |
699 | 42 | #include "dccl/codecs3/field_codec_default.h" | ||
700 | 43 | #include "dccl/field_codec_id.h" | ||
701 | 42 | 44 | ||
702 | 43 | #include "dccl/protobuf/option_extensions.pb.h" | 45 | #include "dccl/protobuf/option_extensions.pb.h" |
703 | 44 | 46 | ||
704 | @@ -63,7 +65,7 @@ | |||
705 | 63 | dccl::Codec::Codec(const std::string& dccl_id_codec) | 65 | dccl::Codec::Codec(const std::string& dccl_id_codec) |
706 | 64 | : id_codec_(dccl_id_codec) | 66 | : id_codec_(dccl_id_codec) |
707 | 65 | { | 67 | { |
709 | 66 | FieldCodecManager::add<DefaultIdentifierCodec>("_default_id_codec"); | 68 | FieldCodecManager::add<DefaultIdentifierCodec>(default_id_codec_name()); |
710 | 67 | // make sure the id codec exists | 69 | // make sure the id codec exists |
711 | 68 | id_codec(); | 70 | id_codec(); |
712 | 69 | set_default_codecs(); | 71 | set_default_codecs(); |
713 | @@ -77,31 +79,59 @@ | |||
714 | 77 | if(!defaults_loaded) | 79 | if(!defaults_loaded) |
715 | 78 | { | 80 | { |
716 | 79 | using google::protobuf::FieldDescriptor; | 81 | using google::protobuf::FieldDescriptor; |
742 | 80 | 82 | ||
743 | 81 | FieldCodecManager::add<DefaultNumericFieldCodec<double> >(default_codec_name()); | 83 | // version 2 |
744 | 82 | FieldCodecManager::add<DefaultNumericFieldCodec<float> >(default_codec_name()); | 84 | FieldCodecManager::add<v2::DefaultNumericFieldCodec<double> >(default_codec_name()); |
745 | 83 | FieldCodecManager::add<DefaultBoolCodec>(default_codec_name()); | 85 | FieldCodecManager::add<v2::DefaultNumericFieldCodec<float> >(default_codec_name()); |
746 | 84 | FieldCodecManager::add<DefaultNumericFieldCodec<int32> >(default_codec_name()); | 86 | FieldCodecManager::add<v2::DefaultBoolCodec>(default_codec_name()); |
747 | 85 | FieldCodecManager::add<DefaultNumericFieldCodec<int64> >(default_codec_name()); | 87 | FieldCodecManager::add<v2::DefaultNumericFieldCodec<int32> >(default_codec_name()); |
748 | 86 | FieldCodecManager::add<DefaultNumericFieldCodec<uint32> >(default_codec_name()); | 88 | FieldCodecManager::add<v2::DefaultNumericFieldCodec<int64> >(default_codec_name()); |
749 | 87 | FieldCodecManager::add<DefaultNumericFieldCodec<uint64> >(default_codec_name()); | 89 | FieldCodecManager::add<v2::DefaultNumericFieldCodec<uint32> >(default_codec_name()); |
750 | 88 | FieldCodecManager::add<DefaultStringCodec, FieldDescriptor::TYPE_STRING>(default_codec_name()); | 90 | FieldCodecManager::add<v2::DefaultNumericFieldCodec<uint64> >(default_codec_name()); |
751 | 89 | FieldCodecManager::add<DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(default_codec_name()); | 91 | FieldCodecManager::add<v2::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(default_codec_name()); |
752 | 90 | FieldCodecManager::add<DefaultEnumCodec>(default_codec_name()); | 92 | FieldCodecManager::add<v2::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(default_codec_name()); |
753 | 91 | FieldCodecManager::add<DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(default_codec_name()); | 93 | FieldCodecManager::add<v2::DefaultEnumCodec >(default_codec_name()); |
754 | 92 | 94 | FieldCodecManager::add<v2::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(default_codec_name()); | |
755 | 93 | FieldCodecManager::add<TimeCodec<uint64> >("_time"); | 95 | |
756 | 94 | FieldCodecManager::add<TimeCodec<int64> >("_time"); | 96 | FieldCodecManager::add<v2::TimeCodec<uint64> >("dccl.time2"); |
757 | 95 | FieldCodecManager::add<TimeCodec<double> >("_time"); | 97 | FieldCodecManager::add<v2::TimeCodec<int64> >("dccl.time2"); |
758 | 96 | 98 | FieldCodecManager::add<v2::TimeCodec<double> >("dccl.time2"); | |
759 | 97 | FieldCodecManager::add<StaticCodec<std::string> >("_static"); | 99 | |
760 | 98 | FieldCodecManager::add<StaticCodec<double> >("_static"); | 100 | FieldCodecManager::add<v2::StaticCodec<std::string> >("dccl.static2"); |
761 | 99 | FieldCodecManager::add<StaticCodec<float> >("_static"); | 101 | FieldCodecManager::add<v2::StaticCodec<double> >("dccl.static2"); |
762 | 100 | FieldCodecManager::add<StaticCodec<int32> >("_static"); | 102 | FieldCodecManager::add<v2::StaticCodec<float> >("dccl.static2"); |
763 | 101 | FieldCodecManager::add<StaticCodec<int64> >("_static"); | 103 | FieldCodecManager::add<v2::StaticCodec<int32> >("dccl.static2"); |
764 | 102 | FieldCodecManager::add<StaticCodec<uint32> >("_static"); | 104 | FieldCodecManager::add<v2::StaticCodec<int64> >("dccl.static2"); |
765 | 103 | FieldCodecManager::add<StaticCodec<uint64> >("_static"); | 105 | FieldCodecManager::add<v2::StaticCodec<uint32> >("dccl.static2"); |
766 | 104 | 106 | FieldCodecManager::add<v2::StaticCodec<uint64> >("dccl.static2"); | |
767 | 107 | |||
768 | 108 | // version 3 | ||
769 | 109 | FieldCodecManager::add<v3::DefaultNumericFieldCodec<double> >(default_codec_name(3)); | ||
770 | 110 | FieldCodecManager::add<v3::DefaultNumericFieldCodec<float> >(default_codec_name(3)); | ||
771 | 111 | FieldCodecManager::add<v3::DefaultBoolCodec>(default_codec_name(3)); | ||
772 | 112 | FieldCodecManager::add<v3::DefaultNumericFieldCodec<int32> >(default_codec_name(3)); | ||
773 | 113 | FieldCodecManager::add<v3::DefaultNumericFieldCodec<int64> >(default_codec_name(3)); | ||
774 | 114 | FieldCodecManager::add<v3::DefaultNumericFieldCodec<uint32> >(default_codec_name(3)); | ||
775 | 115 | FieldCodecManager::add<v3::DefaultNumericFieldCodec<uint64> >(default_codec_name(3)); | ||
776 | 116 | FieldCodecManager::add<v3::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(default_codec_name(3)); | ||
777 | 117 | FieldCodecManager::add<v3::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(default_codec_name(3)); | ||
778 | 118 | FieldCodecManager::add<v3::DefaultEnumCodec >(default_codec_name(3)); | ||
779 | 119 | FieldCodecManager::add<v3::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(default_codec_name(3)); | ||
780 | 120 | |||
781 | 121 | // for backwards compatibility | ||
782 | 122 | FieldCodecManager::add<v2::TimeCodec<uint64> >("_time"); | ||
783 | 123 | FieldCodecManager::add<v2::TimeCodec<int64> >("_time"); | ||
784 | 124 | FieldCodecManager::add<v2::TimeCodec<double> >("_time"); | ||
785 | 125 | |||
786 | 126 | FieldCodecManager::add<v2::StaticCodec<std::string> >("_static"); | ||
787 | 127 | FieldCodecManager::add<v2::StaticCodec<double> >("_static"); | ||
788 | 128 | FieldCodecManager::add<v2::StaticCodec<float> >("_static"); | ||
789 | 129 | FieldCodecManager::add<v2::StaticCodec<int32> >("_static"); | ||
790 | 130 | FieldCodecManager::add<v2::StaticCodec<int64> >("_static"); | ||
791 | 131 | FieldCodecManager::add<v2::StaticCodec<uint32> >("_static"); | ||
792 | 132 | FieldCodecManager::add<v2::StaticCodec<uint64> >("_static"); | ||
793 | 133 | |||
794 | 134 | |||
795 | 105 | defaults_loaded = true; | 135 | defaults_loaded = true; |
796 | 106 | } | 136 | } |
797 | 107 | } | 137 | } |
798 | @@ -326,6 +356,9 @@ | |||
799 | 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\"")); |
800 | 327 | if(!desc->options().GetExtension(dccl::msg).has_max_bytes()) | 357 | if(!desc->options().GetExtension(dccl::msg).has_max_bytes()) |
801 | 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\"")); |
802 | 359 | |||
803 | 360 | if(!desc->options().GetExtension(dccl::msg).has_codec_version()) | ||
804 | 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; | ||
805 | 329 | 362 | ||
806 | 330 | boost::shared_ptr<FieldCodecBase> codec = FieldCodecManager::find(desc); | 363 | boost::shared_ptr<FieldCodecBase> codec = FieldCodecManager::find(desc); |
807 | 331 | 364 | ||
808 | @@ -419,7 +452,8 @@ | |||
809 | 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(); |
810 | 420 | const unsigned allowed_bit_size = allowed_byte_size * BITS_IN_BYTE; | 453 | const unsigned allowed_bit_size = allowed_byte_size * BITS_IN_BYTE; |
811 | 421 | 454 | ||
813 | 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(); |
814 | 456 | std::string guard = std::string((full_width-message_name.size())/2, '='); | ||
815 | 423 | 457 | ||
816 | 424 | std::string bits_dccl_head_str = "dccl.id head"; | 458 | std::string bits_dccl_head_str = "dccl.id head"; |
817 | 425 | std::string bits_user_head_str = "user head"; | 459 | std::string bits_user_head_str = "user head"; |
818 | @@ -430,7 +464,7 @@ | |||
819 | 430 | const int spaces = 8; | 464 | const int spaces = 8; |
820 | 431 | std::string indent = std::string(spaces,' '); | 465 | std::string indent = std::string(spaces,' '); |
821 | 432 | 466 | ||
823 | 433 | *os << guard << " " << desc->full_name() << " " << guard << "\n" | 467 | *os << guard << " " << message_name << " " << guard << "\n" |
824 | 434 | << "Actual maximum size of message: " << byte_size << " bytes / " | 468 | << "Actual maximum size of message: " << byte_size << " bytes / " |
825 | 435 | << byte_size*BITS_IN_BYTE << " bits\n" | 469 | << byte_size*BITS_IN_BYTE << " bits\n" |
826 | 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" |
827 | @@ -443,7 +477,7 @@ | |||
828 | 443 | std::string header_str = "Header"; | 477 | std::string header_str = "Header"; |
829 | 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, '-'); |
830 | 445 | *os << header_guard << " " << header_str << " " << header_guard << std::endl; | 479 | *os << header_guard << " " << header_str << " " << header_guard << std::endl; |
832 | 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"; |
833 | 447 | codec->base_info(os, desc, MessageStack::HEAD); | 481 | codec->base_info(os, desc, MessageStack::HEAD); |
834 | 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; |
835 | 449 | 483 | ||
836 | @@ -459,6 +493,9 @@ | |||
837 | 459 | { | 493 | { |
838 | 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; |
839 | 461 | } | 495 | } |
840 | 496 | |||
841 | 497 | os->flush(); | ||
842 | 498 | |||
843 | 462 | } | 499 | } |
844 | 463 | 500 | ||
845 | 464 | } | 501 | } |
846 | @@ -564,4 +601,5 @@ | |||
847 | 564 | 601 | ||
848 | 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; |
849 | 566 | } | 603 | } |
850 | 604 | |||
851 | 567 | } | 605 | } |
852 | 568 | 606 | ||
853 | === modified file 'src/codec.h' | |||
854 | --- src/codec.h 2014-04-22 20:10:37 +0000 | |||
855 | +++ src/codec.h 2014-08-27 16:27:22 +0000 | |||
856 | @@ -42,7 +42,9 @@ | |||
857 | 42 | #include "exception.h" | 42 | #include "exception.h" |
858 | 43 | #include "field_codec.h" | 43 | #include "field_codec.h" |
859 | 44 | #include "field_codec_fixed.h" | 44 | #include "field_codec_fixed.h" |
861 | 45 | #include "field_codec_default.h" | 45 | |
862 | 46 | #include "codecs2/field_codec_default_message.h" | ||
863 | 47 | #include "codecs3/field_codec_default_message.h" | ||
864 | 46 | #include "type_helper.h" | 48 | #include "type_helper.h" |
865 | 47 | #include "field_codec_manager.h" | 49 | #include "field_codec_manager.h" |
866 | 48 | 50 | ||
867 | @@ -84,7 +86,7 @@ | |||
868 | 84 | class Codec | 86 | class Codec |
869 | 85 | { | 87 | { |
870 | 86 | public: | 88 | public: |
872 | 87 | Codec(const std::string& dccl_id_codec = "_default_id_codec"); | 89 | Codec(const std::string& dccl_id_codec = default_id_codec_name()); |
873 | 88 | virtual ~Codec() | 90 | virtual ~Codec() |
874 | 89 | { | 91 | { |
875 | 90 | for(std::vector<void *>::iterator it = dl_handles_.begin(), | 92 | for(std::vector<void *>::iterator it = dl_handles_.begin(), |
876 | @@ -181,6 +183,9 @@ | |||
877 | 181 | return desc->options().GetExtension(dccl::msg).id(); | 183 | return desc->options().GetExtension(dccl::msg).id(); |
878 | 182 | } | 184 | } |
879 | 183 | 185 | ||
880 | 186 | /// \brief Provides a map of all loaded DCCL IDs to the equivalent Protobuf descriptor | ||
881 | 187 | const std::map<int32, const google::protobuf::Descriptor*>& loaded() const { return id2desc_; } | ||
882 | 188 | |||
883 | 184 | //@} | 189 | //@} |
884 | 185 | 190 | ||
885 | 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) |
886 | @@ -237,8 +242,26 @@ | |||
887 | 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. |
888 | 238 | template<typename GoogleProtobufMessagePointer> | 243 | template<typename GoogleProtobufMessagePointer> |
889 | 239 | GoogleProtobufMessagePointer decode(std::string* bytes); | 244 | GoogleProtobufMessagePointer decode(std::string* bytes); |
892 | 240 | 245 | ||
893 | 241 | friend class DefaultMessageCodec; | 246 | static std::string default_id_codec_name() |
894 | 247 | { return "dccl.default.id"; } | ||
895 | 248 | |||
896 | 249 | |||
897 | 250 | static std::string default_codec_name(int version = 2) | ||
898 | 251 | { | ||
899 | 252 | switch(version) | ||
900 | 253 | { | ||
901 | 254 | case 2: | ||
902 | 255 | return dccl::DCCLFieldOptions::descriptor()->FindFieldByName("codec")->default_value_string(); | ||
903 | 256 | default: | ||
904 | 257 | return "dccl.default" + boost::lexical_cast<std::string>(version); | ||
905 | 258 | } | ||
906 | 259 | |||
907 | 260 | } | ||
908 | 261 | |||
909 | 262 | |||
910 | 263 | friend class v2::DefaultMessageCodec; | ||
911 | 264 | //friend class v3::DefaultMessageCodec; | ||
912 | 242 | private: | 265 | private: |
913 | 243 | Codec(const Codec&); | 266 | Codec(const Codec&); |
914 | 244 | Codec& operator= (const Codec&); | 267 | Codec& operator= (const Codec&); |
915 | @@ -254,11 +277,6 @@ | |||
916 | 254 | id_codec_); | 277 | id_codec_); |
917 | 255 | } | 278 | } |
918 | 256 | 279 | ||
919 | 257 | static const std::string& default_codec_name() | ||
920 | 258 | { | ||
921 | 259 | return dccl::DCCLFieldOptions::descriptor()->FindFieldByName("codec")->default_value_string(); | ||
922 | 260 | } | ||
923 | 261 | |||
924 | 262 | private: | 280 | private: |
925 | 263 | // SHA256 hash of the crypto passphrase | 281 | // SHA256 hash of the crypto passphrase |
926 | 264 | std::string crypto_key_; | 282 | std::string crypto_key_; |
927 | @@ -287,7 +305,7 @@ | |||
928 | 287 | unsigned this_id = id(bytes); | 305 | unsigned this_id = id(bytes); |
929 | 288 | 306 | ||
930 | 289 | if(!id2desc_.count(this_id)) | 307 | if(!id2desc_.count(this_id)) |
932 | 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.")); |
933 | 291 | 309 | ||
934 | 292 | // ownership of this object goes to the caller of decode() | 310 | // ownership of this object goes to the caller of decode() |
935 | 293 | GoogleProtobufMessagePointer msg = | 311 | GoogleProtobufMessagePointer msg = |
936 | 294 | 312 | ||
937 | === added directory 'src/codecs2' | |||
938 | === renamed file 'src/field_codec_default.cpp' => 'src/codecs2/field_codec_default.cpp' | |||
939 | --- src/field_codec_default.cpp 2014-04-22 20:10:37 +0000 | |||
940 | +++ src/codecs2/field_codec_default.cpp 2014-08-27 16:27:22 +0000 | |||
941 | @@ -25,108 +25,28 @@ | |||
942 | 25 | #include <sstream> | 25 | #include <sstream> |
943 | 26 | #include <algorithm> | 26 | #include <algorithm> |
944 | 27 | 27 | ||
947 | 28 | #include "field_codec_default.h" | 28 | #include "dccl/codecs2/field_codec_default.h" |
948 | 29 | #include "type_helper.h" | 29 | #include "dccl/type_helper.h" |
949 | 30 | #include "dccl/codec.h" | 30 | #include "dccl/codec.h" |
950 | 31 | 31 | ||
951 | 32 | using namespace dccl::logger; | 32 | using namespace dccl::logger; |
952 | 33 | 33 | ||
953 | 34 | 34 | ||
954 | 35 | // | 35 | // |
955 | 36 | // DefaultIdentifierCodec | ||
956 | 37 | // | ||
957 | 38 | |||
958 | 39 | dccl::Bitset dccl::DefaultIdentifierCodec::encode() | ||
959 | 40 | { | ||
960 | 41 | return encode(0); | ||
961 | 42 | } | ||
962 | 43 | |||
963 | 44 | dccl::Bitset dccl::DefaultIdentifierCodec::encode(const uint32& id) | ||
964 | 45 | { | ||
965 | 46 | if(id <= ONE_BYTE_MAX_ID) | ||
966 | 47 | { | ||
967 | 48 | return(dccl::Bitset(this_size(id), id) << 1); | ||
968 | 49 | } | ||
969 | 50 | else | ||
970 | 51 | { | ||
971 | 52 | dccl::Bitset return_bits(this_size(id), id); | ||
972 | 53 | return_bits <<= 1; | ||
973 | 54 | // set LSB to indicate long header form | ||
974 | 55 | return_bits.set(0, true); | ||
975 | 56 | |||
976 | 57 | |||
977 | 58 | return return_bits; | ||
978 | 59 | } | ||
979 | 60 | } | ||
980 | 61 | |||
981 | 62 | dccl::uint32 dccl::DefaultIdentifierCodec::decode(Bitset* bits) | ||
982 | 63 | { | ||
983 | 64 | if(bits->test(0)) | ||
984 | 65 | { | ||
985 | 66 | // long header | ||
986 | 67 | // grabs more bits to add to the MSB of `bits` | ||
987 | 68 | bits->get_more_bits((LONG_FORM_ID_BYTES - SHORT_FORM_ID_BYTES)*BITS_IN_BYTE); | ||
988 | 69 | // discard identifier | ||
989 | 70 | *(bits) >>= 1; | ||
990 | 71 | return bits->to_ulong(); | ||
991 | 72 | } | ||
992 | 73 | else | ||
993 | 74 | { | ||
994 | 75 | // short header | ||
995 | 76 | *(bits) >>= 1; | ||
996 | 77 | return bits->to_ulong(); | ||
997 | 78 | } | ||
998 | 79 | } | ||
999 | 80 | |||
1000 | 81 | unsigned dccl::DefaultIdentifierCodec::size() | ||
1001 | 82 | { | ||
1002 | 83 | return this_size(0); | ||
1003 | 84 | } | ||
1004 | 85 | |||
1005 | 86 | unsigned dccl::DefaultIdentifierCodec::size(const uint32& id) | ||
1006 | 87 | { | ||
1007 | 88 | return this_size(id); | ||
1008 | 89 | } | ||
1009 | 90 | |||
1010 | 91 | unsigned dccl::DefaultIdentifierCodec::this_size(const uint32& id) | ||
1011 | 92 | { | ||
1012 | 93 | if(id > TWO_BYTE_MAX_ID) | ||
1013 | 94 | throw(Exception("dccl.id provided (" + boost::lexical_cast<std::string>(id) + ") exceeds maximum: " + boost::lexical_cast<std::string>(int(TWO_BYTE_MAX_ID)))); | ||
1014 | 95 | |||
1015 | 96 | return (id <= ONE_BYTE_MAX_ID) ? | ||
1016 | 97 | SHORT_FORM_ID_BYTES*BITS_IN_BYTE : | ||
1017 | 98 | LONG_FORM_ID_BYTES*BITS_IN_BYTE; | ||
1018 | 99 | } | ||
1019 | 100 | |||
1020 | 101 | |||
1021 | 102 | unsigned dccl::DefaultIdentifierCodec::max_size() | ||
1022 | 103 | { | ||
1023 | 104 | return LONG_FORM_ID_BYTES * BITS_IN_BYTE; | ||
1024 | 105 | } | ||
1025 | 106 | |||
1026 | 107 | unsigned dccl::DefaultIdentifierCodec::min_size() | ||
1027 | 108 | { | ||
1028 | 109 | return SHORT_FORM_ID_BYTES * BITS_IN_BYTE; | ||
1029 | 110 | } | ||
1030 | 111 | |||
1031 | 112 | |||
1032 | 113 | |||
1033 | 114 | |||
1034 | 115 | // | ||
1035 | 116 | // DefaultBoolCodec | 36 | // DefaultBoolCodec |
1036 | 117 | // | 37 | // |
1037 | 118 | 38 | ||
1039 | 119 | dccl::Bitset dccl::DefaultBoolCodec::encode() | 39 | dccl::Bitset dccl::v2::DefaultBoolCodec::encode() |
1040 | 120 | { | 40 | { |
1041 | 121 | return Bitset(size()); | 41 | return Bitset(size()); |
1042 | 122 | } | 42 | } |
1043 | 123 | 43 | ||
1045 | 124 | dccl::Bitset dccl::DefaultBoolCodec::encode(const bool& wire_value) | 44 | dccl::Bitset dccl::v2::DefaultBoolCodec::encode(const bool& wire_value) |
1046 | 125 | { | 45 | { |
1047 | 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); |
1048 | 127 | } | 47 | } |
1049 | 128 | 48 | ||
1051 | 129 | bool dccl::DefaultBoolCodec::decode(Bitset* bits) | 49 | bool dccl::v2::DefaultBoolCodec::decode(Bitset* bits) |
1052 | 130 | { | 50 | { |
1053 | 131 | unsigned long t = bits->to_ulong(); | 51 | unsigned long t = bits->to_ulong(); |
1054 | 132 | if(this_field()->is_required()) | 52 | if(this_field()->is_required()) |
1055 | @@ -145,7 +65,7 @@ | |||
1056 | 145 | } | 65 | } |
1057 | 146 | 66 | ||
1058 | 147 | 67 | ||
1060 | 148 | unsigned dccl::DefaultBoolCodec::size() | 68 | unsigned dccl::v2::DefaultBoolCodec::size() |
1061 | 149 | { | 69 | { |
1062 | 150 | // true and false | 70 | // true and false |
1063 | 151 | const unsigned BOOL_VALUES = 2; | 71 | const unsigned BOOL_VALUES = 2; |
1064 | @@ -155,19 +75,19 @@ | |||
1065 | 155 | return dccl::ceil_log2(BOOL_VALUES + NULL_VALUE); | 75 | return dccl::ceil_log2(BOOL_VALUES + NULL_VALUE); |
1066 | 156 | } | 76 | } |
1067 | 157 | 77 | ||
1069 | 158 | void dccl::DefaultBoolCodec::validate() | 78 | void dccl::v2::DefaultBoolCodec::validate() |
1070 | 159 | { } | 79 | { } |
1071 | 160 | 80 | ||
1072 | 161 | // | 81 | // |
1073 | 162 | // DefaultStringCodec | 82 | // DefaultStringCodec |
1074 | 163 | // | 83 | // |
1075 | 164 | 84 | ||
1077 | 165 | dccl::Bitset dccl::DefaultStringCodec::encode() | 85 | dccl::Bitset dccl::v2::DefaultStringCodec::encode() |
1078 | 166 | { | 86 | { |
1079 | 167 | return Bitset(min_size()); | 87 | return Bitset(min_size()); |
1080 | 168 | } | 88 | } |
1081 | 169 | 89 | ||
1083 | 170 | dccl::Bitset dccl::DefaultStringCodec::encode(const std::string& wire_value) | 90 | dccl::Bitset dccl::v2::DefaultStringCodec::encode(const std::string& wire_value) |
1084 | 171 | { | 91 | { |
1085 | 172 | std::string s = wire_value; | 92 | std::string s = wire_value; |
1086 | 173 | if(s.size() > dccl_field_options().max_length()) | 93 | if(s.size() > dccl_field_options().max_length()) |
1087 | @@ -197,7 +117,7 @@ | |||
1088 | 197 | return length_bits; | 117 | return length_bits; |
1089 | 198 | } | 118 | } |
1090 | 199 | 119 | ||
1092 | 200 | std::string dccl::DefaultStringCodec::decode(Bitset* bits) | 120 | std::string dccl::v2::DefaultStringCodec::decode(Bitset* bits) |
1093 | 201 | { | 121 | { |
1094 | 202 | unsigned value_length = bits->to_ulong(); | 122 | unsigned value_length = bits->to_ulong(); |
1095 | 203 | 123 | ||
1096 | @@ -228,30 +148,30 @@ | |||
1097 | 228 | 148 | ||
1098 | 229 | } | 149 | } |
1099 | 230 | 150 | ||
1101 | 231 | unsigned dccl::DefaultStringCodec::size() | 151 | unsigned dccl::v2::DefaultStringCodec::size() |
1102 | 232 | { | 152 | { |
1103 | 233 | return min_size(); | 153 | return min_size(); |
1104 | 234 | } | 154 | } |
1105 | 235 | 155 | ||
1107 | 236 | unsigned dccl::DefaultStringCodec::size(const std::string& wire_value) | 156 | unsigned dccl::v2::DefaultStringCodec::size(const std::string& wire_value) |
1108 | 237 | { | 157 | { |
1109 | 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()); |
1110 | 239 | } | 159 | } |
1111 | 240 | 160 | ||
1112 | 241 | 161 | ||
1114 | 242 | unsigned dccl::DefaultStringCodec::max_size() | 162 | unsigned dccl::v2::DefaultStringCodec::max_size() |
1115 | 243 | { | 163 | { |
1116 | 244 | // string length + actual string | 164 | // string length + actual string |
1117 | 245 | return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE; | 165 | return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE; |
1118 | 246 | } | 166 | } |
1119 | 247 | 167 | ||
1121 | 248 | unsigned dccl::DefaultStringCodec::min_size() | 168 | unsigned dccl::v2::DefaultStringCodec::min_size() |
1122 | 249 | { | 169 | { |
1123 | 250 | return dccl::ceil_log2(MAX_STRING_LENGTH+1); | 170 | return dccl::ceil_log2(MAX_STRING_LENGTH+1); |
1124 | 251 | } | 171 | } |
1125 | 252 | 172 | ||
1126 | 253 | 173 | ||
1128 | 254 | void dccl::DefaultStringCodec::validate() | 174 | void dccl::v2::DefaultStringCodec::validate() |
1129 | 255 | { | 175 | { |
1130 | 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"); |
1131 | 257 | require(dccl_field_options().max_length() <= MAX_STRING_LENGTH, | 177 | require(dccl_field_options().max_length() <= MAX_STRING_LENGTH, |
1132 | @@ -261,13 +181,13 @@ | |||
1133 | 261 | // | 181 | // |
1134 | 262 | // DefaultBytesCodec | 182 | // DefaultBytesCodec |
1135 | 263 | // | 183 | // |
1137 | 264 | dccl::Bitset dccl::DefaultBytesCodec::encode() | 184 | dccl::Bitset dccl::v2::DefaultBytesCodec::encode() |
1138 | 265 | { | 185 | { |
1139 | 266 | return Bitset(min_size(), 0); | 186 | return Bitset(min_size(), 0); |
1140 | 267 | } | 187 | } |
1141 | 268 | 188 | ||
1142 | 269 | 189 | ||
1144 | 270 | dccl::Bitset dccl::DefaultBytesCodec::encode(const std::string& wire_value) | 190 | dccl::Bitset dccl::v2::DefaultBytesCodec::encode(const std::string& wire_value) |
1145 | 271 | { | 191 | { |
1146 | 272 | Bitset bits; | 192 | Bitset bits; |
1147 | 273 | bits.from_byte_string(wire_value); | 193 | bits.from_byte_string(wire_value); |
1148 | @@ -282,19 +202,19 @@ | |||
1149 | 282 | return bits; | 202 | return bits; |
1150 | 283 | } | 203 | } |
1151 | 284 | 204 | ||
1153 | 285 | unsigned dccl::DefaultBytesCodec::size() | 205 | unsigned dccl::v2::DefaultBytesCodec::size() |
1154 | 286 | { | 206 | { |
1155 | 287 | return min_size(); | 207 | return min_size(); |
1156 | 288 | } | 208 | } |
1157 | 289 | 209 | ||
1158 | 290 | 210 | ||
1160 | 291 | unsigned dccl::DefaultBytesCodec::size(const std::string& wire_value) | 211 | unsigned dccl::v2::DefaultBytesCodec::size(const std::string& wire_value) |
1161 | 292 | { | 212 | { |
1162 | 293 | return max_size(); | 213 | return max_size(); |
1163 | 294 | } | 214 | } |
1164 | 295 | 215 | ||
1165 | 296 | 216 | ||
1167 | 297 | std::string dccl::DefaultBytesCodec::decode(Bitset* bits) | 217 | std::string dccl::v2::DefaultBytesCodec::decode(Bitset* bits) |
1168 | 298 | { | 218 | { |
1169 | 299 | if(!this_field()->is_required()) | 219 | if(!this_field()->is_required()) |
1170 | 300 | { | 220 | { |
1171 | @@ -320,13 +240,13 @@ | |||
1172 | 320 | } | 240 | } |
1173 | 321 | } | 241 | } |
1174 | 322 | 242 | ||
1176 | 323 | unsigned dccl::DefaultBytesCodec::max_size() | 243 | unsigned dccl::v2::DefaultBytesCodec::max_size() |
1177 | 324 | { | 244 | { |
1178 | 325 | return dccl_field_options().max_length() * BITS_IN_BYTE + | 245 | return dccl_field_options().max_length() * BITS_IN_BYTE + |
1179 | 326 | (this_field()->is_required() ? 0 : 1); // presence bit? | 246 | (this_field()->is_required() ? 0 : 1); // presence bit? |
1180 | 327 | } | 247 | } |
1181 | 328 | 248 | ||
1183 | 329 | unsigned dccl::DefaultBytesCodec::min_size() | 249 | unsigned dccl::v2::DefaultBytesCodec::min_size() |
1184 | 330 | { | 250 | { |
1185 | 331 | if(this_field()->is_required()) | 251 | if(this_field()->is_required()) |
1186 | 332 | return max_size(); | 252 | return max_size(); |
1187 | @@ -334,7 +254,7 @@ | |||
1188 | 334 | return 1; // presence bit | 254 | return 1; // presence bit |
1189 | 335 | } | 255 | } |
1190 | 336 | 256 | ||
1192 | 337 | void dccl::DefaultBytesCodec::validate() | 257 | void dccl::v2::DefaultBytesCodec::validate() |
1193 | 338 | { | 258 | { |
1194 | 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"); |
1195 | 340 | } | 260 | } |
1196 | @@ -342,12 +262,12 @@ | |||
1197 | 342 | // | 262 | // |
1198 | 343 | // DefaultEnumCodec | 263 | // DefaultEnumCodec |
1199 | 344 | // | 264 | // |
1201 | 345 | dccl::int32 dccl::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value) | 265 | dccl::int32 dccl::v2::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value) |
1202 | 346 | { | 266 | { |
1203 | 347 | return field_value->index(); | 267 | return field_value->index(); |
1204 | 348 | } | 268 | } |
1205 | 349 | 269 | ||
1207 | 350 | const google::protobuf::EnumValueDescriptor* dccl::DefaultEnumCodec::post_decode(const dccl::int32& wire_value) | 270 | const google::protobuf::EnumValueDescriptor* dccl::v2::DefaultEnumCodec::post_decode(const dccl::int32& wire_value) |
1208 | 351 | { | 271 | { |
1209 | 352 | const google::protobuf::EnumDescriptor* e = this_field()->enum_type(); | 272 | const google::protobuf::EnumDescriptor* e = this_field()->enum_type(); |
1210 | 353 | 273 | ||
1211 | 354 | 274 | ||
1212 | === renamed file 'src/field_codec_default.h' => 'src/codecs2/field_codec_default.h' | |||
1213 | --- src/field_codec_default.h 2014-04-22 20:10:37 +0000 | |||
1214 | +++ src/codecs2/field_codec_default.h 2014-08-27 16:27:22 +0000 | |||
1215 | @@ -2,6 +2,7 @@ | |||
1216 | 2 | // GobySoft, LLC (2013-) | 2 | // GobySoft, LLC (2013-) |
1217 | 3 | // Massachusetts Institute of Technology (2007-2014) | 3 | // Massachusetts Institute of Technology (2007-2014) |
1218 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) |
1219 | 5 | // | ||
1220 | 5 | // | 6 | // |
1221 | 6 | // This file is part of the Dynamic Compact Control Language Library | 7 | // This file is part of the Dynamic Compact Control Language Library |
1222 | 7 | // ("DCCL"). | 8 | // ("DCCL"). |
1223 | @@ -39,328 +40,307 @@ | |||
1224 | 39 | 40 | ||
1225 | 40 | #include "dccl/protobuf/option_extensions.pb.h" | 41 | #include "dccl/protobuf/option_extensions.pb.h" |
1226 | 41 | 42 | ||
1231 | 42 | #include "field_codec_default_message.h" | 43 | #include "dccl/codecs2/field_codec_default_message.h" |
1232 | 43 | #include "field_codec_fixed.h" | 44 | #include "dccl/field_codec_fixed.h" |
1233 | 44 | #include "field_codec.h" | 45 | #include "dccl/field_codec.h" |
1234 | 45 | #include "binary.h" | 46 | #include "dccl/binary.h" |
1235 | 46 | 47 | ||
1236 | 47 | namespace dccl | 48 | namespace dccl |
1237 | 48 | { | 49 | { |
1553 | 49 | /// \brief Provides the default 1 byte or 2 byte DCCL ID codec | 50 | namespace v2 |
1554 | 50 | class DefaultIdentifierCodec : public TypedFieldCodec<uint32> | 51 | { |
1555 | 51 | { | 52 | /// \brief Provides a basic bounded arbitrary length numeric (double, float, uint32, uint64, int32, int64) encoder. |
1556 | 52 | protected: | 53 | /// |
1557 | 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. |
1558 | 54 | virtual Bitset encode(const uint32& wire_value); | 55 | template<typename WireType, typename FieldType = WireType> |
1559 | 55 | virtual uint32 decode(Bitset* bits); | 56 | class DefaultNumericFieldCodec : public TypedFixedFieldCodec<WireType, FieldType> |
1560 | 56 | virtual unsigned size(); | 57 | { |
1561 | 57 | virtual unsigned size(const uint32& wire_value); | 58 | protected: |
1562 | 58 | virtual unsigned max_size(); | 59 | |
1563 | 59 | virtual unsigned min_size(); | 60 | virtual double max() |
1564 | 60 | virtual void validate() { } | 61 | { return FieldCodecBase::dccl_field_options().max(); } |
1565 | 61 | 62 | ||
1566 | 62 | private: | 63 | virtual double min() |
1567 | 63 | unsigned this_size(const uint32& wire_value); | 64 | { return FieldCodecBase::dccl_field_options().min(); } |
1568 | 64 | // maximum id we can fit in short or long header (MSB reserved to indicate | 65 | |
1569 | 65 | // short or long header) | 66 | virtual double precision() |
1570 | 66 | enum { ONE_BYTE_MAX_ID = (1 << 7) - 1, | 67 | { return FieldCodecBase::dccl_field_options().precision(); } |
1571 | 67 | TWO_BYTE_MAX_ID = (1 << 15) - 1}; | 68 | |
1572 | 68 | 69 | virtual void validate() | |
1573 | 69 | enum { SHORT_FORM_ID_BYTES = 1, | 70 | { |
1574 | 70 | LONG_FORM_ID_BYTES = 2 }; | 71 | FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_min(), |
1575 | 71 | }; | 72 | "missing (dccl.field).min"); |
1576 | 72 | 73 | FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_max(), | |
1577 | 73 | 74 | "missing (dccl.field).max"); | |
1578 | 74 | 75 | ||
1579 | 75 | /// \brief Provides a basic bounded arbitrary length numeric (double, float, uint32, uint64, int32, int64) encoder. | 76 | validate_numeric_bounds(); |
1580 | 76 | /// | 77 | } |
1581 | 77 | /// Takes ceil(log2((max-min)*10^precision)+1) bits for required fields, ceil(log2((max-min)*10^precision)+2) for optional fields. | 78 | |
1582 | 78 | template<typename WireType, typename FieldType = WireType> | 79 | void validate_numeric_bounds() |
1583 | 79 | class DefaultNumericFieldCodec : public TypedFixedFieldCodec<WireType, FieldType> | 80 | { |
1584 | 80 | { | 81 | |
1585 | 81 | protected: | 82 | // ensure given max and min fit within WireType ranges |
1586 | 82 | 83 | FieldCodecBase::require(min() >= boost::numeric::bounds<WireType>::lowest(), | |
1587 | 83 | virtual double max() | 84 | "(dccl.field).min must be >= minimum of this field type."); |
1588 | 84 | { return FieldCodecBase::dccl_field_options().max(); } | 85 | FieldCodecBase::require(max() <= boost::numeric::bounds<WireType>::highest(), |
1589 | 85 | 86 | "(dccl.field).max must be <= maximum of this field type."); | |
1590 | 86 | virtual double min() | 87 | |
1591 | 87 | { return FieldCodecBase::dccl_field_options().min(); } | 88 | |
1592 | 88 | 89 | // ensure value fits into double | |
1593 | 89 | virtual double precision() | 90 | FieldCodecBase::require((precision() + std::ceil(std::log10(max() - min()))) <= std::numeric_limits<double>::digits10, |
1594 | 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."); |
1595 | 91 | 92 | ||
1596 | 92 | virtual void validate() | 93 | } |
1597 | 93 | { | 94 | |
1598 | 94 | FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_min(), | 95 | |
1599 | 95 | "missing (dccl.field).min"); | 96 | Bitset encode() |
1600 | 96 | FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_max(), | 97 | { |
1601 | 97 | "missing (dccl.field).max"); | 98 | return Bitset(size()); |
1602 | 98 | 99 | } | |
1603 | 99 | validate_numeric_bounds(); | 100 | |
1604 | 100 | } | 101 | |
1605 | 101 | 102 | virtual Bitset encode(const WireType& value) | |
1606 | 102 | void validate_numeric_bounds() | 103 | { |
1607 | 103 | { | 104 | // round first, before checking bounds |
1608 | 104 | 105 | WireType wire_value = dccl::round(value, precision()); | |
1609 | 105 | // ensure given max and min fit within WireType ranges | 106 | |
1610 | 106 | FieldCodecBase::require(min() >= boost::numeric::bounds<WireType>::lowest(), | 107 | // check bounds, if out-of-bounds, send as zeros |
1611 | 107 | "(dccl.field).min must be >= minimum of this field type."); | 108 | if(wire_value < min() || wire_value > max()) |
1612 | 108 | FieldCodecBase::require(max() <= boost::numeric::bounds<WireType>::highest(), | 109 | return Bitset(size()); |
1613 | 109 | "(dccl.field).max must be <= maximum of this field type."); | 110 | |
1614 | 110 | 111 | wire_value -= dccl::round((WireType)min(), precision()); | |
1615 | 111 | 112 | ||
1616 | 112 | // ensure value fits into double | 113 | if (precision() < 0) { |
1617 | 113 | FieldCodecBase::require((precision() + std::ceil(std::log10(max() - min()))) <= std::numeric_limits<double>::digits10, | 114 | wire_value /= (WireType)std::pow(10.0, -precision()); |
1618 | 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) { |
1619 | 115 | 116 | wire_value *= (WireType)std::pow(10.0, precision()); | |
1620 | 116 | } | 117 | } |
1621 | 117 | 118 | ||
1622 | 118 | 119 | dccl::uint64 uint_value = boost::numeric_cast<dccl::uint64>(dccl::round(wire_value, 0)); | |
1623 | 119 | Bitset encode() | 120 | |
1624 | 120 | { | 121 | // "presence" value (0) |
1625 | 121 | return Bitset(size()); | 122 | if(!FieldCodecBase::this_field()->is_required()) |
1626 | 122 | } | 123 | uint_value += 1; |
1627 | 123 | 124 | ||
1628 | 124 | 125 | ||
1629 | 125 | virtual Bitset encode(const WireType& value) | 126 | Bitset encoded; |
1630 | 126 | { | 127 | encoded.from(uint_value, size()); |
1631 | 127 | WireType wire_value = value; | 128 | return encoded; |
1632 | 128 | 129 | } | |
1633 | 129 | if(wire_value < min() || wire_value > max()) | 130 | |
1634 | 130 | return Bitset(size()); | 131 | virtual WireType decode(Bitset* bits) |
1635 | 131 | 132 | { | |
1636 | 132 | wire_value -= (WireType)min(); | 133 | // The line below SHOULD BE: |
1637 | 133 | 134 | // dccl::uint64 t = bits->to<dccl::uint64>(); | |
1638 | 134 | wire_value = dccl::round(wire_value, precision()); | 135 | // But GCC3.3 requires an explicit template modifier on the method. |
1639 | 135 | if (precision() < 0) { | 136 | // See, e.g., http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10959 |
1640 | 136 | wire_value /= (WireType)std::pow(10.0, -precision()); | 137 | dccl::uint64 uint_value = (bits->template to<dccl::uint64>)(); |
1641 | 137 | } else if (precision() > 0) { | 138 | |
1642 | 138 | wire_value *= (WireType)std::pow(10.0, precision()); | 139 | if(!FieldCodecBase::this_field()->is_required()) |
1643 | 139 | } | 140 | { |
1644 | 140 | 141 | if(!uint_value) throw NullValueException(); | |
1645 | 141 | // "presence" value (0) | 142 | --uint_value; |
1646 | 142 | if(!FieldCodecBase::this_field()->is_required()) | 143 | } |
1647 | 143 | wire_value += 1; | 144 | |
1648 | 144 | 145 | WireType wire_value = (WireType)uint_value; | |
1649 | 145 | 146 | ||
1650 | 146 | Bitset encoded; | 147 | if (precision() < 0) { |
1651 | 147 | encoded.from(boost::numeric_cast<dccl::uint64>(dccl::round(wire_value, 0)), size()); | 148 | wire_value *= (WireType)std::pow(10.0, -precision()); |
1652 | 148 | return encoded; | 149 | } else if (precision() > 0) { |
1653 | 149 | } | 150 | wire_value /= (WireType)std::pow(10.0, precision()); |
1654 | 150 | 151 | } | |
1655 | 151 | virtual WireType decode(Bitset* bits) | 152 | |
1656 | 152 | { | 153 | // round values again to properly handle cases where double precision |
1657 | 153 | // The line below SHOULD BE: | 154 | // leads to slightly off values (e.g. 2.099999999 instead of 2.1) |
1658 | 154 | // dccl::uint64 t = bits->to<dccl::uint64>(); | 155 | wire_value = dccl::round(wire_value + dccl::round((WireType)min(), precision()), |
1659 | 155 | // But GCC3.3 requires an explicit template modifier on the method. | 156 | precision()); |
1660 | 156 | // See, e.g., http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10959 | 157 | |
1661 | 157 | dccl::uint64 uint_value = (bits->template to<dccl::uint64>)(); | 158 | return wire_value; |
1662 | 158 | 159 | } | |
1663 | 159 | if(!FieldCodecBase::this_field()->is_required()) | 160 | |
1664 | 160 | { | 161 | unsigned size() |
1665 | 161 | if(!uint_value) throw NullValueException(); | 162 | { |
1666 | 162 | --uint_value; | 163 | // if not required field, leave one value for unspecified (always encoded as 0) |
1667 | 163 | } | 164 | const unsigned NULL_VALUE = FieldCodecBase::this_field()->is_required() ? 0 : 1; |
1668 | 164 | 165 | ||
1669 | 165 | WireType wire_value = (WireType)uint_value; | 166 | return dccl::ceil_log2((max()-min())*std::pow(10.0, precision())+1 + NULL_VALUE); |
1670 | 166 | 167 | } | |
1671 | 167 | if (precision() < 0) { | 168 | |
1672 | 168 | wire_value *= (WireType)std::pow(10.0, -precision()); | 169 | }; |
1673 | 169 | } else if (precision() > 0) { | 170 | |
1674 | 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` |
1675 | 171 | } | 172 | /// |
1676 | 172 | 173 | /// [presence bit (0 bits if required, 1 bit if optional)][value (1 bit)] | |
1677 | 173 | // round values again to properly handle cases where double precision | 174 | class DefaultBoolCodec : public TypedFixedFieldCodec<bool> |
1678 | 174 | // leads to slightly off values (e.g. 2.099999999 instead of 2.1) | 175 | { |
1679 | 175 | wire_value = dccl::round(wire_value + (WireType)min(), | 176 | private: |
1680 | 176 | precision()); | 177 | Bitset encode(const bool& wire_value); |
1681 | 177 | 178 | Bitset encode(); | |
1682 | 178 | return wire_value; | 179 | bool decode(Bitset* bits); |
1683 | 179 | } | 180 | unsigned size(); |
1684 | 180 | 181 | void validate(); | |
1685 | 181 | unsigned size() | 182 | }; |
1686 | 182 | { | 183 | |
1687 | 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. |
1688 | 184 | const unsigned NULL_VALUE = FieldCodecBase::this_field()->is_required() ? 0 : 1; | 185 | /// |
1689 | 185 | 186 | /// [length of following string (1 byte)][string (0-255 bytes)] | |
1690 | 186 | return dccl::ceil_log2((max()-min())*std::pow(10.0, precision())+1 + NULL_VALUE); | 187 | class DefaultStringCodec : public TypedFieldCodec<std::string> |
1691 | 187 | } | 188 | { |
1692 | 188 | 189 | private: | |
1693 | 189 | }; | 190 | Bitset encode(); |
1694 | 190 | 191 | Bitset encode(const std::string& wire_value); | |
1695 | 191 | /// \brief Provides a bool encoder. Uses 1 bit if field is `required`, 2 bits if `optional` | 192 | std::string decode(Bitset* bits); |
1696 | 192 | /// | 193 | unsigned size(); |
1697 | 193 | /// [presence bit (0 bits if required, 1 bit if optional)][value (1 bit)] | 194 | unsigned size(const std::string& wire_value); |
1698 | 194 | class DefaultBoolCodec : public TypedFixedFieldCodec<bool> | 195 | unsigned max_size(); |
1699 | 195 | { | 196 | unsigned min_size(); |
1700 | 196 | private: | 197 | void validate(); |
1701 | 197 | Bitset encode(const bool& wire_value); | 198 | private: |
1702 | 198 | Bitset encode(); | 199 | enum { MAX_STRING_LENGTH = 255 }; |
1703 | 199 | bool decode(Bitset* bits); | 200 | |
1704 | 200 | unsigned size(); | 201 | }; |
1705 | 201 | void validate(); | 202 | |
1706 | 202 | }; | 203 | |
1707 | 203 | 204 | /// \brief Provides an fixed length byte string encoder. | |
1708 | 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> |
1709 | 205 | /// | 206 | { |
1710 | 206 | /// [length of following string (1 byte)][string (0-255 bytes)] | 207 | private: |
1711 | 207 | class DefaultStringCodec : public TypedFieldCodec<std::string> | 208 | Bitset encode(); |
1712 | 208 | { | 209 | Bitset encode(const std::string& wire_value); |
1713 | 209 | private: | 210 | std::string decode(Bitset* bits); |
1714 | 210 | Bitset encode(); | 211 | unsigned size(); |
1715 | 211 | Bitset encode(const std::string& wire_value); | 212 | unsigned size(const std::string& wire_value); |
1716 | 212 | std::string decode(Bitset* bits); | 213 | unsigned max_size(); |
1717 | 213 | unsigned size(); | 214 | unsigned min_size(); |
1718 | 214 | unsigned size(const std::string& wire_value); | 215 | void validate(); |
1719 | 215 | unsigned max_size(); | 216 | }; |
1720 | 216 | unsigned min_size(); | 217 | |
1721 | 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. |
1722 | 218 | private: | 219 | class DefaultEnumCodec |
1723 | 219 | enum { MAX_STRING_LENGTH = 255 }; | 220 | : public DefaultNumericFieldCodec<int32, const google::protobuf::EnumValueDescriptor*> |
1724 | 220 | 221 | { | |
1725 | 221 | }; | 222 | public: |
1726 | 222 | 223 | int32 pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value); | |
1727 | 223 | 224 | const google::protobuf::EnumValueDescriptor* post_decode(const int32& wire_value); | |
1728 | 224 | /// \brief Provides an fixed length byte string encoder. | 225 | |
1729 | 225 | class DefaultBytesCodec : public TypedFieldCodec<std::string> | 226 | private: |
1730 | 226 | { | 227 | void validate() { } |
1731 | 227 | private: | 228 | |
1732 | 228 | Bitset encode(); | 229 | double max() |
1733 | 229 | Bitset encode(const std::string& wire_value); | 230 | { |
1734 | 230 | std::string decode(Bitset* bits); | 231 | const google::protobuf::EnumDescriptor* e = this_field()->enum_type(); |
1735 | 231 | unsigned size(); | 232 | return e->value_count()-1; |
1736 | 232 | unsigned size(const std::string& wire_value); | 233 | } |
1737 | 233 | unsigned max_size(); | 234 | double min() |
1738 | 234 | unsigned min_size(); | 235 | { return 0; } |
1739 | 235 | void validate(); | 236 | }; |
1740 | 236 | }; | 237 | |
1741 | 237 | 238 | ||
1742 | 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) |
1743 | 239 | class DefaultEnumCodec | 240 | /// |
1744 | 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. |
1745 | 241 | { | 242 | |
1746 | 242 | public: | 243 | typedef double time_wire_type; |
1747 | 243 | int32 pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value); | 244 | template<typename TimeType, int conversion_factor> |
1748 | 244 | const google::protobuf::EnumValueDescriptor* post_decode(const int32& wire_value); | 245 | class TimeCodecBase : public DefaultNumericFieldCodec<time_wire_type, TimeType> |
1749 | 245 | 246 | { | |
1750 | 246 | private: | 247 | public: |
1751 | 247 | void validate() { } | 248 | time_wire_type pre_encode(const TimeType& time_of_day) { |
1752 | 248 | 249 | time_wire_type max_secs = max(); | |
1753 | 249 | double max() | 250 | return std::fmod(time_of_day / static_cast<time_wire_type>(conversion_factor), max_secs); |
1754 | 250 | { | 251 | } |
1755 | 251 | const google::protobuf::EnumDescriptor* e = this_field()->enum_type(); | 252 | |
1756 | 252 | return e->value_count()-1; | 253 | TimeType post_decode(const time_wire_type& encoded_time) { |
1757 | 253 | } | 254 | |
1758 | 254 | double min() | 255 | int64 max_secs = (int64)max(); |
1759 | 255 | { return 0; } | 256 | timeval t; |
1760 | 256 | }; | 257 | gettimeofday(&t, 0); |
1761 | 257 | 258 | int64 now = t.tv_sec; | |
1762 | 258 | 259 | int64 daystart = now - (now % max_secs); | |
1763 | 259 | /// \brief Encodes time of day (default: second precision, but can be set with (dccl.field).precision extension) | 260 | int64 today_time = now - daystart; |
1764 | 260 | /// | 261 | |
1765 | 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. |
1766 | 262 | 263 | if ((encoded_time - today_time) > (max_secs/2)) { | |
1767 | 263 | typedef double time_wire_type; | 264 | daystart -= max_secs; |
1768 | 264 | template<typename TimeType, int conversion_factor> | 265 | } else if ((today_time - encoded_time) > (max_secs/2)) { |
1769 | 265 | class TimeCodecBase : public DefaultNumericFieldCodec<time_wire_type, TimeType> | 266 | daystart += max_secs; |
1770 | 266 | { | 267 | } |
1771 | 267 | public: | 268 | |
1772 | 268 | time_wire_type pre_encode(const TimeType& time_of_day) { | 269 | return (TimeType)(conversion_factor * (daystart + encoded_time)); |
1773 | 269 | time_wire_type max_secs = max(); | 270 | } |
1774 | 270 | return std::fmod(time_of_day / static_cast<time_wire_type>(conversion_factor), max_secs); | 271 | |
1775 | 271 | } | 272 | private: |
1776 | 272 | 273 | void validate() | |
1777 | 273 | TimeType post_decode(const time_wire_type& encoded_time) { | 274 | { |
1778 | 274 | 275 | DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds(); | |
1779 | 275 | int64 max_secs = (int64)max(); | 276 | } |
1780 | 276 | timeval t; | 277 | |
1781 | 277 | gettimeofday(&t, 0); | 278 | double max() { |
1782 | 278 | int64 now = t.tv_sec; | 279 | return FieldCodecBase::dccl_field_options().num_days() * SECONDS_IN_DAY; |
1783 | 279 | int64 daystart = now - (now % max_secs); | 280 | } |
1784 | 280 | int64 today_time = now - daystart; | 281 | |
1785 | 281 | 282 | double min() { return 0; } | |
1786 | 282 | // If time is more than 12 hours ahead of now, assume it's yesterday. | 283 | double precision() |
1787 | 283 | if ((encoded_time - today_time) > (max_secs/2)) { | 284 | { |
1788 | 284 | daystart -= max_secs; | 285 | if(!FieldCodecBase::dccl_field_options().has_precision()) |
1789 | 285 | } else if ((today_time - encoded_time) > (max_secs/2)) { | 286 | return 0; // default to second precision |
1790 | 286 | daystart += max_secs; | 287 | else |
1791 | 287 | } | 288 | { |
1792 | 288 | 289 | return FieldCodecBase::dccl_field_options().precision() + (double)std::log10((double)conversion_factor); | |
1793 | 289 | return (TimeType)(conversion_factor * (daystart + encoded_time)); | 290 | } |
1794 | 290 | } | 291 | |
1795 | 291 | 292 | } | |
1796 | 292 | private: | 293 | |
1797 | 293 | void validate() | 294 | |
1798 | 294 | { | 295 | private: |
1799 | 295 | DefaultNumericFieldCodec<time_wire_type, TimeType>::validate_numeric_bounds(); | 296 | enum { SECONDS_IN_DAY = 86400 }; |
1800 | 296 | } | 297 | }; |
1801 | 297 | 298 | ||
1802 | 298 | double max() { | 299 | template<typename TimeType> |
1803 | 299 | return FieldCodecBase::dccl_field_options().num_days() * SECONDS_IN_DAY; | 300 | class TimeCodec : public TimeCodecBase<TimeType, 0> |
1804 | 300 | } | 301 | { BOOST_STATIC_ASSERT(sizeof(TimeCodec) == 0); }; |
1805 | 301 | 302 | ||
1806 | 302 | double min() { return 0; } | 303 | template<> class TimeCodec<uint64> : public TimeCodecBase<uint64, 1000000> { }; |
1807 | 303 | double precision() | 304 | template<> class TimeCodec<int64> : public TimeCodecBase<int64, 1000000> { }; |
1808 | 304 | { | 305 | template<> class TimeCodec<double> : public TimeCodecBase<double, 1> { }; |
1809 | 305 | if(!FieldCodecBase::dccl_field_options().has_precision()) | 306 | |
1810 | 306 | return 0; // default to second precision | 307 | |
1811 | 307 | else | 308 | /// \brief Placeholder codec that takes no space on the wire (0 bits). |
1812 | 308 | { | 309 | template<typename T> |
1813 | 309 | return FieldCodecBase::dccl_field_options().precision() + (double)std::log10((double)conversion_factor); | 310 | class StaticCodec : public TypedFixedFieldCodec<T> |
1814 | 310 | } | 311 | { |
1815 | 311 | 312 | Bitset encode(const T&) | |
1816 | 312 | } | 313 | { return Bitset(size()); } |
1817 | 313 | 314 | ||
1818 | 314 | 315 | Bitset encode() | |
1819 | 315 | private: | 316 | { return Bitset(size()); } |
1820 | 316 | enum { SECONDS_IN_DAY = 86400 }; | 317 | |
1821 | 317 | }; | 318 | T decode(Bitset* bits) |
1822 | 318 | 319 | { | |
1823 | 319 | template<typename TimeType> | 320 | return boost::lexical_cast<T>( |
1824 | 320 | class TimeCodec : public TimeCodecBase<TimeType, 0> | 321 | FieldCodecBase::dccl_field_options().static_value()); |
1825 | 321 | { BOOST_STATIC_ASSERT(sizeof(TimeCodec) == 0); }; | 322 | } |
1826 | 322 | 323 | ||
1827 | 323 | template<> class TimeCodec<uint64> : public TimeCodecBase<uint64, 1000000> { }; | 324 | unsigned size() |
1828 | 324 | template<> class TimeCodec<int64> : public TimeCodecBase<int64, 1000000> { }; | 325 | { return 0; } |
1829 | 325 | template<> class TimeCodec<double> : public TimeCodecBase<double, 1> { }; | 326 | |
1830 | 326 | 327 | void validate() | |
1831 | 327 | 328 | { | |
1832 | 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"); |
1833 | 329 | template<typename T> | 330 | |
1834 | 330 | class StaticCodec : public TypedFixedFieldCodec<T> | 331 | std::string t = FieldCodecBase::dccl_field_options().static_value(); |
1835 | 331 | { | 332 | try |
1836 | 332 | Bitset encode(const T&) | 333 | { |
1837 | 333 | { return Bitset(size()); } | 334 | boost::lexical_cast<T>(t); |
1838 | 334 | 335 | } | |
1839 | 335 | Bitset encode() | 336 | catch(boost::bad_lexical_cast&) |
1840 | 336 | { return Bitset(size()); } | 337 | { |
1841 | 337 | 338 | FieldCodecBase::require(false, "invalid static_value for this type."); | |
1842 | 338 | T decode(Bitset* bits) | 339 | } |
1843 | 339 | { | 340 | } |
1844 | 340 | return boost::lexical_cast<T>( | 341 | |
1845 | 341 | FieldCodecBase::dccl_field_options().static_value()); | 342 | }; |
1846 | 342 | } | 343 | } |
1532 | 343 | |||
1533 | 344 | unsigned size() | ||
1534 | 345 | { return 0; } | ||
1535 | 346 | |||
1536 | 347 | void validate() | ||
1537 | 348 | { | ||
1538 | 349 | FieldCodecBase::require(FieldCodecBase::dccl_field_options().has_static_value(), "missing (dccl.field).static_value"); | ||
1539 | 350 | |||
1540 | 351 | std::string t = FieldCodecBase::dccl_field_options().static_value(); | ||
1541 | 352 | try | ||
1542 | 353 | { | ||
1543 | 354 | boost::lexical_cast<T>(t); | ||
1544 | 355 | } | ||
1545 | 356 | catch(boost::bad_lexical_cast&) | ||
1546 | 357 | { | ||
1547 | 358 | FieldCodecBase::require(false, "invalid static_value for this type."); | ||
1548 | 359 | } | ||
1549 | 360 | } | ||
1550 | 361 | |||
1551 | 362 | }; | ||
1552 | 363 | |||
1847 | 364 | } | 344 | } |
1848 | 365 | 345 | ||
1849 | 366 | 346 | ||
1850 | 367 | 347 | ||
1851 | === renamed file 'src/field_codec_default_message.cpp' => 'src/codecs2/field_codec_default_message.cpp' | |||
1852 | --- src/field_codec_default_message.cpp 2014-04-22 20:10:37 +0000 | |||
1853 | +++ src/codecs2/field_codec_default_message.cpp 2014-08-27 16:27:22 +0000 | |||
1854 | @@ -30,17 +30,17 @@ | |||
1855 | 30 | // DefaultMessageCodec | 30 | // DefaultMessageCodec |
1856 | 31 | // | 31 | // |
1857 | 32 | 32 | ||
1859 | 33 | void dccl::DefaultMessageCodec::any_encode(Bitset* bits, const boost::any& wire_value) | 33 | void dccl::v2::DefaultMessageCodec::any_encode(Bitset* bits, const boost::any& wire_value) |
1860 | 34 | { | 34 | { |
1865 | 35 | if(wire_value.empty()) | 35 | if(wire_value.empty()) |
1866 | 36 | *bits = Bitset(min_size()); | 36 | *bits = Bitset(min_size()); |
1867 | 37 | else | 37 | else |
1868 | 38 | *bits = traverse_const_message<Encoder, Bitset>(wire_value); | 38 | *bits = traverse_const_message<Encoder, Bitset>(wire_value); |
1869 | 39 | } | 39 | } |
1870 | 40 | 40 | ||
1871 | 41 | 41 | ||
1872 | 42 | 42 | ||
1874 | 43 | unsigned dccl::DefaultMessageCodec::any_size(const boost::any& wire_value) | 43 | unsigned dccl::v2::DefaultMessageCodec::any_size(const boost::any& wire_value) |
1875 | 44 | { | 44 | { |
1876 | 45 | if(wire_value.empty()) | 45 | if(wire_value.empty()) |
1877 | 46 | return min_size(); | 46 | return min_size(); |
1878 | @@ -49,7 +49,7 @@ | |||
1879 | 49 | } | 49 | } |
1880 | 50 | 50 | ||
1881 | 51 | 51 | ||
1883 | 52 | void dccl::DefaultMessageCodec::any_decode(Bitset* bits, boost::any* wire_value) | 52 | void dccl::v2::DefaultMessageCodec::any_decode(Bitset* bits, boost::any* wire_value) |
1884 | 53 | { | 53 | { |
1885 | 54 | try | 54 | try |
1886 | 55 | { | 55 | { |
1887 | @@ -67,8 +67,8 @@ | |||
1888 | 67 | if(!check_field(field_desc)) | 67 | if(!check_field(field_desc)) |
1889 | 68 | continue; | 68 | continue; |
1890 | 69 | 69 | ||
1893 | 70 | boost::shared_ptr<FieldCodecBase> codec = | 70 | |
1894 | 71 | FieldCodecManager::find(field_desc); | 71 | boost::shared_ptr<FieldCodecBase> codec = find(field_desc); |
1895 | 72 | boost::shared_ptr<FromProtoCppTypeBase> helper = | 72 | boost::shared_ptr<FromProtoCppTypeBase> helper = |
1896 | 73 | TypeHelper::find(field_desc); | 73 | TypeHelper::find(field_desc); |
1897 | 74 | 74 | ||
1898 | @@ -127,14 +127,14 @@ | |||
1899 | 127 | } | 127 | } |
1900 | 128 | 128 | ||
1901 | 129 | 129 | ||
1903 | 130 | unsigned dccl::DefaultMessageCodec::max_size() | 130 | unsigned dccl::v2::DefaultMessageCodec::max_size() |
1904 | 131 | { | 131 | { |
1905 | 132 | unsigned u = 0; | 132 | unsigned u = 0; |
1906 | 133 | traverse_descriptor<MaxSize>(&u); | 133 | traverse_descriptor<MaxSize>(&u); |
1907 | 134 | return u; | 134 | return u; |
1908 | 135 | } | 135 | } |
1909 | 136 | 136 | ||
1911 | 137 | unsigned dccl::DefaultMessageCodec::min_size() | 137 | unsigned dccl::v2::DefaultMessageCodec::min_size() |
1912 | 138 | { | 138 | { |
1913 | 139 | unsigned u = 0; | 139 | unsigned u = 0; |
1914 | 140 | traverse_descriptor<MinSize>(&u); | 140 | traverse_descriptor<MinSize>(&u); |
1915 | @@ -142,20 +142,20 @@ | |||
1916 | 142 | } | 142 | } |
1917 | 143 | 143 | ||
1918 | 144 | 144 | ||
1920 | 145 | void dccl::DefaultMessageCodec::validate() | 145 | void dccl::v2::DefaultMessageCodec::validate() |
1921 | 146 | { | 146 | { |
1922 | 147 | bool b = false; | 147 | bool b = false; |
1923 | 148 | traverse_descriptor<Validate>(&b); | 148 | traverse_descriptor<Validate>(&b); |
1924 | 149 | } | 149 | } |
1925 | 150 | 150 | ||
1927 | 151 | std::string dccl::DefaultMessageCodec::info() | 151 | std::string dccl::v2::DefaultMessageCodec::info() |
1928 | 152 | { | 152 | { |
1929 | 153 | std::stringstream ss; | 153 | std::stringstream ss; |
1930 | 154 | traverse_descriptor<Info>(&ss); | 154 | traverse_descriptor<Info>(&ss); |
1931 | 155 | return ss.str(); | 155 | return ss.str(); |
1932 | 156 | } | 156 | } |
1933 | 157 | 157 | ||
1935 | 158 | bool dccl::DefaultMessageCodec::check_field(const google::protobuf::FieldDescriptor* field) | 158 | bool dccl::v2::DefaultMessageCodec::check_field(const google::protobuf::FieldDescriptor* field) |
1936 | 159 | { | 159 | { |
1937 | 160 | if(!field) | 160 | if(!field) |
1938 | 161 | { | 161 | { |
1939 | @@ -171,7 +171,7 @@ | |||
1940 | 171 | else if(MessageStack::current_part() == MessageStack::UNKNOWN) // part not yet explicitly specified | 171 | else if(MessageStack::current_part() == MessageStack::UNKNOWN) // part not yet explicitly specified |
1941 | 172 | { | 172 | { |
1942 | 173 | if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE && | 173 | if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE && |
1944 | 174 | FieldCodecManager::find(field)->name() == Codec::default_codec_name()) // default message codec will expand | 174 | find(field)->name() == Codec::default_codec_name()) // default message codec will expand |
1945 | 175 | return true; | 175 | return true; |
1946 | 176 | else if((part() == MessageStack::HEAD && !dccl_field_options.in_head()) | 176 | else if((part() == MessageStack::HEAD && !dccl_field_options.in_head()) |
1947 | 177 | || (part() == MessageStack::BODY && dccl_field_options.in_head())) | 177 | || (part() == MessageStack::BODY && dccl_field_options.in_head())) |
1948 | 178 | 178 | ||
1949 | === renamed file 'src/field_codec_default_message.h' => 'src/codecs2/field_codec_default_message.h' | |||
1950 | --- src/field_codec_default_message.h 2014-04-22 20:10:37 +0000 | |||
1951 | +++ src/codecs2/field_codec_default_message.h 2014-08-27 16:27:22 +0000 | |||
1952 | @@ -24,225 +24,183 @@ | |||
1953 | 24 | #ifndef DCCLFIELDCODECDEFAULTMESSAGE20110510H | 24 | #ifndef DCCLFIELDCODECDEFAULTMESSAGE20110510H |
1954 | 25 | #define DCCLFIELDCODECDEFAULTMESSAGE20110510H | 25 | #define DCCLFIELDCODECDEFAULTMESSAGE20110510H |
1955 | 26 | 26 | ||
1958 | 27 | #include "field_codec.h" | 27 | #include "dccl/field_codec.h" |
1959 | 28 | #include "field_codec_manager.h" | 28 | #include "dccl/field_codec_manager.h" |
1960 | 29 | 29 | ||
1961 | 30 | #include "dccl/protobuf/option_extensions.pb.h" | 30 | #include "dccl/protobuf/option_extensions.pb.h" |
1962 | 31 | 31 | ||
1963 | 32 | namespace dccl | 32 | namespace dccl |
1964 | 33 | { | 33 | { |
1967 | 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 |
1966 | 35 | class DefaultMessageCodec : public FieldCodecBase | ||
1968 | 36 | { | 35 | { |
2071 | 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. |
2072 | 38 | 37 | class DefaultMessageCodec : public FieldCodecBase | |
2073 | 39 | void any_encode(Bitset* bits, const boost::any& wire_value); | 38 | { |
2074 | 40 | void any_decode(Bitset* bits, boost::any* wire_value); | 39 | private: |
2075 | 41 | unsigned max_size(); | 40 | |
2076 | 42 | unsigned min_size(); | 41 | void any_encode(Bitset* bits, const boost::any& wire_value); |
2077 | 43 | unsigned any_size(const boost::any& wire_value); | 42 | void any_decode(Bitset* bits, boost::any* wire_value); |
2078 | 44 | 43 | unsigned max_size(); | |
2079 | 45 | 44 | unsigned min_size(); | |
2080 | 46 | void validate(); | 45 | unsigned any_size(const boost::any& wire_value); |
2081 | 47 | std::string info(); | 46 | |
2082 | 48 | bool check_field(const google::protobuf::FieldDescriptor* field); | 47 | |
2083 | 49 | 48 | boost::shared_ptr<FieldCodecBase> find(const google::protobuf::FieldDescriptor* field_desc) | |
2084 | 50 | struct Size | 49 | { |
2085 | 51 | { | 50 | return FieldCodecManager::find(field_desc, has_codec_group(), codec_group()); |
2086 | 52 | static void repeated(boost::shared_ptr<FieldCodecBase> codec, | 51 | } |
2087 | 53 | unsigned* return_value, | 52 | |
2088 | 54 | const std::vector<boost::any>& field_values, | 53 | |
2089 | 55 | const google::protobuf::FieldDescriptor* field_desc) | 54 | void validate(); |
2090 | 56 | { | 55 | std::string info(); |
2091 | 57 | codec->field_size_repeated(return_value, field_values, field_desc); | 56 | bool check_field(const google::protobuf::FieldDescriptor* field); |
2092 | 58 | } | 57 | |
2093 | 59 | 58 | struct Size | |
2094 | 60 | static void single(boost::shared_ptr<FieldCodecBase> codec, | 59 | { |
2095 | 61 | unsigned* return_value, | 60 | static void repeated(boost::shared_ptr<FieldCodecBase> codec, |
2096 | 62 | const boost::any& field_value, | 61 | unsigned* return_value, |
2097 | 63 | const google::protobuf::FieldDescriptor* field_desc) | 62 | const std::vector<boost::any>& field_values, |
2098 | 64 | { | 63 | const google::protobuf::FieldDescriptor* field_desc) |
2099 | 65 | codec->field_size(return_value, field_value, field_desc); | 64 | { |
2100 | 66 | } | 65 | codec->field_size_repeated(return_value, field_values, field_desc); |
2101 | 67 | 66 | } | |
2102 | 68 | }; | 67 | |
2103 | 69 | 68 | static void single(boost::shared_ptr<FieldCodecBase> codec, | |
2104 | 70 | struct Encoder | 69 | unsigned* return_value, |
2105 | 71 | { | 70 | const boost::any& field_value, |
2106 | 72 | static void repeated(boost::shared_ptr<FieldCodecBase> codec, | 71 | const google::protobuf::FieldDescriptor* field_desc) |
2107 | 73 | Bitset* return_value, | 72 | { |
2108 | 74 | const std::vector<boost::any>& field_values, | 73 | codec->field_size(return_value, field_value, field_desc); |
2109 | 75 | const google::protobuf::FieldDescriptor* field_desc) | 74 | } |
2110 | 76 | { | 75 | |
2111 | 77 | codec->field_encode_repeated(return_value, field_values, field_desc); | 76 | }; |
2112 | 78 | } | 77 | |
2113 | 79 | 78 | struct Encoder | |
2114 | 80 | static void single(boost::shared_ptr<FieldCodecBase> codec, | 79 | { |
2115 | 81 | Bitset* return_value, | 80 | static void repeated(boost::shared_ptr<FieldCodecBase> codec, |
2116 | 82 | const boost::any& field_value, | 81 | Bitset* return_value, |
2117 | 83 | const google::protobuf::FieldDescriptor* field_desc) | 82 | const std::vector<boost::any>& field_values, |
2118 | 84 | { | 83 | const google::protobuf::FieldDescriptor* field_desc) |
2119 | 85 | codec->field_encode(return_value, field_value, field_desc); | 84 | { |
2120 | 86 | } | 85 | codec->field_encode_repeated(return_value, field_values, field_desc); |
2121 | 87 | }; | 86 | } |
2122 | 88 | 87 | ||
2123 | 89 | struct MaxSize | 88 | static void single(boost::shared_ptr<FieldCodecBase> codec, |
2124 | 90 | { | 89 | Bitset* return_value, |
2125 | 91 | static void field(boost::shared_ptr<FieldCodecBase> codec, | 90 | const boost::any& field_value, |
2126 | 92 | unsigned* return_value, | 91 | const google::protobuf::FieldDescriptor* field_desc) |
2127 | 93 | const google::protobuf::FieldDescriptor* field_desc) | 92 | { |
2128 | 94 | { | 93 | codec->field_encode(return_value, field_value, field_desc); |
2129 | 95 | codec->field_max_size(return_value, field_desc); | 94 | } |
2130 | 96 | } | 95 | }; |
2131 | 97 | }; | 96 | |
2132 | 98 | 97 | struct MaxSize | |
2133 | 99 | struct MinSize | 98 | { |
2134 | 100 | { | 99 | static void field(boost::shared_ptr<FieldCodecBase> codec, |
2135 | 101 | static void field(boost::shared_ptr<FieldCodecBase> codec, | 100 | unsigned* return_value, |
2136 | 102 | unsigned* return_value, | 101 | const google::protobuf::FieldDescriptor* field_desc) |
2137 | 103 | const google::protobuf::FieldDescriptor* field_desc) | 102 | { |
2138 | 104 | { | 103 | codec->field_max_size(return_value, field_desc); |
2139 | 105 | codec->field_min_size(return_value, field_desc); | 104 | } |
2140 | 106 | } | 105 | }; |
2141 | 107 | }; | 106 | |
2142 | 108 | 107 | struct MinSize | |
2143 | 109 | 108 | { | |
2144 | 110 | struct Validate | 109 | static void field(boost::shared_ptr<FieldCodecBase> codec, |
2145 | 111 | { | 110 | unsigned* return_value, |
2146 | 112 | static void field(boost::shared_ptr<FieldCodecBase> codec, | 111 | const google::protobuf::FieldDescriptor* field_desc) |
2147 | 113 | bool* return_value, | 112 | { |
2148 | 114 | const google::protobuf::FieldDescriptor* field_desc) | 113 | codec->field_min_size(return_value, field_desc); |
2149 | 115 | { | 114 | } |
2150 | 116 | codec->field_validate(return_value, field_desc); | 115 | }; |
2151 | 117 | } | 116 | |
2152 | 118 | }; | 117 | |
2153 | 119 | 118 | struct Validate | |
2154 | 120 | struct Info | 119 | { |
2155 | 121 | { | 120 | static void field(boost::shared_ptr<FieldCodecBase> codec, |
2156 | 122 | static void field(boost::shared_ptr<FieldCodecBase> codec, | 121 | bool* return_value, |
2157 | 123 | std::stringstream* return_value, | 122 | const google::protobuf::FieldDescriptor* field_desc) |
2158 | 124 | const google::protobuf::FieldDescriptor* field_desc) | 123 | { |
2159 | 125 | { | 124 | codec->field_validate(return_value, field_desc); |
2160 | 126 | codec->field_info(return_value, field_desc); | 125 | } |
2161 | 127 | } | 126 | }; |
2162 | 128 | }; | 127 | |
2163 | 129 | 128 | struct Info | |
2164 | 130 | 129 | { | |
2165 | 131 | template<typename Action, typename ReturnType> | 130 | static void field(boost::shared_ptr<FieldCodecBase> codec, |
2166 | 132 | void traverse_descriptor(ReturnType* return_value) | 131 | std::stringstream* return_value, |
2167 | 133 | { | 132 | const google::protobuf::FieldDescriptor* field_desc) |
2168 | 134 | const google::protobuf::Descriptor* desc = | 133 | { |
2169 | 135 | FieldCodecBase::this_descriptor(); | 134 | codec->field_info(return_value, field_desc); |
2170 | 136 | for(int i = 0, n = desc->field_count(); i < n; ++i) | 135 | } |
2171 | 137 | { | 136 | }; |
2172 | 138 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | 137 | |
2173 | 138 | |||
2174 | 139 | template<typename Action, typename ReturnType> | ||
2175 | 140 | void traverse_descriptor(ReturnType* return_value) | ||
2176 | 141 | { | ||
2177 | 142 | const google::protobuf::Descriptor* desc = | ||
2178 | 143 | FieldCodecBase::this_descriptor(); | ||
2179 | 144 | for(int i = 0, n = desc->field_count(); i < n; ++i) | ||
2180 | 145 | { | ||
2181 | 146 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | ||
2182 | 139 | 147 | ||
2185 | 140 | if(!check_field(field_desc)) | 148 | if(!check_field(field_desc)) |
2186 | 141 | continue; | 149 | continue; |
2187 | 142 | 150 | ||
2190 | 143 | Action::field(FieldCodecManager::find(field_desc), | 151 | Action::field(find(field_desc), return_value, field_desc); |
2191 | 144 | return_value, field_desc); | 152 | } |
2192 | 145 | } | 153 | } |
2193 | 146 | } | ||
2194 | 147 | 154 | ||
2195 | 148 | 155 | ||
2200 | 149 | template<typename Action, typename ReturnType> | 156 | template<typename Action, typename ReturnType> |
2201 | 150 | ReturnType traverse_const_message(const boost::any& wire_value) | 157 | ReturnType traverse_const_message(const boost::any& wire_value) |
2198 | 151 | { | ||
2199 | 152 | try | ||
2202 | 153 | { | 158 | { |
2204 | 154 | ReturnType return_value = ReturnType(); | 159 | try |
2205 | 160 | { | ||
2206 | 161 | ReturnType return_value = ReturnType(); | ||
2207 | 155 | 162 | ||
2214 | 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); |
2215 | 157 | const google::protobuf::Descriptor* desc = msg->GetDescriptor(); | 164 | const google::protobuf::Descriptor* desc = msg->GetDescriptor(); |
2216 | 158 | const google::protobuf::Reflection* refl = msg->GetReflection(); | 165 | const google::protobuf::Reflection* refl = msg->GetReflection(); |
2217 | 159 | for(int i = 0, n = desc->field_count(); i < n; ++i) | 166 | for(int i = 0, n = desc->field_count(); i < n; ++i) |
2218 | 160 | { | 167 | { |
2219 | 161 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | 168 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); |
2220 | 162 | 169 | ||
2223 | 163 | if(!check_field(field_desc)) | 170 | if(!check_field(field_desc)) |
2224 | 164 | continue; | 171 | continue; |
2225 | 165 | 172 | ||
2237 | 166 | boost::shared_ptr<FieldCodecBase> codec = | 173 | boost::shared_ptr<FieldCodecBase> codec = find(field_desc); |
2238 | 167 | FieldCodecManager::find(field_desc); | 174 | boost::shared_ptr<FromProtoCppTypeBase> helper = |
2239 | 168 | boost::shared_ptr<FromProtoCppTypeBase> helper = | 175 | TypeHelper::find(field_desc); |
2240 | 169 | TypeHelper::find(field_desc); | 176 | |
2241 | 170 | 177 | ||
2242 | 171 | 178 | if(field_desc->is_repeated()) | |
2243 | 172 | if(field_desc->is_repeated()) | 179 | { |
2244 | 173 | { | 180 | std::vector<boost::any> field_values; |
2245 | 174 | std::vector<boost::any> field_values; | 181 | for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j) |
2246 | 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)); |
2236 | 176 | field_values.push_back(helper->get_repeated_value(field_desc, *msg, j)); | ||
2247 | 177 | 183 | ||
2313 | 178 | Action::repeated(codec, &return_value, field_values, field_desc); | 184 | Action::repeated(codec, &return_value, field_values, field_desc); |
2314 | 179 | } | 185 | } |
2315 | 180 | else | 186 | else |
2316 | 181 | { | 187 | { |
2317 | 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); |
2318 | 183 | } | 189 | } |
2319 | 184 | } | 190 | } |
2320 | 185 | return return_value; | 191 | return return_value; |
2321 | 186 | } | 192 | } |
2322 | 187 | catch(boost::bad_any_cast& e) | 193 | catch(boost::bad_any_cast& e) |
2323 | 188 | { | 194 | { |
2324 | 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()))); |
2325 | 190 | } | 196 | } |
2326 | 191 | 197 | ||
2327 | 192 | } | 198 | } |
2328 | 193 | 199 | }; | |
2329 | 194 | template<typename Action, typename ReturnType> | 200 | |
2330 | 195 | ReturnType traverse_mutable_message(const boost::any& wire_value) | 201 | } |
2266 | 196 | { | ||
2267 | 197 | try | ||
2268 | 198 | { | ||
2269 | 199 | ReturnType return_value = ReturnType(); | ||
2270 | 200 | |||
2271 | 201 | const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value); | ||
2272 | 202 | const google::protobuf::Descriptor* desc = msg->GetDescriptor(); | ||
2273 | 203 | const google::protobuf::Reflection* refl = msg->GetReflection(); | ||
2274 | 204 | for(int i = 0, n = desc->field_count(); i < n; ++i) | ||
2275 | 205 | { | ||
2276 | 206 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | ||
2277 | 207 | |||
2278 | 208 | if(!check_field(field_desc)) | ||
2279 | 209 | continue; | ||
2280 | 210 | |||
2281 | 211 | boost::shared_ptr<FieldCodecBase> codec = | ||
2282 | 212 | FieldCodecManager::find(field_desc); | ||
2283 | 213 | boost::shared_ptr<FromProtoCppTypeBase> helper = | ||
2284 | 214 | TypeHelper::find(field_desc); | ||
2285 | 215 | |||
2286 | 216 | |||
2287 | 217 | if(field_desc->is_repeated()) | ||
2288 | 218 | { | ||
2289 | 219 | std::vector<boost::any> field_values; | ||
2290 | 220 | for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j) | ||
2291 | 221 | field_values.push_back(helper->get_repeated_value(field_desc, *msg, j)); | ||
2292 | 222 | |||
2293 | 223 | Action::repeated(codec, &return_value, field_values, field_desc); | ||
2294 | 224 | } | ||
2295 | 225 | else | ||
2296 | 226 | { | ||
2297 | 227 | Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc); | ||
2298 | 228 | } | ||
2299 | 229 | } | ||
2300 | 230 | return return_value; | ||
2301 | 231 | } | ||
2302 | 232 | catch(boost::bad_any_cast& e) | ||
2303 | 233 | { | ||
2304 | 234 | throw(Exception("Bad type given to traverse, expecting const google::protobuf::Message*")); | ||
2305 | 235 | } | ||
2306 | 236 | |||
2307 | 237 | } | ||
2308 | 238 | |||
2309 | 239 | |||
2310 | 240 | |||
2311 | 241 | }; | ||
2312 | 242 | |||
2331 | 243 | } | 202 | } |
2332 | 244 | 203 | ||
2333 | 245 | |||
2334 | 246 | //encode, size, etc. | 204 | //encode, size, etc. |
2335 | 247 | 205 | ||
2336 | 248 | 206 | ||
2337 | 249 | 207 | ||
2338 | === added directory 'src/codecs3' | |||
2339 | === added file 'src/codecs3/field_codec_default.cpp' | |||
2340 | --- src/codecs3/field_codec_default.cpp 1970-01-01 00:00:00 +0000 | |||
2341 | +++ src/codecs3/field_codec_default.cpp 2014-08-27 16:27:22 +0000 | |||
2342 | @@ -0,0 +1,122 @@ | |||
2343 | 1 | // Copyright 2009-2014 Toby Schneider (https://launchpad.net/~tes) | ||
2344 | 2 | // GobySoft, LLC (2013-) | ||
2345 | 3 | // Massachusetts Institute of Technology (2007-2014) | ||
2346 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
2347 | 5 | // | ||
2348 | 6 | // This file is part of the Dynamic Compact Control Language Library | ||
2349 | 7 | // ("DCCL"). | ||
2350 | 8 | // | ||
2351 | 9 | // DCCL is free software: you can redistribute them and/or modify | ||
2352 | 10 | // them under the terms of the GNU Lesser General Public License as published by | ||
2353 | 11 | // the Free Software Foundation, either version 2.1 of the License, or | ||
2354 | 12 | // (at your option) any later version. | ||
2355 | 13 | // | ||
2356 | 14 | // DCCL is distributed in the hope that they will be useful, | ||
2357 | 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2358 | 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2359 | 17 | // GNU Lesser General Public License for more details. | ||
2360 | 18 | // | ||
2361 | 19 | // You should have received a copy of the GNU Lesser General Public License | ||
2362 | 20 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
2363 | 21 | |||
2364 | 22 | #include "dccl/codecs3/field_codec_default.h" | ||
2365 | 23 | |||
2366 | 24 | using namespace dccl::logger; | ||
2367 | 25 | |||
2368 | 26 | // | ||
2369 | 27 | // DefaultStringCodec | ||
2370 | 28 | // | ||
2371 | 29 | |||
2372 | 30 | dccl::Bitset dccl::v3::DefaultStringCodec::encode() | ||
2373 | 31 | { | ||
2374 | 32 | return Bitset(min_size()); | ||
2375 | 33 | } | ||
2376 | 34 | |||
2377 | 35 | dccl::Bitset dccl::v3::DefaultStringCodec::encode(const std::string& wire_value) | ||
2378 | 36 | { | ||
2379 | 37 | std::string s = wire_value; | ||
2380 | 38 | if(s.size() > dccl_field_options().max_length()) | ||
2381 | 39 | { | ||
2382 | 40 | dccl::dlog.is(DEBUG2) && dccl::dlog << "String " << s << " exceeds `dccl.max_length`, truncating" << std::endl; | ||
2383 | 41 | s.resize(dccl_field_options().max_length()); | ||
2384 | 42 | } | ||
2385 | 43 | |||
2386 | 44 | |||
2387 | 45 | Bitset value_bits; | ||
2388 | 46 | value_bits.from_byte_string(s); | ||
2389 | 47 | |||
2390 | 48 | Bitset length_bits(min_size(), s.length()); | ||
2391 | 49 | |||
2392 | 50 | dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec value_bits: " << value_bits << std::endl; | ||
2393 | 51 | |||
2394 | 52 | |||
2395 | 53 | dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec length_bits: " << length_bits << std::endl; | ||
2396 | 54 | |||
2397 | 55 | // adds to MSBs | ||
2398 | 56 | for(int i = 0, n = value_bits.size(); i < n; ++i) | ||
2399 | 57 | length_bits.push_back(value_bits[i]); | ||
2400 | 58 | |||
2401 | 59 | dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec created: " << length_bits << std::endl; | ||
2402 | 60 | |||
2403 | 61 | |||
2404 | 62 | return length_bits; | ||
2405 | 63 | } | ||
2406 | 64 | |||
2407 | 65 | std::string dccl::v3::DefaultStringCodec::decode(Bitset* bits) | ||
2408 | 66 | { | ||
2409 | 67 | unsigned value_length = bits->to_ulong(); | ||
2410 | 68 | |||
2411 | 69 | if(value_length) | ||
2412 | 70 | { | ||
2413 | 71 | |||
2414 | 72 | unsigned header_length = min_size(); | ||
2415 | 73 | |||
2416 | 74 | dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl; | ||
2417 | 75 | |||
2418 | 76 | dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl; | ||
2419 | 77 | |||
2420 | 78 | // grabs more bits to add to the MSBs of `bits` | ||
2421 | 79 | bits->get_more_bits(value_length*BITS_IN_BYTE); | ||
2422 | 80 | |||
2423 | 81 | |||
2424 | 82 | dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl; | ||
2425 | 83 | Bitset string_body_bits = *bits; | ||
2426 | 84 | string_body_bits >>= header_length; | ||
2427 | 85 | string_body_bits.resize(bits->size() - header_length); | ||
2428 | 86 | |||
2429 | 87 | return string_body_bits.to_byte_string(); | ||
2430 | 88 | } | ||
2431 | 89 | else | ||
2432 | 90 | { | ||
2433 | 91 | throw NullValueException(); | ||
2434 | 92 | } | ||
2435 | 93 | |||
2436 | 94 | } | ||
2437 | 95 | |||
2438 | 96 | unsigned dccl::v3::DefaultStringCodec::size() | ||
2439 | 97 | { | ||
2440 | 98 | return min_size(); | ||
2441 | 99 | } | ||
2442 | 100 | |||
2443 | 101 | unsigned dccl::v3::DefaultStringCodec::size(const std::string& wire_value) | ||
2444 | 102 | { | ||
2445 | 103 | return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size()); | ||
2446 | 104 | } | ||
2447 | 105 | |||
2448 | 106 | |||
2449 | 107 | unsigned dccl::v3::DefaultStringCodec::max_size() | ||
2450 | 108 | { | ||
2451 | 109 | // string length + actual string | ||
2452 | 110 | return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE; | ||
2453 | 111 | } | ||
2454 | 112 | |||
2455 | 113 | unsigned dccl::v3::DefaultStringCodec::min_size() | ||
2456 | 114 | { | ||
2457 | 115 | return dccl::ceil_log2(dccl_field_options().max_length()+1); | ||
2458 | 116 | } | ||
2459 | 117 | |||
2460 | 118 | |||
2461 | 119 | void dccl::v3::DefaultStringCodec::validate() | ||
2462 | 120 | { | ||
2463 | 121 | require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length"); | ||
2464 | 122 | } | ||
2465 | 0 | 123 | ||
2466 | === added file 'src/codecs3/field_codec_default.h' | |||
2467 | --- src/codecs3/field_codec_default.h 1970-01-01 00:00:00 +0000 | |||
2468 | +++ src/codecs3/field_codec_default.h 2014-08-27 16:27:22 +0000 | |||
2469 | @@ -0,0 +1,77 @@ | |||
2470 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
2471 | 2 | // Massachusetts Institute of Technology (2007-) | ||
2472 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
2473 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
2474 | 5 | // | ||
2475 | 6 | // | ||
2476 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
2477 | 8 | // ("DCCL"). | ||
2478 | 9 | // | ||
2479 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
2480 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
2481 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
2482 | 13 | // (at your option) any later version. | ||
2483 | 14 | // | ||
2484 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
2485 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2486 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2487 | 18 | // GNU Lesser General Public License for more details. | ||
2488 | 19 | // | ||
2489 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
2490 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
2491 | 22 | |||
2492 | 23 | |||
2493 | 24 | |||
2494 | 25 | // implements FieldCodecBase for all the basic DCCL types for version 3 | ||
2495 | 26 | |||
2496 | 27 | #ifndef DCCLV3FIELDCODECDEFAULT20140403H | ||
2497 | 28 | #define DCCLV3FIELDCODECDEFAULT20140403H | ||
2498 | 29 | |||
2499 | 30 | #include "dccl/codecs2/field_codec_default.h" | ||
2500 | 31 | |||
2501 | 32 | namespace dccl | ||
2502 | 33 | { | ||
2503 | 34 | namespace v3 | ||
2504 | 35 | { | ||
2505 | 36 | // all these are the same as version 2 | ||
2506 | 37 | template<typename WireType, typename FieldType = WireType> | ||
2507 | 38 | class DefaultNumericFieldCodec : public v2::DefaultNumericFieldCodec<WireType, FieldType> { }; | ||
2508 | 39 | |||
2509 | 40 | typedef v2::DefaultBoolCodec DefaultBoolCodec; | ||
2510 | 41 | typedef v2::DefaultBytesCodec DefaultBytesCodec; | ||
2511 | 42 | typedef v2::DefaultEnumCodec DefaultEnumCodec; | ||
2512 | 43 | |||
2513 | 44 | |||
2514 | 45 | template<typename TimeType> | ||
2515 | 46 | class TimeCodec : public v2::TimeCodecBase<TimeType, 0> | ||
2516 | 47 | { BOOST_STATIC_ASSERT(sizeof(TimeCodec) == 0); }; | ||
2517 | 48 | |||
2518 | 49 | template<> class TimeCodec<uint64> : public v2::TimeCodecBase<uint64, 1000000> { }; | ||
2519 | 50 | template<> class TimeCodec<int64> : public v2::TimeCodecBase<int64, 1000000> { }; | ||
2520 | 51 | template<> class TimeCodec<double> : public v2::TimeCodecBase<double, 1> { }; | ||
2521 | 52 | |||
2522 | 53 | template<typename T> | ||
2523 | 54 | class StaticCodec : public v2::StaticCodec<T> | ||
2524 | 55 | { }; | ||
2525 | 56 | |||
2526 | 57 | |||
2527 | 58 | /// \brief Provides an variable length ASCII string encoder. | ||
2528 | 59 | /// | ||
2529 | 60 | /// [length of following string size: ceil(log2(max_length))][string] | ||
2530 | 61 | class DefaultStringCodec : public TypedFieldCodec<std::string> | ||
2531 | 62 | { | ||
2532 | 63 | private: | ||
2533 | 64 | Bitset encode(); | ||
2534 | 65 | Bitset encode(const std::string& wire_value); | ||
2535 | 66 | std::string decode(Bitset* bits); | ||
2536 | 67 | unsigned size(); | ||
2537 | 68 | unsigned size(const std::string& wire_value); | ||
2538 | 69 | unsigned max_size(); | ||
2539 | 70 | unsigned min_size(); | ||
2540 | 71 | void validate(); | ||
2541 | 72 | }; | ||
2542 | 73 | |||
2543 | 74 | } | ||
2544 | 75 | } | ||
2545 | 76 | |||
2546 | 77 | #endif | ||
2547 | 0 | 78 | ||
2548 | === added file 'src/codecs3/field_codec_default_message.cpp' | |||
2549 | --- src/codecs3/field_codec_default_message.cpp 1970-01-01 00:00:00 +0000 | |||
2550 | +++ src/codecs3/field_codec_default_message.cpp 2014-08-27 16:27:22 +0000 | |||
2551 | @@ -0,0 +1,236 @@ | |||
2552 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
2553 | 2 | // Massachusetts Institute of Technology (2007-) | ||
2554 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
2555 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
2556 | 5 | // | ||
2557 | 6 | // | ||
2558 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
2559 | 8 | // ("DCCL"). | ||
2560 | 9 | // | ||
2561 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
2562 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
2563 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
2564 | 13 | // (at your option) any later version. | ||
2565 | 14 | // | ||
2566 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
2567 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2568 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2569 | 18 | // GNU Lesser General Public License for more details. | ||
2570 | 19 | // | ||
2571 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
2572 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
2573 | 22 | |||
2574 | 23 | |||
2575 | 24 | |||
2576 | 25 | #include "dccl/codec.h" | ||
2577 | 26 | #include "dccl/codecs3/field_codec_default_message.h" | ||
2578 | 27 | |||
2579 | 28 | using dccl::dlog; | ||
2580 | 29 | |||
2581 | 30 | // | ||
2582 | 31 | // DefaultMessageCodec | ||
2583 | 32 | // | ||
2584 | 33 | |||
2585 | 34 | void dccl::v3::DefaultMessageCodec::any_encode(Bitset* bits, const boost::any& wire_value) | ||
2586 | 35 | { | ||
2587 | 36 | if(wire_value.empty()) | ||
2588 | 37 | { | ||
2589 | 38 | *bits = Bitset(min_size()); | ||
2590 | 39 | } | ||
2591 | 40 | else | ||
2592 | 41 | { | ||
2593 | 42 | *bits = traverse_const_message<Encoder, Bitset>(wire_value); | ||
2594 | 43 | |||
2595 | 44 | if(is_optional()) | ||
2596 | 45 | bits->push_front(true); // presence bit | ||
2597 | 46 | |||
2598 | 47 | } | ||
2599 | 48 | } | ||
2600 | 49 | |||
2601 | 50 | |||
2602 | 51 | |||
2603 | 52 | unsigned dccl::v3::DefaultMessageCodec::any_size(const boost::any& wire_value) | ||
2604 | 53 | { | ||
2605 | 54 | if(wire_value.empty()) | ||
2606 | 55 | { | ||
2607 | 56 | return min_size(); | ||
2608 | 57 | } | ||
2609 | 58 | else | ||
2610 | 59 | { | ||
2611 | 60 | unsigned size = traverse_const_message<Size, unsigned>(wire_value); | ||
2612 | 61 | if(is_optional()) | ||
2613 | 62 | { | ||
2614 | 63 | const unsigned presence_bit = 1; | ||
2615 | 64 | size += presence_bit; | ||
2616 | 65 | } | ||
2617 | 66 | |||
2618 | 67 | return size; | ||
2619 | 68 | } | ||
2620 | 69 | } | ||
2621 | 70 | |||
2622 | 71 | |||
2623 | 72 | void dccl::v3::DefaultMessageCodec::any_decode(Bitset* bits, boost::any* wire_value) | ||
2624 | 73 | { | ||
2625 | 74 | try | ||
2626 | 75 | { | ||
2627 | 76 | |||
2628 | 77 | google::protobuf::Message* msg = boost::any_cast<google::protobuf::Message* >(*wire_value); | ||
2629 | 78 | |||
2630 | 79 | if(is_optional()) | ||
2631 | 80 | { | ||
2632 | 81 | if(!bits->to_ulong()) | ||
2633 | 82 | { | ||
2634 | 83 | *wire_value = boost::any(); | ||
2635 | 84 | return; | ||
2636 | 85 | } | ||
2637 | 86 | else | ||
2638 | 87 | { | ||
2639 | 88 | bits->pop_front(); // presence bit | ||
2640 | 89 | } | ||
2641 | 90 | } | ||
2642 | 91 | |||
2643 | 92 | const google::protobuf::Descriptor* desc = msg->GetDescriptor(); | ||
2644 | 93 | const google::protobuf::Reflection* refl = msg->GetReflection(); | ||
2645 | 94 | |||
2646 | 95 | for(int i = 0, n = desc->field_count(); i < n; ++i) | ||
2647 | 96 | { | ||
2648 | 97 | |||
2649 | 98 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | ||
2650 | 99 | |||
2651 | 100 | if(!check_field(field_desc)) | ||
2652 | 101 | continue; | ||
2653 | 102 | |||
2654 | 103 | |||
2655 | 104 | boost::shared_ptr<FieldCodecBase> codec = find(field_desc); | ||
2656 | 105 | boost::shared_ptr<FromProtoCppTypeBase> helper = | ||
2657 | 106 | TypeHelper::find(field_desc); | ||
2658 | 107 | |||
2659 | 108 | if(field_desc->is_repeated()) | ||
2660 | 109 | { | ||
2661 | 110 | std::vector<boost::any> field_values; | ||
2662 | 111 | if(field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) | ||
2663 | 112 | { | ||
2664 | 113 | unsigned max_repeat = field_desc->options().GetExtension(dccl::field).max_repeat(); | ||
2665 | 114 | for(unsigned j = 0, m = max_repeat; j < m; ++j) | ||
2666 | 115 | field_values.push_back(refl->AddMessage(msg, field_desc)); | ||
2667 | 116 | |||
2668 | 117 | codec->field_decode_repeated(bits, &field_values, field_desc); | ||
2669 | 118 | |||
2670 | 119 | // remove the unused messages | ||
2671 | 120 | for(int j = field_values.size(), m = max_repeat; j < m; ++j) | ||
2672 | 121 | { | ||
2673 | 122 | refl->RemoveLast(msg, field_desc); | ||
2674 | 123 | } | ||
2675 | 124 | } | ||
2676 | 125 | else | ||
2677 | 126 | { | ||
2678 | 127 | // for primitive types | ||
2679 | 128 | codec->field_decode_repeated(bits, &field_values, field_desc); | ||
2680 | 129 | for(int j = 0, m = field_values.size(); j < m; ++j) | ||
2681 | 130 | helper->add_value(field_desc, msg, field_values[j]); | ||
2682 | 131 | } | ||
2683 | 132 | } | ||
2684 | 133 | else | ||
2685 | 134 | { | ||
2686 | 135 | boost::any field_value; | ||
2687 | 136 | if(field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) | ||
2688 | 137 | { | ||
2689 | 138 | // allows us to propagate pointers instead of making many copies of entire messages | ||
2690 | 139 | field_value = refl->MutableMessage(msg, field_desc); | ||
2691 | 140 | codec->field_decode(bits, &field_value, field_desc); | ||
2692 | 141 | if(field_value.empty()) refl->ClearField(msg, field_desc); | ||
2693 | 142 | } | ||
2694 | 143 | else | ||
2695 | 144 | { | ||
2696 | 145 | // for primitive types | ||
2697 | 146 | codec->field_decode(bits, &field_value, field_desc); | ||
2698 | 147 | helper->set_value(field_desc, msg, field_value); | ||
2699 | 148 | } | ||
2700 | 149 | } | ||
2701 | 150 | } | ||
2702 | 151 | |||
2703 | 152 | std::vector< const google::protobuf::FieldDescriptor* > set_fields; | ||
2704 | 153 | refl->ListFields(*msg, &set_fields); | ||
2705 | 154 | if(set_fields.empty() && this_field()) *wire_value = boost::any(); | ||
2706 | 155 | else *wire_value = msg; | ||
2707 | 156 | } | ||
2708 | 157 | catch(boost::bad_any_cast& e) | ||
2709 | 158 | { | ||
2710 | 159 | throw(Exception("Bad type given to traverse mutable, expecting google::protobuf::Message*, got " + std::string(wire_value->type().name()))); | ||
2711 | 160 | } | ||
2712 | 161 | |||
2713 | 162 | } | ||
2714 | 163 | |||
2715 | 164 | |||
2716 | 165 | unsigned dccl::v3::DefaultMessageCodec::max_size() | ||
2717 | 166 | { | ||
2718 | 167 | unsigned u = 0; | ||
2719 | 168 | traverse_descriptor<MaxSize>(&u); | ||
2720 | 169 | |||
2721 | 170 | if(is_optional()) | ||
2722 | 171 | { | ||
2723 | 172 | const unsigned presence_bit = 1; | ||
2724 | 173 | u += presence_bit; | ||
2725 | 174 | } | ||
2726 | 175 | |||
2727 | 176 | return u; | ||
2728 | 177 | } | ||
2729 | 178 | |||
2730 | 179 | unsigned dccl::v3::DefaultMessageCodec::min_size() | ||
2731 | 180 | { | ||
2732 | 181 | if(is_optional()) | ||
2733 | 182 | { | ||
2734 | 183 | const unsigned presence_bit = 1; | ||
2735 | 184 | return presence_bit; | ||
2736 | 185 | } | ||
2737 | 186 | else | ||
2738 | 187 | { | ||
2739 | 188 | unsigned u = 0; | ||
2740 | 189 | traverse_descriptor<MinSize>(&u); | ||
2741 | 190 | return u; | ||
2742 | 191 | } | ||
2743 | 192 | } | ||
2744 | 193 | |||
2745 | 194 | |||
2746 | 195 | void dccl::v3::DefaultMessageCodec::validate() | ||
2747 | 196 | { | ||
2748 | 197 | bool b = false; | ||
2749 | 198 | traverse_descriptor<Validate>(&b); | ||
2750 | 199 | } | ||
2751 | 200 | |||
2752 | 201 | std::string dccl::v3::DefaultMessageCodec::info() | ||
2753 | 202 | { | ||
2754 | 203 | std::stringstream ss; | ||
2755 | 204 | traverse_descriptor<Info>(&ss); | ||
2756 | 205 | return ss.str(); | ||
2757 | 206 | } | ||
2758 | 207 | |||
2759 | 208 | bool dccl::v3::DefaultMessageCodec::check_field(const google::protobuf::FieldDescriptor* field) | ||
2760 | 209 | { | ||
2761 | 210 | if(!field) | ||
2762 | 211 | { | ||
2763 | 212 | return true; | ||
2764 | 213 | } | ||
2765 | 214 | else | ||
2766 | 215 | { | ||
2767 | 216 | dccl::DCCLFieldOptions dccl_field_options = field->options().GetExtension(dccl::field); | ||
2768 | 217 | if(dccl_field_options.omit()) // omit | ||
2769 | 218 | { | ||
2770 | 219 | return false; | ||
2771 | 220 | } | ||
2772 | 221 | else if(MessageStack::current_part() == MessageStack::UNKNOWN) // part not yet explicitly specified | ||
2773 | 222 | { | ||
2774 | 223 | if((part() == MessageStack::HEAD && !dccl_field_options.in_head()) | ||
2775 | 224 | || (part() == MessageStack::BODY && dccl_field_options.in_head())) | ||
2776 | 225 | return false; | ||
2777 | 226 | else | ||
2778 | 227 | return true; | ||
2779 | 228 | } | ||
2780 | 229 | else if(MessageStack::current_part() != part()) // part specified and doesn't match | ||
2781 | 230 | return false; | ||
2782 | 231 | else | ||
2783 | 232 | return true; | ||
2784 | 233 | } | ||
2785 | 234 | } | ||
2786 | 235 | |||
2787 | 236 | |||
2788 | 0 | 237 | ||
2789 | === added file 'src/codecs3/field_codec_default_message.h' | |||
2790 | --- src/codecs3/field_codec_default_message.h 1970-01-01 00:00:00 +0000 | |||
2791 | +++ src/codecs3/field_codec_default_message.h 2014-08-27 16:27:22 +0000 | |||
2792 | @@ -0,0 +1,213 @@ | |||
2793 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
2794 | 2 | // Massachusetts Institute of Technology (2007-) | ||
2795 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
2796 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
2797 | 5 | // | ||
2798 | 6 | // | ||
2799 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
2800 | 8 | // ("DCCL"). | ||
2801 | 9 | // | ||
2802 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
2803 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
2804 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
2805 | 13 | // (at your option) any later version. | ||
2806 | 14 | // | ||
2807 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
2808 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2809 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2810 | 18 | // GNU Lesser General Public License for more details. | ||
2811 | 19 | // | ||
2812 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
2813 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
2814 | 22 | |||
2815 | 23 | |||
2816 | 24 | |||
2817 | 25 | #ifndef DCCLFIELDCODECDEFAULTMESSAGEV320140421H | ||
2818 | 26 | #define DCCLFIELDCODECDEFAULTMESSAGEV320140421H | ||
2819 | 27 | |||
2820 | 28 | #include "dccl/field_codec.h" | ||
2821 | 29 | #include "dccl/field_codec_manager.h" | ||
2822 | 30 | |||
2823 | 31 | #include "dccl/protobuf/option_extensions.pb.h" | ||
2824 | 32 | |||
2825 | 33 | namespace dccl | ||
2826 | 34 | { | ||
2827 | 35 | namespace v3 | ||
2828 | 36 | { | ||
2829 | 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. | ||
2830 | 38 | class DefaultMessageCodec : public FieldCodecBase | ||
2831 | 39 | { | ||
2832 | 40 | private: | ||
2833 | 41 | |||
2834 | 42 | void any_encode(Bitset* bits, const boost::any& wire_value); | ||
2835 | 43 | void any_decode(Bitset* bits, boost::any* wire_value); | ||
2836 | 44 | unsigned max_size(); | ||
2837 | 45 | unsigned min_size(); | ||
2838 | 46 | unsigned any_size(const boost::any& wire_value); | ||
2839 | 47 | |||
2840 | 48 | |||
2841 | 49 | boost::shared_ptr<FieldCodecBase> find(const google::protobuf::FieldDescriptor* field_desc) | ||
2842 | 50 | { | ||
2843 | 51 | return FieldCodecManager::find(field_desc, has_codec_group(), codec_group()); | ||
2844 | 52 | } | ||
2845 | 53 | |||
2846 | 54 | bool is_optional() | ||
2847 | 55 | { return this_field() && this_field()->is_optional(); } | ||
2848 | 56 | |||
2849 | 57 | |||
2850 | 58 | void validate(); | ||
2851 | 59 | std::string info(); | ||
2852 | 60 | bool check_field(const google::protobuf::FieldDescriptor* field); | ||
2853 | 61 | |||
2854 | 62 | struct Size | ||
2855 | 63 | { | ||
2856 | 64 | static void repeated(boost::shared_ptr<FieldCodecBase> codec, | ||
2857 | 65 | unsigned* return_value, | ||
2858 | 66 | const std::vector<boost::any>& field_values, | ||
2859 | 67 | const google::protobuf::FieldDescriptor* field_desc) | ||
2860 | 68 | { | ||
2861 | 69 | codec->field_size_repeated(return_value, field_values, field_desc); | ||
2862 | 70 | } | ||
2863 | 71 | |||
2864 | 72 | static void single(boost::shared_ptr<FieldCodecBase> codec, | ||
2865 | 73 | unsigned* return_value, | ||
2866 | 74 | const boost::any& field_value, | ||
2867 | 75 | const google::protobuf::FieldDescriptor* field_desc) | ||
2868 | 76 | { | ||
2869 | 77 | codec->field_size(return_value, field_value, field_desc); | ||
2870 | 78 | } | ||
2871 | 79 | |||
2872 | 80 | }; | ||
2873 | 81 | |||
2874 | 82 | struct Encoder | ||
2875 | 83 | { | ||
2876 | 84 | static void repeated(boost::shared_ptr<FieldCodecBase> codec, | ||
2877 | 85 | Bitset* return_value, | ||
2878 | 86 | const std::vector<boost::any>& field_values, | ||
2879 | 87 | const google::protobuf::FieldDescriptor* field_desc) | ||
2880 | 88 | { | ||
2881 | 89 | codec->field_encode_repeated(return_value, field_values, field_desc); | ||
2882 | 90 | } | ||
2883 | 91 | |||
2884 | 92 | static void single(boost::shared_ptr<FieldCodecBase> codec, | ||
2885 | 93 | Bitset* return_value, | ||
2886 | 94 | const boost::any& field_value, | ||
2887 | 95 | const google::protobuf::FieldDescriptor* field_desc) | ||
2888 | 96 | { | ||
2889 | 97 | codec->field_encode(return_value, field_value, field_desc); | ||
2890 | 98 | } | ||
2891 | 99 | }; | ||
2892 | 100 | |||
2893 | 101 | struct MaxSize | ||
2894 | 102 | { | ||
2895 | 103 | static void field(boost::shared_ptr<FieldCodecBase> codec, | ||
2896 | 104 | unsigned* return_value, | ||
2897 | 105 | const google::protobuf::FieldDescriptor* field_desc) | ||
2898 | 106 | { | ||
2899 | 107 | codec->field_max_size(return_value, field_desc); | ||
2900 | 108 | } | ||
2901 | 109 | }; | ||
2902 | 110 | |||
2903 | 111 | struct MinSize | ||
2904 | 112 | { | ||
2905 | 113 | static void field(boost::shared_ptr<FieldCodecBase> codec, | ||
2906 | 114 | unsigned* return_value, | ||
2907 | 115 | const google::protobuf::FieldDescriptor* field_desc) | ||
2908 | 116 | { | ||
2909 | 117 | codec->field_min_size(return_value, field_desc); | ||
2910 | 118 | } | ||
2911 | 119 | }; | ||
2912 | 120 | |||
2913 | 121 | |||
2914 | 122 | struct Validate | ||
2915 | 123 | { | ||
2916 | 124 | static void field(boost::shared_ptr<FieldCodecBase> codec, | ||
2917 | 125 | bool* return_value, | ||
2918 | 126 | const google::protobuf::FieldDescriptor* field_desc) | ||
2919 | 127 | { | ||
2920 | 128 | codec->field_validate(return_value, field_desc); | ||
2921 | 129 | } | ||
2922 | 130 | }; | ||
2923 | 131 | |||
2924 | 132 | struct Info | ||
2925 | 133 | { | ||
2926 | 134 | static void field(boost::shared_ptr<FieldCodecBase> codec, | ||
2927 | 135 | std::stringstream* return_value, | ||
2928 | 136 | const google::protobuf::FieldDescriptor* field_desc) | ||
2929 | 137 | { | ||
2930 | 138 | codec->field_info(return_value, field_desc); | ||
2931 | 139 | } | ||
2932 | 140 | }; | ||
2933 | 141 | |||
2934 | 142 | |||
2935 | 143 | template<typename Action, typename ReturnType> | ||
2936 | 144 | void traverse_descriptor(ReturnType* return_value) | ||
2937 | 145 | { | ||
2938 | 146 | const google::protobuf::Descriptor* desc = | ||
2939 | 147 | FieldCodecBase::this_descriptor(); | ||
2940 | 148 | for(int i = 0, n = desc->field_count(); i < n; ++i) | ||
2941 | 149 | { | ||
2942 | 150 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | ||
2943 | 151 | |||
2944 | 152 | if(!check_field(field_desc)) | ||
2945 | 153 | continue; | ||
2946 | 154 | |||
2947 | 155 | Action::field(find(field_desc), return_value, field_desc); | ||
2948 | 156 | } | ||
2949 | 157 | } | ||
2950 | 158 | |||
2951 | 159 | |||
2952 | 160 | template<typename Action, typename ReturnType> | ||
2953 | 161 | ReturnType traverse_const_message(const boost::any& wire_value) | ||
2954 | 162 | { | ||
2955 | 163 | try | ||
2956 | 164 | { | ||
2957 | 165 | ReturnType return_value = ReturnType(); | ||
2958 | 166 | |||
2959 | 167 | const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value); | ||
2960 | 168 | const google::protobuf::Descriptor* desc = msg->GetDescriptor(); | ||
2961 | 169 | const google::protobuf::Reflection* refl = msg->GetReflection(); | ||
2962 | 170 | for(int i = 0, n = desc->field_count(); i < n; ++i) | ||
2963 | 171 | { | ||
2964 | 172 | const google::protobuf::FieldDescriptor* field_desc = desc->field(i); | ||
2965 | 173 | |||
2966 | 174 | if(!check_field(field_desc)) | ||
2967 | 175 | continue; | ||
2968 | 176 | |||
2969 | 177 | boost::shared_ptr<FieldCodecBase> codec = find(field_desc); | ||
2970 | 178 | boost::shared_ptr<FromProtoCppTypeBase> helper = | ||
2971 | 179 | TypeHelper::find(field_desc); | ||
2972 | 180 | |||
2973 | 181 | |||
2974 | 182 | if(field_desc->is_repeated()) | ||
2975 | 183 | { | ||
2976 | 184 | std::vector<boost::any> field_values; | ||
2977 | 185 | for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j) | ||
2978 | 186 | field_values.push_back(helper->get_repeated_value(field_desc, *msg, j)); | ||
2979 | 187 | |||
2980 | 188 | Action::repeated(codec, &return_value, field_values, field_desc); | ||
2981 | 189 | } | ||
2982 | 190 | else | ||
2983 | 191 | { | ||
2984 | 192 | Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc); | ||
2985 | 193 | } | ||
2986 | 194 | } | ||
2987 | 195 | return return_value; | ||
2988 | 196 | } | ||
2989 | 197 | catch(boost::bad_any_cast& e) | ||
2990 | 198 | { | ||
2991 | 199 | throw(Exception("Bad type given to traverse const, expecting const google::protobuf::Message*, got " + std::string(wire_value.type().name()))); | ||
2992 | 200 | } | ||
2993 | 201 | |||
2994 | 202 | } | ||
2995 | 203 | }; | ||
2996 | 204 | |||
2997 | 205 | } | ||
2998 | 206 | } | ||
2999 | 207 | |||
3000 | 208 | //encode, size, etc. | ||
3001 | 209 | |||
3002 | 210 | |||
3003 | 211 | |||
3004 | 212 | |||
3005 | 213 | #endif | ||
3006 | 0 | 214 | ||
3007 | === modified file 'src/field_codec.cpp' | |||
3008 | --- src/field_codec.cpp 2014-04-22 20:10:37 +0000 | |||
3009 | +++ src/field_codec.cpp 2014-08-27 16:27:22 +0000 | |||
3010 | @@ -29,6 +29,7 @@ | |||
3011 | 29 | dccl::MessageStack::UNKNOWN; | 29 | dccl::MessageStack::UNKNOWN; |
3012 | 30 | 30 | ||
3013 | 31 | const google::protobuf::Message* dccl::FieldCodecBase::root_message_ = 0; | 31 | const google::protobuf::Message* dccl::FieldCodecBase::root_message_ = 0; |
3014 | 32 | const google::protobuf::Descriptor* dccl::FieldCodecBase::root_descriptor_ = 0; | ||
3015 | 32 | 33 | ||
3016 | 33 | using dccl::dlog; | 34 | using dccl::dlog; |
3017 | 34 | using namespace dccl::logger; | 35 | using namespace dccl::logger; |
3018 | @@ -66,6 +67,7 @@ | |||
3019 | 66 | 67 | ||
3020 | 67 | Bitset new_bits; | 68 | Bitset new_bits; |
3021 | 68 | any_encode(&new_bits, wire_value); | 69 | any_encode(&new_bits, wire_value); |
3022 | 70 | disp_size(field, new_bits, msg_handler.field_.size()); | ||
3023 | 69 | bits->append(new_bits); | 71 | bits->append(new_bits); |
3024 | 70 | } | 72 | } |
3025 | 71 | 73 | ||
3026 | @@ -80,6 +82,7 @@ | |||
3027 | 80 | 82 | ||
3028 | 81 | Bitset new_bits; | 83 | Bitset new_bits; |
3029 | 82 | any_encode_repeated(&new_bits, wire_values); | 84 | any_encode_repeated(&new_bits, wire_values); |
3030 | 85 | disp_size(field, new_bits, msg_handler.field_.size(), wire_values.size()); | ||
3031 | 83 | bits->append(new_bits); | 86 | bits->append(new_bits); |
3032 | 84 | } | 87 | } |
3033 | 85 | 88 | ||
3034 | @@ -190,7 +193,8 @@ | |||
3035 | 190 | 193 | ||
3036 | 191 | std::vector<boost::any> wire_values = *field_values; | 194 | std::vector<boost::any> wire_values = *field_values; |
3037 | 192 | any_decode_repeated(&these_bits, &wire_values); | 195 | any_decode_repeated(&these_bits, &wire_values); |
3039 | 193 | 196 | ||
3040 | 197 | field_values->clear(); | ||
3041 | 194 | field_post_decode_repeated(wire_values, field_values); | 198 | field_post_decode_repeated(wire_values, field_values); |
3042 | 195 | } | 199 | } |
3043 | 196 | 200 | ||
3044 | @@ -199,7 +203,7 @@ | |||
3045 | 199 | const google::protobuf::Descriptor* desc, | 203 | const google::protobuf::Descriptor* desc, |
3046 | 200 | MessageStack::MessagePart part) | 204 | MessageStack::MessagePart part) |
3047 | 201 | { | 205 | { |
3049 | 202 | BaseRAII scoped_globals(part); | 206 | BaseRAII scoped_globals(part, desc); |
3050 | 203 | *bit_size = 0; | 207 | *bit_size = 0; |
3051 | 204 | 208 | ||
3052 | 205 | MessageStack msg_handler; | 209 | MessageStack msg_handler; |
3053 | @@ -228,7 +232,7 @@ | |||
3054 | 228 | const google::protobuf::Descriptor* desc, | 232 | const google::protobuf::Descriptor* desc, |
3055 | 229 | MessageStack::MessagePart part) | 233 | MessageStack::MessagePart part) |
3056 | 230 | { | 234 | { |
3058 | 231 | BaseRAII scoped_globals(part); | 235 | BaseRAII scoped_globals(part, desc); |
3059 | 232 | 236 | ||
3060 | 233 | *bit_size = 0; | 237 | *bit_size = 0; |
3061 | 234 | 238 | ||
3062 | @@ -257,7 +261,7 @@ | |||
3063 | 257 | void dccl::FieldCodecBase::base_validate(const google::protobuf::Descriptor* desc, | 261 | void dccl::FieldCodecBase::base_validate(const google::protobuf::Descriptor* desc, |
3064 | 258 | MessageStack::MessagePart part) | 262 | MessageStack::MessagePart part) |
3065 | 259 | { | 263 | { |
3067 | 260 | BaseRAII scoped_globals(part); | 264 | BaseRAII scoped_globals(part, desc); |
3068 | 261 | 265 | ||
3069 | 262 | MessageStack msg_handler; | 266 | MessageStack msg_handler; |
3070 | 263 | if(desc) | 267 | if(desc) |
3071 | @@ -283,7 +287,7 @@ | |||
3072 | 283 | 287 | ||
3073 | 284 | void dccl::FieldCodecBase::base_info(std::ostream* os, const google::protobuf::Descriptor* desc, MessageStack::MessagePart part) | 288 | void dccl::FieldCodecBase::base_info(std::ostream* os, const google::protobuf::Descriptor* desc, MessageStack::MessagePart part) |
3074 | 285 | { | 289 | { |
3076 | 286 | BaseRAII scoped_globals(part); | 290 | BaseRAII scoped_globals(part, desc); |
3077 | 287 | 291 | ||
3078 | 288 | MessageStack msg_handler; | 292 | MessageStack msg_handler; |
3079 | 289 | if(desc) | 293 | if(desc) |
3080 | @@ -337,7 +341,11 @@ | |||
3081 | 337 | } | 341 | } |
3082 | 338 | 342 | ||
3083 | 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; |
3085 | 340 | ss << indent << name << std::setfill('.') << std::setw(std::max(1, width)) << range.str(); | 344 | ss << indent << name << |
3086 | 345 | std::setfill('.') << std::setw(std::max(1, width)) << range.str() | ||
3087 | 346 | << " {" << (this_field() ? FieldCodecManager::find(this_field(), has_codec_group(), codec_group())->name() : FieldCodecManager::find(root_descriptor_)->name()) << "}"; | ||
3088 | 347 | |||
3089 | 348 | |||
3090 | 341 | 349 | ||
3091 | 342 | // std::string s = ss.str(); | 350 | // std::string s = ss.str(); |
3092 | 343 | // boost::replace_all(s, "\n", "\n" + indent); | 351 | // boost::replace_all(s, "\n", "\n" + indent); |
3093 | @@ -353,6 +361,14 @@ | |||
3094 | 353 | 361 | ||
3095 | 354 | } | 362 | } |
3096 | 355 | 363 | ||
3097 | 364 | std::string dccl::FieldCodecBase::codec_group(const google::protobuf::Descriptor* desc) | ||
3098 | 365 | { | ||
3099 | 366 | if(desc->options().GetExtension(dccl::msg).has_codec_group()) | ||
3100 | 367 | return desc->options().GetExtension(dccl::msg).codec_group(); | ||
3101 | 368 | else | ||
3102 | 369 | return Codec::default_codec_name(desc->options().GetExtension(dccl::msg).codec_version()); | ||
3103 | 370 | } | ||
3104 | 371 | |||
3105 | 356 | 372 | ||
3106 | 357 | // | 373 | // |
3107 | 358 | // FieldCodecBase protected | 374 | // FieldCodecBase protected |
3108 | @@ -366,7 +382,18 @@ | |||
3109 | 366 | void dccl::FieldCodecBase::any_encode_repeated(dccl::Bitset* bits, const std::vector<boost::any>& wire_values) | 382 | void dccl::FieldCodecBase::any_encode_repeated(dccl::Bitset* bits, const std::vector<boost::any>& wire_values) |
3110 | 367 | { | 383 | { |
3111 | 368 | // out_bits = [field_values[2]][field_values[1]][field_values[0]] | 384 | // out_bits = [field_values[2]][field_values[1]][field_values[0]] |
3113 | 369 | for(unsigned i = 0, n = dccl_field_options().max_repeat(); i < n; ++i) | 385 | |
3114 | 386 | unsigned wire_vector_size = dccl_field_options().max_repeat(); | ||
3115 | 387 | |||
3116 | 388 | // for DCCL3 and beyond, add a prefix numeric field giving the vector size (rather than always going to max_repeat | ||
3117 | 389 | if(codec_version() > 2) | ||
3118 | 390 | { | ||
3119 | 391 | wire_vector_size = std::min((int)dccl_field_options().max_repeat(), (int)wire_values.size()); | ||
3120 | 392 | Bitset size_bits(repeated_vector_field_size(dccl_field_options().max_repeat()), wire_values.size()); | ||
3121 | 393 | bits->append(size_bits); | ||
3122 | 394 | } | ||
3123 | 395 | |||
3124 | 396 | for(unsigned i = 0, n = wire_vector_size; i < n; ++i) | ||
3125 | 370 | { | 397 | { |
3126 | 371 | Bitset new_bits; | 398 | Bitset new_bits; |
3127 | 372 | if(i < wire_values.size()) | 399 | if(i < wire_values.size()) |
3128 | @@ -379,27 +406,41 @@ | |||
3129 | 379 | } | 406 | } |
3130 | 380 | 407 | ||
3131 | 381 | 408 | ||
3132 | 409 | |||
3133 | 382 | void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* wire_values) | 410 | void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* wire_values) |
3134 | 383 | { | 411 | { |
3136 | 384 | for(unsigned i = 0, n = dccl_field_options().max_repeat(); i < n; ++i) | 412 | |
3137 | 413 | unsigned wire_vector_size = dccl_field_options().max_repeat(); | ||
3138 | 414 | if(codec_version() > 2) | ||
3139 | 415 | { | ||
3140 | 416 | Bitset size_bits(repeated_bits); | ||
3141 | 417 | size_bits.get_more_bits(repeated_vector_field_size(dccl_field_options().max_repeat())); | ||
3142 | 418 | |||
3143 | 419 | wire_vector_size = size_bits.to_ulong(); | ||
3144 | 420 | } | ||
3145 | 421 | |||
3146 | 422 | wire_values->resize(wire_vector_size); | ||
3147 | 423 | |||
3148 | 424 | for(unsigned i = 0, n = wire_vector_size; i < n; ++i) | ||
3149 | 385 | { | 425 | { |
3150 | 386 | Bitset these_bits(repeated_bits); | 426 | Bitset these_bits(repeated_bits); |
3160 | 387 | these_bits.get_more_bits(min_size()); | 427 | these_bits.get_more_bits(min_size()); |
3161 | 388 | 428 | any_decode(&these_bits, &(*wire_values)[i]); | |
3153 | 389 | boost::any value; | ||
3154 | 390 | |||
3155 | 391 | if(wire_values->size() > i) | ||
3156 | 392 | value = (*wire_values)[i]; | ||
3157 | 393 | |||
3158 | 394 | any_decode(&these_bits, &value); | ||
3159 | 395 | wire_values->push_back(value); | ||
3162 | 396 | } | 429 | } |
3163 | 397 | } | 430 | } |
3164 | 398 | 431 | ||
3165 | 399 | unsigned dccl::FieldCodecBase::any_size_repeated(const std::vector<boost::any>& wire_values) | 432 | unsigned dccl::FieldCodecBase::any_size_repeated(const std::vector<boost::any>& wire_values) |
3166 | 400 | { | 433 | { |
3167 | 401 | unsigned out = 0; | 434 | unsigned out = 0; |
3169 | 402 | for(unsigned i = 0, n = dccl_field_options().max_repeat(); i < n; ++i) | 435 | unsigned wire_vector_size = dccl_field_options().max_repeat(); |
3170 | 436 | |||
3171 | 437 | if(codec_version() > 2) | ||
3172 | 438 | { | ||
3173 | 439 | wire_vector_size = std::min((int)dccl_field_options().max_repeat(), (int)wire_values.size()); | ||
3174 | 440 | out += repeated_vector_field_size(dccl_field_options().max_repeat()); | ||
3175 | 441 | } | ||
3176 | 442 | |||
3177 | 443 | for(unsigned i = 0, n = wire_vector_size; i < n; ++i) | ||
3178 | 403 | { | 444 | { |
3179 | 404 | if(i < wire_values.size()) | 445 | if(i < wire_values.size()) |
3180 | 405 | out += any_size(wire_values[i]); | 446 | out += any_size(wire_values[i]); |
3181 | @@ -413,6 +454,8 @@ | |||
3182 | 413 | { | 454 | { |
3183 | 414 | if(!dccl_field_options().has_max_repeat()) | 455 | if(!dccl_field_options().has_max_repeat()) |
3184 | 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())); |
3185 | 457 | else if(codec_version() > 2) | ||
3186 | 458 | return repeated_vector_field_size(dccl_field_options().max_repeat()) + max_size() * dccl_field_options().max_repeat(); | ||
3187 | 416 | else | 459 | else |
3188 | 417 | return max_size() * dccl_field_options().max_repeat(); | 460 | return max_size() * dccl_field_options().max_repeat(); |
3189 | 418 | } | 461 | } |
3190 | @@ -421,6 +464,8 @@ | |||
3191 | 421 | { | 464 | { |
3192 | 422 | if(!dccl_field_options().has_max_repeat()) | 465 | if(!dccl_field_options().has_max_repeat()) |
3193 | 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())); |
3194 | 467 | else if(codec_version() > 2) | ||
3195 | 468 | return repeated_vector_field_size(dccl_field_options().max_repeat()); | ||
3196 | 424 | else | 469 | else |
3197 | 425 | return min_size() * dccl_field_options().max_repeat(); | 470 | return min_size() * dccl_field_options().max_repeat(); |
3198 | 426 | } | 471 | } |
3199 | @@ -453,3 +498,22 @@ | |||
3200 | 453 | // FieldCodecBase private | 498 | // FieldCodecBase private |
3201 | 454 | // | 499 | // |
3202 | 455 | 500 | ||
3203 | 501 | void dccl::FieldCodecBase::disp_size(const google::protobuf::FieldDescriptor* field, const Bitset& new_bits, int depth, int vector_size /* = -1 */) | ||
3204 | 502 | { | ||
3205 | 503 | if(!root_descriptor_) | ||
3206 | 504 | return; | ||
3207 | 505 | |||
3208 | 506 | if(dlog.is(INFO, SIZE)) | ||
3209 | 507 | { | ||
3210 | 508 | std::string name = ((field) ? field->name() : root_descriptor_->full_name()); | ||
3211 | 509 | if(vector_size >= 0) | ||
3212 | 510 | name += "[" + boost::lexical_cast<std::string>(vector_size) + "]"; | ||
3213 | 511 | |||
3214 | 512 | |||
3215 | 513 | dlog << std::string(depth, '|') << name << std::setfill('.') << std::setw(40-name.size()-depth) << new_bits.size() << std::endl; | ||
3216 | 514 | |||
3217 | 515 | if(!field) | ||
3218 | 516 | dlog << std::endl; | ||
3219 | 517 | |||
3220 | 518 | } | ||
3221 | 519 | } | ||
3222 | 456 | 520 | ||
3223 | === modified file 'src/field_codec.h' | |||
3224 | --- src/field_codec.h 2014-04-22 20:10:37 +0000 | |||
3225 | +++ src/field_codec.h 2014-08-27 16:27:22 +0000 | |||
3226 | @@ -28,6 +28,7 @@ | |||
3227 | 28 | #include <string> | 28 | #include <string> |
3228 | 29 | 29 | ||
3229 | 30 | #include <boost/any.hpp> | 30 | #include <boost/any.hpp> |
3230 | 31 | #include <boost/lexical_cast.hpp> | ||
3231 | 31 | 32 | ||
3232 | 32 | #include <google/protobuf/message.h> | 33 | #include <google/protobuf/message.h> |
3233 | 33 | #include <google/protobuf/descriptor.pb.h> | 34 | #include <google/protobuf/descriptor.pb.h> |
3234 | @@ -38,6 +39,7 @@ | |||
3235 | 38 | #include "dccl/protobuf/option_extensions.pb.h" | 39 | #include "dccl/protobuf/option_extensions.pb.h" |
3236 | 39 | #include "type_helper.h" | 40 | #include "type_helper.h" |
3237 | 40 | #include "field_codec_message_stack.h" | 41 | #include "field_codec_message_stack.h" |
3238 | 42 | #include "dccl/binary.h" | ||
3239 | 41 | 43 | ||
3240 | 42 | namespace dccl | 44 | namespace dccl |
3241 | 43 | { | 45 | { |
3242 | @@ -94,7 +96,25 @@ | |||
3243 | 94 | // currently encoded or (partially) decoded root message | 96 | // currently encoded or (partially) decoded root message |
3244 | 95 | static const google::protobuf::Message* root_message() | 97 | static const google::protobuf::Message* root_message() |
3245 | 96 | { return root_message_; } | 98 | { return root_message_; } |
3247 | 97 | 99 | ||
3248 | 100 | static bool has_codec_group() | ||
3249 | 101 | { | ||
3250 | 102 | if(root_descriptor_) | ||
3251 | 103 | { | ||
3252 | 104 | return root_descriptor_->options().GetExtension(dccl::msg).has_codec_group() || | ||
3253 | 105 | root_descriptor_->options().GetExtension(dccl::msg).has_codec_version(); | ||
3254 | 106 | } | ||
3255 | 107 | else | ||
3256 | 108 | return false; | ||
3257 | 109 | } | ||
3258 | 110 | |||
3259 | 111 | static std::string codec_group(const google::protobuf::Descriptor* desc); | ||
3260 | 112 | |||
3261 | 113 | static std::string codec_group() | ||
3262 | 114 | { return codec_group(root_descriptor_); } | ||
3263 | 115 | |||
3264 | 116 | static int codec_version() | ||
3265 | 117 | { return root_descriptor_->options().GetExtension(dccl::msg).codec_version(); } | ||
3266 | 98 | 118 | ||
3267 | 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). |
3268 | 100 | static MessageStack::MessagePart part() { return part_; } | 120 | static MessageStack::MessagePart part() { return part_; } |
3269 | @@ -379,7 +399,6 @@ | |||
3270 | 379 | /// | 399 | /// |
3271 | 380 | /// \return Minimum size of this field (in bits). | 400 | /// \return Minimum size of this field (in bits). |
3272 | 381 | virtual unsigned min_size() = 0; | 401 | virtual unsigned min_size() = 0; |
3273 | 382 | |||
3274 | 383 | 402 | ||
3275 | 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); |
3276 | 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); |
3277 | @@ -404,29 +423,52 @@ | |||
3278 | 404 | void set_wire_type(google::protobuf::FieldDescriptor::CppType type) | 423 | void set_wire_type(google::protobuf::FieldDescriptor::CppType type) |
3279 | 405 | { wire_type_ = type; } | 424 | { wire_type_ = type; } |
3280 | 406 | 425 | ||
3283 | 407 | bool variable_size() { return max_size() != min_size(); } | 426 | bool variable_size() |
3284 | 408 | 427 | { | |
3285 | 428 | if(this_field() && this_field()->is_repeated()) | ||
3286 | 429 | return max_size_repeated() != min_size_repeated(); | ||
3287 | 430 | else | ||
3288 | 431 | return max_size() != min_size(); | ||
3289 | 432 | } | ||
3290 | 433 | |||
3291 | 434 | int repeated_vector_field_size(int max_repeat) | ||
3292 | 435 | { return dccl::ceil_log2(max_repeat+1); } | ||
3293 | 436 | |||
3294 | 437 | void disp_size(const google::protobuf::FieldDescriptor* field, const Bitset& new_bits, int depth, int vector_size = -1); | ||
3295 | 438 | |||
3296 | 439 | |||
3297 | 409 | private: | 440 | private: |
3298 | 410 | // sets global statics relating the current message begin processed | 441 | // sets global statics relating the current message begin processed |
3299 | 411 | // and unsets them on destruction | 442 | // and unsets them on destruction |
3300 | 412 | struct BaseRAII | 443 | struct BaseRAII |
3301 | 413 | { | 444 | { |
3302 | 414 | BaseRAII(MessageStack::MessagePart part, | 445 | BaseRAII(MessageStack::MessagePart part, |
3304 | 415 | const google::protobuf::Message* root_message = 0) | 446 | const google::protobuf::Descriptor* root_descriptor) |
3305 | 447 | { | ||
3306 | 448 | FieldCodecBase::part_ = part; | ||
3307 | 449 | FieldCodecBase::root_message_ = 0; | ||
3308 | 450 | FieldCodecBase::root_descriptor_ = root_descriptor; | ||
3309 | 451 | } | ||
3310 | 452 | |||
3311 | 453 | BaseRAII(MessageStack::MessagePart part, | ||
3312 | 454 | const google::protobuf::Message* root_message) | ||
3313 | 416 | { | 455 | { |
3314 | 417 | FieldCodecBase::part_ = part; | 456 | FieldCodecBase::part_ = part; |
3315 | 418 | FieldCodecBase::root_message_ = root_message; | 457 | FieldCodecBase::root_message_ = root_message; |
3316 | 458 | FieldCodecBase::root_descriptor_ = root_message->GetDescriptor(); | ||
3317 | 419 | } | 459 | } |
3318 | 420 | ~BaseRAII() | 460 | ~BaseRAII() |
3319 | 421 | { | 461 | { |
3320 | 422 | FieldCodecBase::part_ = dccl::MessageStack::UNKNOWN; | 462 | FieldCodecBase::part_ = dccl::MessageStack::UNKNOWN; |
3321 | 423 | FieldCodecBase::root_message_ = 0; | 463 | FieldCodecBase::root_message_ = 0; |
3322 | 464 | FieldCodecBase::root_descriptor_ = 0; | ||
3323 | 424 | } | 465 | } |
3324 | 425 | }; | 466 | }; |
3325 | 426 | 467 | ||
3326 | 427 | 468 | ||
3327 | 428 | static MessageStack::MessagePart part_; | 469 | static MessageStack::MessagePart part_; |
3328 | 429 | static const google::protobuf::Message* root_message_; | 470 | static const google::protobuf::Message* root_message_; |
3329 | 471 | static const google::protobuf::Descriptor* root_descriptor_; | ||
3330 | 430 | 472 | ||
3331 | 431 | std::string name_; | 473 | std::string name_; |
3332 | 432 | google::protobuf::FieldDescriptor::Type field_type_; | 474 | google::protobuf::FieldDescriptor::Type field_type_; |
3333 | 433 | 475 | ||
3334 | === added file 'src/field_codec_id.cpp' | |||
3335 | --- src/field_codec_id.cpp 1970-01-01 00:00:00 +0000 | |||
3336 | +++ src/field_codec_id.cpp 2014-08-27 16:27:22 +0000 | |||
3337 | @@ -0,0 +1,100 @@ | |||
3338 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
3339 | 2 | // Massachusetts Institute of Technology (2007-) | ||
3340 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
3341 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
3342 | 5 | // | ||
3343 | 6 | // | ||
3344 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
3345 | 8 | // ("DCCL"). | ||
3346 | 9 | // | ||
3347 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
3348 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
3349 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
3350 | 13 | // (at your option) any later version. | ||
3351 | 14 | // | ||
3352 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
3353 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3354 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3355 | 18 | // GNU Lesser General Public License for more details. | ||
3356 | 19 | // | ||
3357 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
3358 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
3359 | 22 | |||
3360 | 23 | #include "field_codec_id.h" | ||
3361 | 24 | |||
3362 | 25 | // | ||
3363 | 26 | // DefaultIdentifierCodec | ||
3364 | 27 | // | ||
3365 | 28 | |||
3366 | 29 | dccl::Bitset dccl::DefaultIdentifierCodec::encode() | ||
3367 | 30 | { | ||
3368 | 31 | return encode(0); | ||
3369 | 32 | } | ||
3370 | 33 | |||
3371 | 34 | dccl::Bitset dccl::DefaultIdentifierCodec::encode(const uint32& id) | ||
3372 | 35 | { | ||
3373 | 36 | if(id <= ONE_BYTE_MAX_ID) | ||
3374 | 37 | { | ||
3375 | 38 | return(dccl::Bitset(this_size(id), id) << 1); | ||
3376 | 39 | } | ||
3377 | 40 | else | ||
3378 | 41 | { | ||
3379 | 42 | dccl::Bitset return_bits(this_size(id), id); | ||
3380 | 43 | return_bits <<= 1; | ||
3381 | 44 | // set LSB to indicate long header form | ||
3382 | 45 | return_bits.set(0, true); | ||
3383 | 46 | |||
3384 | 47 | |||
3385 | 48 | return return_bits; | ||
3386 | 49 | } | ||
3387 | 50 | } | ||
3388 | 51 | |||
3389 | 52 | dccl::uint32 dccl::DefaultIdentifierCodec::decode(Bitset* bits) | ||
3390 | 53 | { | ||
3391 | 54 | if(bits->test(0)) | ||
3392 | 55 | { | ||
3393 | 56 | // long header | ||
3394 | 57 | // grabs more bits to add to the MSB of `bits` | ||
3395 | 58 | bits->get_more_bits((LONG_FORM_ID_BYTES - SHORT_FORM_ID_BYTES)*BITS_IN_BYTE); | ||
3396 | 59 | // discard identifier | ||
3397 | 60 | *(bits) >>= 1; | ||
3398 | 61 | return bits->to_ulong(); | ||
3399 | 62 | } | ||
3400 | 63 | else | ||
3401 | 64 | { | ||
3402 | 65 | // short header | ||
3403 | 66 | *(bits) >>= 1; | ||
3404 | 67 | return bits->to_ulong(); | ||
3405 | 68 | } | ||
3406 | 69 | } | ||
3407 | 70 | |||
3408 | 71 | unsigned dccl::DefaultIdentifierCodec::size() | ||
3409 | 72 | { | ||
3410 | 73 | return this_size(0); | ||
3411 | 74 | } | ||
3412 | 75 | |||
3413 | 76 | unsigned dccl::DefaultIdentifierCodec::size(const uint32& id) | ||
3414 | 77 | { | ||
3415 | 78 | return this_size(id); | ||
3416 | 79 | } | ||
3417 | 80 | |||
3418 | 81 | unsigned dccl::DefaultIdentifierCodec::this_size(const uint32& id) | ||
3419 | 82 | { | ||
3420 | 83 | if(id > TWO_BYTE_MAX_ID) | ||
3421 | 84 | throw(Exception("dccl.id provided (" + boost::lexical_cast<std::string>(id) + ") exceeds maximum: " + boost::lexical_cast<std::string>(int(TWO_BYTE_MAX_ID)))); | ||
3422 | 85 | |||
3423 | 86 | return (id <= ONE_BYTE_MAX_ID) ? | ||
3424 | 87 | SHORT_FORM_ID_BYTES*BITS_IN_BYTE : | ||
3425 | 88 | LONG_FORM_ID_BYTES*BITS_IN_BYTE; | ||
3426 | 89 | } | ||
3427 | 90 | |||
3428 | 91 | |||
3429 | 92 | unsigned dccl::DefaultIdentifierCodec::max_size() | ||
3430 | 93 | { | ||
3431 | 94 | return LONG_FORM_ID_BYTES * BITS_IN_BYTE; | ||
3432 | 95 | } | ||
3433 | 96 | |||
3434 | 97 | unsigned dccl::DefaultIdentifierCodec::min_size() | ||
3435 | 98 | { | ||
3436 | 99 | return SHORT_FORM_ID_BYTES * BITS_IN_BYTE; | ||
3437 | 100 | } | ||
3438 | 0 | 101 | ||
3439 | === added file 'src/field_codec_id.h' | |||
3440 | --- src/field_codec_id.h 1970-01-01 00:00:00 +0000 | |||
3441 | +++ src/field_codec_id.h 2014-08-27 16:27:22 +0000 | |||
3442 | @@ -0,0 +1,50 @@ | |||
3443 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
3444 | 2 | // Massachusetts Institute of Technology (2007-) | ||
3445 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
3446 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
3447 | 5 | // | ||
3448 | 6 | // | ||
3449 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
3450 | 8 | // ("DCCL"). | ||
3451 | 9 | // | ||
3452 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
3453 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
3454 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
3455 | 13 | // (at your option) any later version. | ||
3456 | 14 | // | ||
3457 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
3458 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3459 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3460 | 18 | // GNU Lesser General Public License for more details. | ||
3461 | 19 | // | ||
3462 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
3463 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
3464 | 22 | |||
3465 | 23 | #include "field_codec_fixed.h" | ||
3466 | 24 | |||
3467 | 25 | namespace dccl | ||
3468 | 26 | { | ||
3469 | 27 | /// \brief Provides the default 1 byte or 2 byte DCCL ID codec | ||
3470 | 28 | class DefaultIdentifierCodec : public TypedFieldCodec<uint32> | ||
3471 | 29 | { | ||
3472 | 30 | protected: | ||
3473 | 31 | virtual Bitset encode(); | ||
3474 | 32 | virtual Bitset encode(const uint32& wire_value); | ||
3475 | 33 | virtual uint32 decode(Bitset* bits); | ||
3476 | 34 | virtual unsigned size(); | ||
3477 | 35 | virtual unsigned size(const uint32& wire_value); | ||
3478 | 36 | virtual unsigned max_size(); | ||
3479 | 37 | virtual unsigned min_size(); | ||
3480 | 38 | virtual void validate() { } | ||
3481 | 39 | |||
3482 | 40 | private: | ||
3483 | 41 | unsigned this_size(const uint32& wire_value); | ||
3484 | 42 | // maximum id we can fit in short or long header (MSB reserved to indicate | ||
3485 | 43 | // short or long header) | ||
3486 | 44 | enum { ONE_BYTE_MAX_ID = (1 << 7) - 1, | ||
3487 | 45 | TWO_BYTE_MAX_ID = (1 << 15) - 1}; | ||
3488 | 46 | |||
3489 | 47 | enum { SHORT_FORM_ID_BYTES = 1, | ||
3490 | 48 | LONG_FORM_ID_BYTES = 2 }; | ||
3491 | 49 | }; | ||
3492 | 50 | } | ||
3493 | 0 | 51 | ||
3494 | === modified file 'src/field_codec_manager.h' | |||
3495 | --- src/field_codec_manager.h 2014-04-22 20:10:37 +0000 | |||
3496 | +++ src/field_codec_manager.h 2014-08-27 16:27:22 +0000 | |||
3497 | @@ -81,12 +81,49 @@ | |||
3498 | 81 | template<class Codec, google::protobuf::FieldDescriptor::Type type> | 81 | template<class Codec, google::protobuf::FieldDescriptor::Type type> |
3499 | 82 | static void add(const std::string& name); | 82 | static void add(const std::string& name); |
3500 | 83 | 83 | ||
3501 | 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). | ||
3502 | 85 | /// | ||
3503 | 86 | /// \tparam Codec A child of FieldCodecBase | ||
3504 | 87 | /// \param name Name to use for this codec. Corresponds to (dccl.field).codec="name" in .proto file. | ||
3505 | 88 | /// \return nothing (void). Return templates are used for template metaprogramming selection of the proper remove() overload. | ||
3506 | 89 | template<class Codec> | ||
3507 | 90 | typename boost::enable_if< | ||
3508 | 91 | boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>, | ||
3509 | 92 | boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> > | ||
3510 | 93 | >, | ||
3511 | 94 | void>::type | ||
3512 | 95 | static remove(const std::string& name, dummy_fcm<0> dummy_fcm = 0); | ||
3513 | 96 | |||
3514 | 97 | /// \brief Remove a new field codec (used for codecs operating on all types except statically generated Protobuf messages). | ||
3515 | 98 | /// | ||
3516 | 99 | /// \tparam Codec A child of FieldCodecBase | ||
3517 | 100 | /// \param name Name to use for this codec. Corresponds to (dccl.field).codec="name" in .proto file. | ||
3518 | 101 | /// \return nothing (void). Return templates are used for template metaprogramming selection of the proper remove() overload. | ||
3519 | 102 | template<class Codec> | ||
3520 | 103 | typename boost::disable_if< | ||
3521 | 104 | boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>, | ||
3522 | 105 | boost::mpl::not_<boost::is_same<google::protobuf::Message,typename Codec::wire_type> > | ||
3523 | 106 | >, | ||
3524 | 107 | void>::type | ||
3525 | 108 | static remove(const std::string& name, dummy_fcm<1> dummy_fcm = 0); | ||
3526 | 109 | |||
3527 | 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`) | ||
3528 | 111 | /// | ||
3529 | 112 | /// \tparam Codec A child of FieldCodecBase | ||
3530 | 113 | /// \tparam type The google::protobuf::FieldDescriptor::Type enumeration that this codec works on. | ||
3531 | 114 | /// \param name Name to use for this codec. Corresponds to (dccl.field).codec="name" in .proto file. | ||
3532 | 115 | template<class Codec, google::protobuf::FieldDescriptor::Type type> | ||
3533 | 116 | static void remove(const std::string& name); | ||
3534 | 117 | |||
3535 | 118 | |||
3536 | 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). |
3537 | 85 | static boost::shared_ptr<FieldCodecBase> find( | 120 | static boost::shared_ptr<FieldCodecBase> find( |
3539 | 86 | const google::protobuf::FieldDescriptor* field) | 121 | const google::protobuf::FieldDescriptor* field, |
3540 | 122 | bool has_codec_group, | ||
3541 | 123 | const std::string& codec_group) | ||
3542 | 87 | { | 124 | { |
3545 | 88 | std::string name = __find_codec(field); | 125 | std::string name = __find_codec(field, has_codec_group, codec_group); |
3546 | 89 | 126 | ||
3547 | 90 | if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) | 127 | if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) |
3548 | 91 | return find(field->message_type(), name); | 128 | return find(field->message_type(), name); |
3549 | 92 | else | 129 | else |
3550 | @@ -101,9 +138,16 @@ | |||
3551 | 101 | const google::protobuf::Descriptor* desc, | 138 | const google::protobuf::Descriptor* desc, |
3552 | 102 | std::string name = "") | 139 | std::string name = "") |
3553 | 103 | { | 140 | { |
3554 | 141 | // this was called on the root message | ||
3555 | 104 | if(name.empty()) | 142 | if(name.empty()) |
3558 | 105 | name = desc->options().GetExtension(dccl::msg).codec(); | 143 | { |
3559 | 106 | 144 | // explicitly declared codec takes precedence over group | |
3560 | 145 | if(desc->options().GetExtension(dccl::msg).has_codec()) | ||
3561 | 146 | name = desc->options().GetExtension(dccl::msg).codec(); | ||
3562 | 147 | else | ||
3563 | 148 | name = FieldCodecBase::codec_group(desc); | ||
3564 | 149 | } | ||
3565 | 150 | |||
3566 | 107 | return __find(google::protobuf::FieldDescriptor::TYPE_MESSAGE, | 151 | return __find(google::protobuf::FieldDescriptor::TYPE_MESSAGE, |
3567 | 108 | name, desc->full_name()); | 152 | name, desc->full_name()); |
3568 | 109 | } | 153 | } |
3569 | @@ -115,6 +159,11 @@ | |||
3570 | 115 | return __find(type, name); | 159 | return __find(type, name); |
3571 | 116 | } | 160 | } |
3572 | 117 | 161 | ||
3573 | 162 | static void clear() | ||
3574 | 163 | { | ||
3575 | 164 | TypeHelper::reset(); | ||
3576 | 165 | codecs_.clear(); | ||
3577 | 166 | } | ||
3578 | 118 | 167 | ||
3579 | 119 | 168 | ||
3580 | 120 | private: | 169 | private: |
3581 | @@ -132,27 +181,41 @@ | |||
3582 | 132 | 181 | ||
3583 | 133 | static std::string __mangle_name(const std::string& codec_name, | 182 | static std::string __mangle_name(const std::string& codec_name, |
3584 | 134 | const std::string& type_name) | 183 | const std::string& type_name) |
3586 | 135 | { return type_name.empty() ? codec_name : codec_name + "@@" + type_name; } | 184 | { return type_name.empty() ? codec_name : codec_name + "[" + type_name + "]"; } |
3587 | 136 | 185 | ||
3588 | 137 | 186 | ||
3589 | 138 | template<typename WireType, typename FieldType, class Codec> | 187 | template<typename WireType, typename FieldType, class Codec> |
3599 | 139 | static void __add(const std::string& name); | 188 | static void add_all_types(const std::string& name); |
3600 | 140 | 189 | ||
3601 | 141 | template<class Codec> | 190 | template<class Codec> |
3602 | 142 | static void __add(const std::string& name, | 191 | static void add_single_type(const std::string& name, |
3603 | 143 | google::protobuf::FieldDescriptor::Type field_type, | 192 | google::protobuf::FieldDescriptor::Type field_type, |
3604 | 144 | google::protobuf::FieldDescriptor::CppType wire_type); | 193 | google::protobuf::FieldDescriptor::CppType wire_type); |
3605 | 145 | 194 | ||
3606 | 146 | 195 | template<typename WireType, typename FieldType, class Codec> | |
3607 | 147 | static std::string __find_codec(const google::protobuf::FieldDescriptor* field) | 196 | static void remove_all_types(const std::string& name); |
3608 | 197 | |||
3609 | 198 | template<class Codec> | ||
3610 | 199 | static void remove_single_type(const std::string& name, | ||
3611 | 200 | google::protobuf::FieldDescriptor::Type field_type, | ||
3612 | 201 | google::protobuf::FieldDescriptor::CppType wire_type); | ||
3613 | 202 | |||
3614 | 203 | |||
3615 | 204 | static std::string __find_codec(const google::protobuf::FieldDescriptor* field, | ||
3616 | 205 | bool has_codec_group, const std::string& codec_group) | ||
3617 | 148 | { | 206 | { |
3618 | 149 | dccl::DCCLFieldOptions dccl_field_options = field->options().GetExtension(dccl::field); | 207 | dccl::DCCLFieldOptions dccl_field_options = field->options().GetExtension(dccl::field); |
3619 | 150 | 208 | ||
3620 | 151 | // prefer the codec listed as a field extension | 209 | // prefer the codec listed as a field extension |
3621 | 152 | if(dccl_field_options.has_codec()) | 210 | if(dccl_field_options.has_codec()) |
3624 | 153 | return dccl_field_options.codec(); | 211 | return dccl_field_options.codec(); |
3625 | 154 | else if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) | 212 | // then, the codec embedded in the message option extension |
3626 | 213 | else if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE && field->message_type()->options().GetExtension(dccl::msg).has_codec()) | ||
3627 | 155 | return field->message_type()->options().GetExtension(dccl::msg).codec(); | 214 | return field->message_type()->options().GetExtension(dccl::msg).codec(); |
3628 | 215 | // then the overarching codec group | ||
3629 | 216 | else if(has_codec_group) | ||
3630 | 217 | return codec_group; | ||
3631 | 218 | // finally the default | ||
3632 | 156 | else | 219 | else |
3633 | 157 | return dccl_field_options.codec(); | 220 | return dccl_field_options.codec(); |
3634 | 158 | } | 221 | } |
3635 | @@ -173,9 +236,9 @@ | |||
3636 | 173 | dccl::FieldCodecManager::add(const std::string& name, dummy_fcm<0> dummy_fcm) | 236 | dccl::FieldCodecManager::add(const std::string& name, dummy_fcm<0> dummy_fcm) |
3637 | 174 | { | 237 | { |
3638 | 175 | TypeHelper::add<typename Codec::wire_type>(); | 238 | TypeHelper::add<typename Codec::wire_type>(); |
3642 | 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()), |
3643 | 177 | google::protobuf::FieldDescriptor::TYPE_MESSAGE, | 240 | google::protobuf::FieldDescriptor::TYPE_MESSAGE, |
3644 | 178 | google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE); | 241 | google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE); |
3645 | 179 | } | 242 | } |
3646 | 180 | 243 | ||
3647 | 181 | template<class Codec> | 244 | template<class Codec> |
3648 | @@ -187,18 +250,18 @@ | |||
3649 | 187 | void>::type | 250 | void>::type |
3650 | 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) |
3651 | 189 | { | 252 | { |
3653 | 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); |
3654 | 191 | } | 254 | } |
3655 | 192 | 255 | ||
3656 | 193 | template<class Codec, google::protobuf::FieldDescriptor::Type type> | 256 | template<class Codec, google::protobuf::FieldDescriptor::Type type> |
3657 | 194 | void dccl::FieldCodecManager::add(const std::string& name) | 257 | void dccl::FieldCodecManager::add(const std::string& name) |
3658 | 195 | { | 258 | { |
3660 | 196 | __add<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type)); | 259 | add_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type)); |
3661 | 197 | } | 260 | } |
3662 | 198 | 261 | ||
3663 | 199 | 262 | ||
3664 | 200 | template<typename WireType, typename FieldType, class Codec> | 263 | template<typename WireType, typename FieldType, class Codec> |
3666 | 201 | void dccl::FieldCodecManager::__add(const std::string& name) | 264 | void dccl::FieldCodecManager::add_all_types(const std::string& name) |
3667 | 202 | { | 265 | { |
3668 | 203 | using google::protobuf::FieldDescriptor; | 266 | using google::protobuf::FieldDescriptor; |
3669 | 204 | const FieldDescriptor::CppType cpp_field_type = ToProtoCppType<FieldType>::as_enum(); | 267 | const FieldDescriptor::CppType cpp_field_type = ToProtoCppType<FieldType>::as_enum(); |
3670 | @@ -209,17 +272,17 @@ | |||
3671 | 209 | FieldDescriptor::Type field_type = static_cast<FieldDescriptor::Type>(i); | 272 | FieldDescriptor::Type field_type = static_cast<FieldDescriptor::Type>(i); |
3672 | 210 | if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type) | 273 | if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type) |
3673 | 211 | { | 274 | { |
3675 | 212 | __add<Codec>(name, field_type, cpp_wire_type); | 275 | add_single_type<Codec>(name, field_type, cpp_wire_type); |
3676 | 213 | } | 276 | } |
3677 | 214 | } | 277 | } |
3678 | 215 | } | 278 | } |
3679 | 216 | 279 | ||
3680 | 217 | template<class Codec> | 280 | template<class Codec> |
3684 | 218 | void dccl::FieldCodecManager::__add(const std::string& name, | 281 | void dccl::FieldCodecManager::add_single_type(const std::string& name, |
3685 | 219 | google::protobuf::FieldDescriptor::Type field_type, | 282 | google::protobuf::FieldDescriptor::Type field_type, |
3686 | 220 | google::protobuf::FieldDescriptor::CppType wire_type) | 283 | google::protobuf::FieldDescriptor::CppType wire_type) |
3687 | 221 | { | 284 | { |
3689 | 222 | using google::protobuf::FieldDescriptor; | 285 | using google::protobuf::FieldDescriptor; |
3690 | 223 | if(!codecs_[field_type].count(name)) | 286 | if(!codecs_[field_type].count(name)) |
3691 | 224 | { | 287 | { |
3692 | 225 | boost::shared_ptr<FieldCodecBase> new_field_codec(new Codec()); | 288 | boost::shared_ptr<FieldCodecBase> new_field_codec(new Codec()); |
3693 | @@ -246,4 +309,82 @@ | |||
3694 | 246 | 309 | ||
3695 | 247 | 310 | ||
3696 | 248 | 311 | ||
3697 | 312 | template<class Codec> | ||
3698 | 313 | typename boost::enable_if< | ||
3699 | 314 | boost::mpl::and_< | ||
3700 | 315 | boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>, | ||
3701 | 316 | boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> > | ||
3702 | 317 | >, | ||
3703 | 318 | void>::type | ||
3704 | 319 | dccl::FieldCodecManager::remove(const std::string& name, dummy_fcm<0> dummy_fcm) | ||
3705 | 320 | { | ||
3706 | 321 | TypeHelper::remove<typename Codec::wire_type>(); | ||
3707 | 322 | remove_single_type<Codec>(__mangle_name(name, Codec::wire_type::descriptor()->full_name()), | ||
3708 | 323 | google::protobuf::FieldDescriptor::TYPE_MESSAGE, | ||
3709 | 324 | google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE); | ||
3710 | 325 | } | ||
3711 | 326 | |||
3712 | 327 | template<class Codec> | ||
3713 | 328 | typename boost::disable_if< | ||
3714 | 329 | boost::mpl::and_< | ||
3715 | 330 | boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>, | ||
3716 | 331 | boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> > | ||
3717 | 332 | >, | ||
3718 | 333 | void>::type | ||
3719 | 334 | dccl::FieldCodecManager::remove(const std::string& name, dummy_fcm<1> dummy_fcm) | ||
3720 | 335 | { | ||
3721 | 336 | remove_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name); | ||
3722 | 337 | } | ||
3723 | 338 | |||
3724 | 339 | template<class Codec, google::protobuf::FieldDescriptor::Type type> | ||
3725 | 340 | void dccl::FieldCodecManager::remove(const std::string& name) | ||
3726 | 341 | { | ||
3727 | 342 | remove_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type)); | ||
3728 | 343 | } | ||
3729 | 344 | |||
3730 | 345 | |||
3731 | 346 | template<typename WireType, typename FieldType, class Codec> | ||
3732 | 347 | void dccl::FieldCodecManager::remove_all_types(const std::string& name) | ||
3733 | 348 | { | ||
3734 | 349 | using google::protobuf::FieldDescriptor; | ||
3735 | 350 | const FieldDescriptor::CppType cpp_field_type = ToProtoCppType<FieldType>::as_enum(); | ||
3736 | 351 | const FieldDescriptor::CppType cpp_wire_type = ToProtoCppType<WireType>::as_enum(); | ||
3737 | 352 | |||
3738 | 353 | for(int i = 1, n = FieldDescriptor::MAX_TYPE; i <= n; ++i) | ||
3739 | 354 | { | ||
3740 | 355 | FieldDescriptor::Type field_type = static_cast<FieldDescriptor::Type>(i); | ||
3741 | 356 | if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type) | ||
3742 | 357 | { | ||
3743 | 358 | remove_single_type<Codec>(name, field_type, cpp_wire_type); | ||
3744 | 359 | } | ||
3745 | 360 | } | ||
3746 | 361 | } | ||
3747 | 362 | |||
3748 | 363 | template<class Codec> | ||
3749 | 364 | void dccl::FieldCodecManager::remove_single_type(const std::string& name, | ||
3750 | 365 | google::protobuf::FieldDescriptor::Type field_type, | ||
3751 | 366 | google::protobuf::FieldDescriptor::CppType wire_type) | ||
3752 | 367 | { | ||
3753 | 368 | using google::protobuf::FieldDescriptor; | ||
3754 | 369 | if(codecs_[field_type].count(name)) | ||
3755 | 370 | { | ||
3756 | 371 | dccl::dlog.is(dccl::logger::DEBUG1) && dccl::dlog << "Removing codec " << *codecs_[field_type][name] << std::endl; | ||
3757 | 372 | codecs_[field_type].erase(name); | ||
3758 | 373 | } | ||
3759 | 374 | else | ||
3760 | 375 | { | ||
3761 | 376 | boost::shared_ptr<FieldCodecBase> new_field_codec(new Codec()); | ||
3762 | 377 | new_field_codec->set_name(name); | ||
3763 | 378 | new_field_codec->set_field_type(field_type); | ||
3764 | 379 | new_field_codec->set_wire_type(wire_type); | ||
3765 | 380 | |||
3766 | 381 | dccl::dlog.is(dccl::logger::DEBUG1) && dccl::dlog << "Trying to remove: " << *new_field_codec | ||
3767 | 382 | << ", but no such codec exists" | ||
3768 | 383 | << std::endl; | ||
3769 | 384 | } | ||
3770 | 385 | } | ||
3771 | 386 | |||
3772 | 387 | |||
3773 | 388 | |||
3774 | 389 | |||
3775 | 249 | #endif | 390 | #endif |
3776 | 250 | 391 | ||
3777 | === modified file 'src/field_codec_message_stack.cpp' | |||
3778 | --- src/field_codec_message_stack.cpp 2014-04-22 20:10:37 +0000 | |||
3779 | +++ src/field_codec_message_stack.cpp 2014-08-27 16:27:22 +0000 | |||
3780 | @@ -26,7 +26,7 @@ | |||
3781 | 26 | 26 | ||
3782 | 27 | std::vector<const google::protobuf::FieldDescriptor*> dccl::MessageStack::field_; | 27 | std::vector<const google::protobuf::FieldDescriptor*> dccl::MessageStack::field_; |
3783 | 28 | std::vector<const google::protobuf::Descriptor*> dccl::MessageStack::desc_; | 28 | std::vector<const google::protobuf::Descriptor*> dccl::MessageStack::desc_; |
3785 | 29 | dccl::MessageStack::MessagePart dccl::MessageStack::current_part_ = dccl::MessageStack::UNKNOWN; | 29 | std::vector<dccl::MessageStack::MessagePart> dccl::MessageStack::parts_; |
3786 | 30 | 30 | ||
3787 | 31 | // | 31 | // |
3788 | 32 | // MessageStack | 32 | // MessageStack |
3789 | @@ -45,6 +45,12 @@ | |||
3790 | 45 | ++fields_pushed_; | 45 | ++fields_pushed_; |
3791 | 46 | } | 46 | } |
3792 | 47 | 47 | ||
3793 | 48 | void dccl::MessageStack::push(MessagePart part) | ||
3794 | 49 | { | ||
3795 | 50 | parts_.push_back(part); | ||
3796 | 51 | ++parts_pushed_; | ||
3797 | 52 | } | ||
3798 | 53 | |||
3799 | 48 | 54 | ||
3800 | 49 | void dccl::MessageStack::__pop_desc() | 55 | void dccl::MessageStack::__pop_desc() |
3801 | 50 | { | 56 | { |
3802 | @@ -58,17 +64,34 @@ | |||
3803 | 58 | field_.pop_back(); | 64 | field_.pop_back(); |
3804 | 59 | } | 65 | } |
3805 | 60 | 66 | ||
3806 | 67 | void dccl::MessageStack::__pop_parts() | ||
3807 | 68 | { | ||
3808 | 69 | if(!parts_.empty()) | ||
3809 | 70 | parts_.pop_back(); | ||
3810 | 71 | } | ||
3811 | 72 | |||
3812 | 73 | |||
3813 | 61 | dccl::MessageStack::MessageStack(const google::protobuf::FieldDescriptor* field) | 74 | dccl::MessageStack::MessageStack(const google::protobuf::FieldDescriptor* field) |
3814 | 62 | : descriptors_pushed_(0), | 75 | : descriptors_pushed_(0), |
3816 | 63 | fields_pushed_(0) | 76 | fields_pushed_(0), |
3817 | 77 | parts_pushed_(0) | ||
3818 | 64 | { | 78 | { |
3819 | 65 | if(field) | 79 | if(field) |
3820 | 66 | { | 80 | { |
3821 | 67 | if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) | 81 | if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) |
3822 | 68 | { | 82 | { |
3824 | 69 | // if explicitly set, set part (HEAD or BODY) of message for all children of this message | 83 | MessagePart part = UNKNOWN; |
3825 | 70 | if(field->options().GetExtension(dccl::field).has_in_head()) | 84 | if(field->options().GetExtension(dccl::field).has_in_head()) |
3827 | 71 | current_part_ = field->options().GetExtension(dccl::field).in_head() ? HEAD : BODY; | 85 | { |
3828 | 86 | // if explicitly set, set part (HEAD or BODY) of message for all children of this message | ||
3829 | 87 | part = field->options().GetExtension(dccl::field).in_head() ? HEAD : BODY; | ||
3830 | 88 | } | ||
3831 | 89 | else | ||
3832 | 90 | { | ||
3833 | 91 | // use the parent's current part | ||
3834 | 92 | part = current_part(); | ||
3835 | 93 | } | ||
3836 | 94 | push(part); | ||
3837 | 72 | 95 | ||
3838 | 73 | push(field->message_type()); | 96 | push(field->message_type()); |
3839 | 74 | } | 97 | } |
3840 | @@ -77,3 +100,14 @@ | |||
3841 | 77 | 100 | ||
3842 | 78 | } | 101 | } |
3843 | 79 | 102 | ||
3844 | 103 | dccl::MessageStack::~MessageStack() | ||
3845 | 104 | { | ||
3846 | 105 | for(int i = 0; i < fields_pushed_; ++i) | ||
3847 | 106 | __pop_field(); | ||
3848 | 107 | |||
3849 | 108 | for(int i = 0; i < descriptors_pushed_; ++i) | ||
3850 | 109 | __pop_desc(); | ||
3851 | 110 | |||
3852 | 111 | for(int i = 0; i < parts_pushed_; ++i) | ||
3853 | 112 | __pop_parts(); | ||
3854 | 113 | } | ||
3855 | 80 | 114 | ||
3856 | === modified file 'src/field_codec_message_stack.h' | |||
3857 | --- src/field_codec_message_stack.h 2014-04-22 20:10:37 +0000 | |||
3858 | +++ src/field_codec_message_stack.h 2014-08-27 16:27:22 +0000 | |||
3859 | @@ -34,19 +34,7 @@ | |||
3860 | 34 | public: | 34 | public: |
3861 | 35 | MessageStack(const google::protobuf::FieldDescriptor* field = 0); | 35 | MessageStack(const google::protobuf::FieldDescriptor* field = 0); |
3862 | 36 | 36 | ||
3876 | 37 | ~MessageStack() | 37 | ~MessageStack(); |
3864 | 38 | { | ||
3865 | 39 | for(int i = 0; i < descriptors_pushed_; ++i) | ||
3866 | 40 | __pop_desc(); | ||
3867 | 41 | |||
3868 | 42 | for(int i = 0; i < fields_pushed_; ++i) | ||
3869 | 43 | __pop_field(); | ||
3870 | 44 | |||
3871 | 45 | if(desc_.empty()) | ||
3872 | 46 | { | ||
3873 | 47 | current_part_ = UNKNOWN; | ||
3874 | 48 | } | ||
3875 | 49 | } | ||
3877 | 50 | 38 | ||
3878 | 51 | enum MessagePart { HEAD, BODY, UNKNOWN }; | 39 | enum MessagePart { HEAD, BODY, UNKNOWN }; |
3879 | 52 | 40 | ||
3880 | @@ -57,19 +45,22 @@ | |||
3881 | 57 | 45 | ||
3882 | 58 | void push(const google::protobuf::Descriptor* desc); | 46 | void push(const google::protobuf::Descriptor* desc); |
3883 | 59 | void push(const google::protobuf::FieldDescriptor* field); | 47 | void push(const google::protobuf::FieldDescriptor* field); |
3884 | 48 | void push(MessagePart part); | ||
3885 | 60 | 49 | ||
3888 | 61 | static MessagePart current_part() { return current_part_; } | 50 | static MessagePart current_part() { return parts_.empty() ? UNKNOWN : parts_.back(); } |
3889 | 62 | 51 | ||
3890 | 63 | friend class FieldCodecBase; | 52 | friend class FieldCodecBase; |
3891 | 64 | private: | 53 | private: |
3892 | 65 | void __pop_desc(); | 54 | void __pop_desc(); |
3893 | 66 | void __pop_field(); | 55 | void __pop_field(); |
3894 | 56 | void __pop_parts(); | ||
3895 | 67 | 57 | ||
3896 | 68 | static std::vector<const google::protobuf::Descriptor*> desc_; | 58 | static std::vector<const google::protobuf::Descriptor*> desc_; |
3897 | 69 | static std::vector<const google::protobuf::FieldDescriptor*> field_; | 59 | static std::vector<const google::protobuf::FieldDescriptor*> field_; |
3898 | 60 | static std::vector<MessagePart> parts_; | ||
3899 | 70 | int descriptors_pushed_; | 61 | int descriptors_pushed_; |
3900 | 71 | int fields_pushed_; | 62 | int fields_pushed_; |
3902 | 72 | static MessagePart current_part_; | 63 | int parts_pushed_; |
3903 | 73 | }; | 64 | }; |
3904 | 74 | } | 65 | } |
3905 | 75 | 66 | ||
3906 | 76 | 67 | ||
3907 | === modified file 'src/field_codec_typed.h' | |||
3908 | --- src/field_codec_typed.h 2014-04-22 20:10:37 +0000 | |||
3909 | +++ src/field_codec_typed.h 2014-08-27 16:27:22 +0000 | |||
3910 | @@ -24,6 +24,9 @@ | |||
3911 | 24 | #ifndef DCCLFIELDCODECTYPED20120312H | 24 | #ifndef DCCLFIELDCODECTYPED20120312H |
3912 | 25 | #define DCCLFIELDCODECTYPED20120312H | 25 | #define DCCLFIELDCODECTYPED20120312H |
3913 | 26 | 26 | ||
3914 | 27 | |||
3915 | 28 | #include <boost/type_traits.hpp> | ||
3916 | 29 | |||
3917 | 27 | #include "field_codec.h" | 30 | #include "field_codec.h" |
3918 | 28 | 31 | ||
3919 | 29 | namespace dccl | 32 | namespace dccl |
3920 | @@ -72,7 +75,7 @@ | |||
3921 | 72 | class TypedFieldCodec : public FieldCodecSelector<WireType, FieldType> | 75 | class TypedFieldCodec : public FieldCodecSelector<WireType, FieldType> |
3922 | 73 | { | 76 | { |
3923 | 74 | public: | 77 | public: |
3925 | 75 | typedef WireType wire_type; | 78 | typedef WireType wire_type; |
3926 | 76 | typedef FieldType field_type; | 79 | typedef FieldType field_type; |
3927 | 77 | 80 | ||
3928 | 78 | public: | 81 | public: |
3929 | @@ -256,8 +259,14 @@ | |||
3930 | 256 | /// | 259 | /// |
3931 | 257 | /// \param bits Bits to use for decoding. | 260 | /// \param bits Bits to use for decoding. |
3932 | 258 | /// \return the decoded value. | 261 | /// \return the decoded value. |
3935 | 259 | virtual WireType decode(Bitset* bits) | 262 | virtual WireType decode(dccl::Bitset* bits) |
3936 | 260 | { return decode_repeated(bits).at(0); } | 263 | { |
3937 | 264 | std::vector<WireType> return_vec = decode_repeated(bits); | ||
3938 | 265 | if(return_vec.empty()) | ||
3939 | 266 | throw dccl::NullValueException(); | ||
3940 | 267 | else | ||
3941 | 268 | return return_vec.at(0); | ||
3942 | 269 | } | ||
3943 | 261 | 270 | ||
3944 | 262 | /// \brief Calculate the size (in bits) of an empty field. | 271 | /// \brief Calculate the size (in bits) of an empty field. |
3945 | 263 | /// | 272 | /// |
3946 | 264 | 273 | ||
3947 | === modified file 'src/logger.cpp' | |||
3948 | --- src/logger.cpp 2014-04-22 20:10:37 +0000 | |||
3949 | +++ src/logger.cpp 2014-08-27 16:27:22 +0000 | |||
3950 | @@ -55,6 +55,7 @@ | |||
3951 | 55 | case logger::GENERAL: break; | 55 | case logger::GENERAL: break; |
3952 | 56 | case logger::ENCODE: grp_str = "{encode}: "; break; | 56 | case logger::ENCODE: grp_str = "{encode}: "; break; |
3953 | 57 | case logger::DECODE: grp_str = "{decode}: "; break; | 57 | case logger::DECODE: grp_str = "{decode}: "; break; |
3954 | 58 | case logger::SIZE: grp_str = "{size}: "; break; | ||
3955 | 58 | } | 59 | } |
3956 | 59 | 60 | ||
3957 | 60 | std::time_t now = std::time(0); | 61 | std::time_t now = std::time(0); |
3958 | @@ -64,11 +65,12 @@ | |||
3959 | 64 | { | 65 | { |
3960 | 65 | *os << "[ " << (t->tm_year+1900) << "-" | 66 | *os << "[ " << (t->tm_year+1900) << "-" |
3961 | 66 | << std::setw(2) << std::setfill('0') << (t->tm_mon+1) << "-" | 67 | << std::setw(2) << std::setfill('0') << (t->tm_mon+1) << "-" |
3963 | 67 | << std::setw(2) << std::setfill('0') << t->tm_mday | 68 | << std::setw(2) << t->tm_mday |
3964 | 68 | << " " | 69 | << " " |
3968 | 69 | << std::setw(2) << std::setfill('0') << t->tm_hour << ":" | 70 | << std::setw(2) << t->tm_hour << ":" |
3969 | 70 | << std::setw(2) << std::setfill('0') << t->tm_min << ":" | 71 | << std::setw(2) << t->tm_min << ":" |
3970 | 71 | << std::setw(2) << std::setfill('0') << t->tm_sec << " ]: "; | 72 | << std::setw(2) << t->tm_sec << " ]: " |
3971 | 73 | << std::setfill(' '); | ||
3972 | 72 | } | 74 | } |
3973 | 73 | 75 | ||
3974 | 74 | *os << grp_str << msg << std::endl; | 76 | *os << grp_str << msg << std::endl; |
3975 | 75 | 77 | ||
3976 | === modified file 'src/logger.h' | |||
3977 | --- src/logger.h 2014-04-22 20:10:37 +0000 | |||
3978 | +++ src/logger.h 2014-08-27 16:27:22 +0000 | |||
3979 | @@ -47,10 +47,11 @@ | |||
3980 | 47 | DEBUG3_PLUS = DEBUG3 | (DEBUG3 - 1) | 47 | DEBUG3_PLUS = DEBUG3 | (DEBUG3 - 1) |
3981 | 48 | }; | 48 | }; |
3982 | 49 | enum Group | 49 | enum Group |
3984 | 50 | { GENERAL, ENCODE, DECODE }; | 50 | { GENERAL, ENCODE, DECODE, SIZE }; |
3985 | 51 | 51 | ||
3986 | 52 | } | 52 | } |
3987 | 53 | 53 | ||
3988 | 54 | |||
3989 | 54 | 55 | ||
3990 | 55 | void to_ostream(const std::string& msg, dccl::logger::Verbosity vrb, | 56 | void to_ostream(const std::string& msg, dccl::logger::Verbosity vrb, |
3991 | 56 | dccl::logger::Group grp, std::ostream* os, bool add_timestamp); | 57 | dccl::logger::Group grp, std::ostream* os, bool add_timestamp); |
3992 | 57 | 58 | ||
3993 | === modified file 'src/protobuf/option_extensions.proto' | |||
3994 | --- src/protobuf/option_extensions.proto 2013-08-20 16:17:28 +0000 | |||
3995 | +++ src/protobuf/option_extensions.proto 2014-08-27 16:27:22 +0000 | |||
3996 | @@ -25,7 +25,7 @@ | |||
3997 | 25 | message DCCLFieldOptions | 25 | message DCCLFieldOptions |
3998 | 26 | { | 26 | { |
3999 | 27 | // what encoder / decoder should we use? | 27 | // what encoder / decoder should we use? |
4001 | 28 | optional string codec = 1 [default = "dccl.default"]; | 28 | optional string codec = 1 [default = "dccl.default2"]; |
4002 | 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) |
4003 | 30 | optional bool omit = 2 [default = false]; | 30 | optional bool omit = 2 [default = false]; |
4004 | 31 | // set true for fields in the header (will *not* be encrypte)d | 31 | // set true for fields in the header (will *not* be encrypte)d |
4005 | @@ -60,9 +60,12 @@ | |||
4006 | 60 | 60 | ||
4007 | 61 | message DCCLMessageOptions | 61 | message DCCLMessageOptions |
4008 | 62 | { | 62 | { |
4013 | 63 | required int32 id = 1; | 63 | optional int32 id = 1; |
4014 | 64 | required uint32 max_bytes = 2; | 64 | optional uint32 max_bytes = 2; |
4015 | 65 | 65 | ||
4016 | 66 | optional string codec = 3 [default = "dccl.default"]; | 66 | optional string codec = 3 [default = "dccl.default2"]; |
4017 | 67 | |||
4018 | 68 | optional string codec_group = 4 [default = "dccl.default2"]; | ||
4019 | 69 | optional int32 codec_version = 5 [default = 2]; | ||
4020 | 67 | } | 70 | } |
4021 | 68 | 71 | ||
4022 | 69 | 72 | ||
4023 | === modified file 'src/test/CMakeLists.txt' | |||
4024 | --- src/test/CMakeLists.txt 2014-03-26 16:25:12 +0000 | |||
4025 | +++ src/test/CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
4026 | @@ -10,6 +10,8 @@ | |||
4027 | 10 | add_subdirectory(dccl_static_methods) | 10 | add_subdirectory(dccl_static_methods) |
4028 | 11 | add_subdirectory(dccl_custom_id) | 11 | add_subdirectory(dccl_custom_id) |
4029 | 12 | add_subdirectory(dccl_numeric_bounds) | 12 | add_subdirectory(dccl_numeric_bounds) |
4030 | 13 | add_subdirectory(dccl_codec_group) | ||
4031 | 14 | add_subdirectory(dccl_message_fix) | ||
4032 | 13 | 15 | ||
4033 | 14 | if(build_ccl) | 16 | if(build_ccl) |
4034 | 15 | add_subdirectory(dccl_ccl) | 17 | add_subdirectory(dccl_ccl) |
4035 | @@ -19,6 +21,9 @@ | |||
4036 | 19 | add_subdirectory(dccl_arithmetic) | 21 | add_subdirectory(dccl_arithmetic) |
4037 | 20 | endif() | 22 | endif() |
4038 | 21 | 23 | ||
4039 | 24 | add_subdirectory(dccl_v2_all_fields) | ||
4040 | 25 | add_subdirectory(dccl_v2_header) | ||
4041 | 26 | |||
4042 | 22 | add_subdirectory(bitset1) | 27 | add_subdirectory(bitset1) |
4043 | 23 | 28 | ||
4044 | 24 | add_subdirectory(logger1) | 29 | add_subdirectory(logger1) |
4045 | 25 | 30 | ||
4046 | === modified file 'src/test/dccl_all_fields/test.cpp' | |||
4047 | --- src/test/dccl_all_fields/test.cpp 2014-04-22 20:13:39 +0000 | |||
4048 | +++ src/test/dccl_all_fields/test.cpp 2014-08-27 16:27:22 +0000 | |||
4049 | @@ -136,7 +136,9 @@ | |||
4050 | 136 | decode_check(bytes); | 136 | decode_check(bytes); |
4051 | 137 | 137 | ||
4052 | 138 | // make sure DCCL defaults stay wire compatible | 138 | // make sure DCCL defaults stay wire compatible |
4054 | 139 | decode_check(dccl::hex_decode("047f277b9628060000b95660c0b0188000d8c0132858800008000dc2c4c6626466024488cca8ee324bd05c3f23af0000ad9112a09509788013e0820b18e0005ed0204c6c2c4666062042644675975982c65235f10a00ad718a5801000000905f27121600000000a0170050640300309201001a0b00007d320a0000a61a0070b20100a81b00d09c6f0000a0401026361643102636160300f0dfbd5b2280ea2e330f3da59a2100aabfa55a000000000000000000000000")); | 139 | |
4055 | 140 | // v3 | ||
4056 | 141 | decode_check(dccl::hex_decode("047f277b16b95660c0b0188000d8c0132858800008002d4c6c2c4666264084c88cea2eb304cdeb67cc2b00b4464a805626e0014e800b2e60800378410b131b8b91990188109951dd6596a0b154cd7805506b9c2256caaf13094ba0978a6c248a692493c682fa6454a69a4e36a16e6ace37a918263616c330b1b118fd77ef9608a0bacbac574fa9cd1050fd6daa0500")); | ||
4057 | 140 | 142 | ||
4058 | 141 | // run a bunch of tests with random strings | 143 | // run a bunch of tests with random strings |
4059 | 142 | std::string random = bytes; | 144 | std::string random = bytes; |
4060 | 143 | 145 | ||
4061 | === modified file 'src/test/dccl_all_fields/test.proto' | |||
4062 | --- src/test/dccl_all_fields/test.proto 2012-10-19 16:41:36 +0000 | |||
4063 | +++ src/test/dccl_all_fields/test.proto 2014-08-27 16:27:22 +0000 | |||
4064 | @@ -29,6 +29,7 @@ | |||
4065 | 29 | { | 29 | { |
4066 | 30 | option (dccl.msg).id = 2; | 30 | option (dccl.msg).id = 2; |
4067 | 31 | option (dccl.msg).max_bytes = 512; | 31 | option (dccl.msg).max_bytes = 512; |
4068 | 32 | option (dccl.msg).codec_version = 3; | ||
4069 | 32 | 33 | ||
4070 | 33 | // test default enc/dec | 34 | // test default enc/dec |
4071 | 34 | optional double double_default_optional = 1 [(dccl.field).min=-100, | 35 | optional double double_default_optional = 1 [(dccl.field).min=-100, |
4072 | @@ -123,8 +124,7 @@ | |||
4073 | 123 | (dccl.field).max_repeat=4]; | 124 | (dccl.field).max_repeat=4]; |
4074 | 124 | repeated uint32 uint32_default_repeat = 105 [(dccl.field).min=0, | 125 | repeated uint32 uint32_default_repeat = 105 [(dccl.field).min=0, |
4075 | 125 | (dccl.field).max=100, | 126 | (dccl.field).max=100, |
4078 | 126 | (dccl.field).max_repeat=4, | 127 | (dccl.field).max_repeat=4]; |
4077 | 127 | (dccl.field).in_head=true]; | ||
4079 | 128 | repeated uint64 uint64_default_repeat = 106 [(dccl.field).min=0, | 128 | repeated uint64 uint64_default_repeat = 106 [(dccl.field).min=0, |
4080 | 129 | (dccl.field).max=100, | 129 | (dccl.field).max=100, |
4081 | 130 | (dccl.field).max_repeat=4]; | 130 | (dccl.field).max_repeat=4]; |
4082 | 131 | 131 | ||
4083 | === modified file 'src/test/dccl_arithmetic/test.proto' | |||
4084 | --- src/test/dccl_arithmetic/test.proto 2012-10-23 00:46:12 +0000 | |||
4085 | +++ src/test/dccl_arithmetic/test.proto 2014-08-27 16:27:22 +0000 | |||
4086 | @@ -25,7 +25,8 @@ | |||
4087 | 25 | { | 25 | { |
4088 | 26 | option (dccl.msg).id = 1; | 26 | option (dccl.msg).id = 1; |
4089 | 27 | option (dccl.msg).max_bytes = 512; | 27 | option (dccl.msg).max_bytes = 512; |
4091 | 28 | 28 | option (dccl.msg).codec_version = 3; | |
4092 | 29 | |||
4093 | 29 | repeated double value = 101 [(dccl.field).codec = "_arithmetic", | 30 | repeated double value = 101 [(dccl.field).codec = "_arithmetic", |
4094 | 30 | (dccl.field).(arithmetic).model = "model", | 31 | (dccl.field).(arithmetic).model = "model", |
4095 | 31 | (dccl.field).(arithmetic).debug_assert = true, | 32 | (dccl.field).(arithmetic).debug_assert = true, |
4096 | @@ -35,6 +36,7 @@ | |||
4097 | 35 | { | 36 | { |
4098 | 36 | option (dccl.msg).id = 2; | 37 | option (dccl.msg).id = 2; |
4099 | 37 | option (dccl.msg).max_bytes = 512; | 38 | option (dccl.msg).max_bytes = 512; |
4100 | 39 | option (dccl.msg).codec_version = 3; | ||
4101 | 38 | 40 | ||
4102 | 39 | repeated Enum1 value = 114 [(dccl.field).codec = "_arithmetic", | 41 | repeated Enum1 value = 114 [(dccl.field).codec = "_arithmetic", |
4103 | 40 | (dccl.field).(arithmetic).model = "model", | 42 | (dccl.field).(arithmetic).model = "model", |
4104 | @@ -47,6 +49,7 @@ | |||
4105 | 47 | { | 49 | { |
4106 | 48 | option (dccl.msg).id = 3; | 50 | option (dccl.msg).id = 3; |
4107 | 49 | option (dccl.msg).max_bytes = 512; | 51 | option (dccl.msg).max_bytes = 512; |
4108 | 52 | option (dccl.msg).codec_version = 3; | ||
4109 | 50 | 53 | ||
4110 | 51 | required Enum1 value = 114 [(dccl.field).codec = "_arithmetic", | 54 | required Enum1 value = 114 [(dccl.field).codec = "_arithmetic", |
4111 | 52 | (dccl.field).(arithmetic).model = "model", | 55 | (dccl.field).(arithmetic).model = "model", |
4112 | @@ -58,6 +61,7 @@ | |||
4113 | 58 | { | 61 | { |
4114 | 59 | option (dccl.msg).id = 4; | 62 | option (dccl.msg).id = 4; |
4115 | 60 | option (dccl.msg).max_bytes = 512; | 63 | option (dccl.msg).max_bytes = 512; |
4116 | 64 | option (dccl.msg).codec_version = 3; | ||
4117 | 61 | 65 | ||
4118 | 62 | repeated Enum2 value = 114 [(dccl.field).codec = "_arithmetic", | 66 | repeated Enum2 value = 114 [(dccl.field).codec = "_arithmetic", |
4119 | 63 | (dccl.field).(arithmetic).model = "model", | 67 | (dccl.field).(arithmetic).model = "model", |
4120 | @@ -70,6 +74,7 @@ | |||
4121 | 70 | { | 74 | { |
4122 | 71 | option (dccl.msg).id = 5; | 75 | option (dccl.msg).id = 5; |
4123 | 72 | option (dccl.msg).max_bytes = 10000; | 76 | option (dccl.msg).max_bytes = 10000; |
4124 | 77 | option (dccl.msg).codec_version = 3; | ||
4125 | 73 | 78 | ||
4126 | 74 | repeated int32 value = 101 [(dccl.field).codec = "_arithmetic", | 79 | repeated int32 value = 101 [(dccl.field).codec = "_arithmetic", |
4127 | 75 | (dccl.field).(arithmetic).model = "model", | 80 | (dccl.field).(arithmetic).model = "model", |
4128 | @@ -82,6 +87,7 @@ | |||
4129 | 82 | { | 87 | { |
4130 | 83 | option (dccl.msg).id = 6; | 88 | option (dccl.msg).id = 6; |
4131 | 84 | option (dccl.msg).max_bytes = 10000; | 89 | option (dccl.msg).max_bytes = 10000; |
4132 | 90 | option (dccl.msg).codec_version = 3; | ||
4133 | 85 | 91 | ||
4134 | 86 | repeated int32 value = 101 [(dccl.field).codec = "_arithmetic", | 92 | repeated int32 value = 101 [(dccl.field).codec = "_arithmetic", |
4135 | 87 | (dccl.field).(arithmetic).model = "model", | 93 | (dccl.field).(arithmetic).model = "model", |
4136 | 88 | 94 | ||
4137 | === modified file 'src/test/dccl_ccl/test.cpp' | |||
4138 | --- src/test/dccl_ccl/test.cpp 2014-04-22 20:13:39 +0000 | |||
4139 | +++ src/test/dccl_ccl/test.cpp 2014-08-27 16:27:22 +0000 | |||
4140 | @@ -48,11 +48,9 @@ | |||
4141 | 48 | { | 48 | { |
4142 | 49 | dccl::dlog.connect(dccl::logger::ALL, &std::cerr); | 49 | dccl::dlog.connect(dccl::logger::ALL, &std::cerr); |
4143 | 50 | 50 | ||
4148 | 51 | { | 51 | { |
4145 | 52 | dccl::FieldCodecManager::add<dccl::LegacyCCLIdentifierCodec>("ccl_id_codec"); | ||
4146 | 53 | dccl::Codec codec("ccl_id_codec"); | ||
4147 | 54 | |||
4149 | 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); |
4150 | 53 | dccl::Codec codec("dccl.ccl.id"); | ||
4151 | 56 | 54 | ||
4152 | 57 | if(!dl_handle) | 55 | if(!dl_handle) |
4153 | 58 | { | 56 | { |
4154 | 59 | 57 | ||
4155 | === modified file 'src/test/dccl_ccl/test.proto' | |||
4156 | --- src/test/dccl_ccl/test.proto 2012-10-24 14:10:06 +0000 | |||
4157 | +++ src/test/dccl_ccl/test.proto 2014-08-27 16:27:22 +0000 | |||
4158 | @@ -4,6 +4,7 @@ | |||
4159 | 4 | { | 4 | { |
4160 | 5 | option (dccl.msg).id = 1; | 5 | option (dccl.msg).id = 1; |
4161 | 6 | option (dccl.msg).max_bytes = 32; | 6 | option (dccl.msg).max_bytes = 32; |
4162 | 7 | option (dccl.msg).codec_version = 3; | ||
4163 | 7 | 8 | ||
4164 | 8 | required int32 a = 1 [(dccl.field).min=0, | 9 | required int32 a = 1 [(dccl.field).min=0, |
4165 | 9 | (dccl.field).max=0xFFFF]; | 10 | (dccl.field).max=0xFFFF]; |
4166 | 10 | 11 | ||
4167 | === added directory 'src/test/dccl_codec_group' | |||
4168 | === added file 'src/test/dccl_codec_group/CMakeLists.txt' | |||
4169 | --- src/test/dccl_codec_group/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
4170 | +++ src/test/dccl_codec_group/CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
4171 | @@ -0,0 +1,6 @@ | |||
4172 | 1 | protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto) | ||
4173 | 2 | |||
4174 | 3 | add_executable(dccl_test_codec_group test.cpp ${PROTO_SRCS} ${PROTO_HDRS}) | ||
4175 | 4 | target_link_libraries(dccl_test_codec_group dccl) | ||
4176 | 5 | |||
4177 | 6 | add_test(dccl_test_codec_group ${dccl_BIN_DIR}/dccl_test_codec_group) | ||
4178 | 0 | 7 | ||
4179 | === added file 'src/test/dccl_codec_group/test.cpp' | |||
4180 | --- src/test/dccl_codec_group/test.cpp 1970-01-01 00:00:00 +0000 | |||
4181 | +++ src/test/dccl_codec_group/test.cpp 2014-08-27 16:27:22 +0000 | |||
4182 | @@ -0,0 +1,104 @@ | |||
4183 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
4184 | 2 | // Massachusetts Institute of Technology (2007-) | ||
4185 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
4186 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
4187 | 5 | // | ||
4188 | 6 | // | ||
4189 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
4190 | 8 | // ("DCCL"). | ||
4191 | 9 | // | ||
4192 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
4193 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
4194 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
4195 | 13 | // (at your option) any later version. | ||
4196 | 14 | // | ||
4197 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
4198 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4199 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4200 | 18 | // GNU Lesser General Public License for more details. | ||
4201 | 19 | // | ||
4202 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
4203 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
4204 | 22 | |||
4205 | 23 | |||
4206 | 24 | // tests all protobuf types with _default codecs, repeat and non repeat | ||
4207 | 25 | |||
4208 | 26 | #include <fstream> | ||
4209 | 27 | |||
4210 | 28 | #include <google/protobuf/descriptor.pb.h> | ||
4211 | 29 | |||
4212 | 30 | #include "dccl/codec.h" | ||
4213 | 31 | #include "dccl/codecs3/field_codec_default.h" | ||
4214 | 32 | |||
4215 | 33 | #include "test.pb.h" | ||
4216 | 34 | #include "dccl/binary.h" | ||
4217 | 35 | |||
4218 | 36 | template <typename Msg> | ||
4219 | 37 | void check(double val, bool should_pass); | ||
4220 | 38 | dccl::Codec codec; | ||
4221 | 39 | TestMsg msg_in; | ||
4222 | 40 | TestMsgGroup msg_group_in; | ||
4223 | 41 | |||
4224 | 42 | class TestCodec : public dccl::v3::DefaultNumericFieldCodec<double> | ||
4225 | 43 | { | ||
4226 | 44 | double max() { return 100; } | ||
4227 | 45 | double min() { return -100; } | ||
4228 | 46 | double precision() { return 1; } | ||
4229 | 47 | void validate() { } | ||
4230 | 48 | }; | ||
4231 | 49 | |||
4232 | 50 | |||
4233 | 51 | |||
4234 | 52 | |||
4235 | 53 | int main(int argc, char* argv[]) | ||
4236 | 54 | { | ||
4237 | 55 | // dccl::dlog.connect(dccl::logger::ALL, &std::cerr); | ||
4238 | 56 | |||
4239 | 57 | dccl::FieldCodecManager::add<TestCodec>("test.grouptest"); | ||
4240 | 58 | dccl::FieldCodecManager::add<dccl::v3::DefaultMessageCodec, google::protobuf::FieldDescriptor::TYPE_MESSAGE>("test.grouptest"); | ||
4241 | 59 | |||
4242 | 60 | check<TestMsg>(50, true); | ||
4243 | 61 | check<TestMsg>(-50, false); | ||
4244 | 62 | check<TestMsgGroup>(50, true); | ||
4245 | 63 | check<TestMsgGroup>(-50, true); | ||
4246 | 64 | check<TestMsgVersion>(50, true); | ||
4247 | 65 | |||
4248 | 66 | std::cout << "all tests passed" << std::endl; | ||
4249 | 67 | } | ||
4250 | 68 | |||
4251 | 69 | |||
4252 | 70 | template <typename Msg> | ||
4253 | 71 | void check(double val, bool should_pass) | ||
4254 | 72 | { | ||
4255 | 73 | Msg msg_in; | ||
4256 | 74 | int i = 0; | ||
4257 | 75 | msg_in.set_d(++i + 0.1); | ||
4258 | 76 | msg_in.add_d_repeat(12.1); | ||
4259 | 77 | msg_in.add_d_repeat(12.2); | ||
4260 | 78 | msg_in.add_d_repeat(12.3); | ||
4261 | 79 | |||
4262 | 80 | msg_in.mutable_msg()->set_val(val); | ||
4263 | 81 | msg_in.mutable_msg()->mutable_msg()->set_val(val); | ||
4264 | 82 | codec.info(msg_in.GetDescriptor(), &std::cout); | ||
4265 | 83 | |||
4266 | 84 | std::cout << "Message in:\n" << msg_in.DebugString() << std::endl; | ||
4267 | 85 | |||
4268 | 86 | codec.load(msg_in.GetDescriptor()); | ||
4269 | 87 | |||
4270 | 88 | std::cout << "Try encode..." << std::endl; | ||
4271 | 89 | std::string bytes; | ||
4272 | 90 | codec.encode(&bytes, msg_in); | ||
4273 | 91 | std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl; | ||
4274 | 92 | |||
4275 | 93 | std::cout << "Try decode..." << std::endl; | ||
4276 | 94 | |||
4277 | 95 | Msg msg_out; | ||
4278 | 96 | codec.decode(bytes, &msg_out); | ||
4279 | 97 | |||
4280 | 98 | std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl; | ||
4281 | 99 | |||
4282 | 100 | if(should_pass) | ||
4283 | 101 | assert(msg_in.SerializeAsString() == msg_out.SerializeAsString()); | ||
4284 | 102 | else | ||
4285 | 103 | assert(msg_in.SerializeAsString() != msg_out.SerializeAsString()); | ||
4286 | 104 | } | ||
4287 | 0 | 105 | ||
4288 | === added file 'src/test/dccl_codec_group/test.proto' | |||
4289 | --- src/test/dccl_codec_group/test.proto 1970-01-01 00:00:00 +0000 | |||
4290 | +++ src/test/dccl_codec_group/test.proto 2014-08-27 16:27:22 +0000 | |||
4291 | @@ -0,0 +1,77 @@ | |||
4292 | 1 | import "dccl/protobuf/option_extensions.proto"; | ||
4293 | 2 | |||
4294 | 3 | |||
4295 | 4 | message EmbeddedMsg1 | ||
4296 | 5 | { | ||
4297 | 6 | option (dccl.msg).codec="dccl.default3"; | ||
4298 | 7 | |||
4299 | 8 | optional double val = 1 [(dccl.field).min=0, | ||
4300 | 9 | (dccl.field).max=100, | ||
4301 | 10 | (dccl.field).precision=3]; | ||
4302 | 11 | |||
4303 | 12 | |||
4304 | 13 | optional EmbeddedMsg2 msg = 2; | ||
4305 | 14 | } | ||
4306 | 15 | |||
4307 | 16 | message EmbeddedMsg2 | ||
4308 | 17 | { | ||
4309 | 18 | optional double val = 1 [(dccl.field).min=0, | ||
4310 | 19 | (dccl.field).max=100, | ||
4311 | 20 | (dccl.field).precision=2]; | ||
4312 | 21 | |||
4313 | 22 | } | ||
4314 | 23 | |||
4315 | 24 | message TestMsg | ||
4316 | 25 | { | ||
4317 | 26 | option (dccl.msg).id = 1; | ||
4318 | 27 | option (dccl.msg).max_bytes = 32; | ||
4319 | 28 | option (dccl.msg).codec_version = 3; | ||
4320 | 29 | |||
4321 | 30 | optional double d = 1 [(dccl.field).min=-100, | ||
4322 | 31 | (dccl.field).max=126, | ||
4323 | 32 | (dccl.field).precision=1, | ||
4324 | 33 | (dccl.field).codec="dccl.default3"]; | ||
4325 | 34 | |||
4326 | 35 | |||
4327 | 36 | |||
4328 | 37 | repeated double d_repeat = 3 [(dccl.field).max_repeat=5, | ||
4329 | 38 | (dccl.field).codec="test.grouptest"]; | ||
4330 | 39 | optional EmbeddedMsg1 msg = 2; | ||
4331 | 40 | } | ||
4332 | 41 | |||
4333 | 42 | message TestMsgGroup | ||
4334 | 43 | { | ||
4335 | 44 | option (dccl.msg).id = 2; | ||
4336 | 45 | option (dccl.msg).max_bytes = 32; | ||
4337 | 46 | option (dccl.msg).codec_group = "test.grouptest"; | ||
4338 | 47 | option (dccl.msg).codec_version = 3; | ||
4339 | 48 | |||
4340 | 49 | optional double d = 1 [(dccl.field).min=-100, | ||
4341 | 50 | (dccl.field).max=126, | ||
4342 | 51 | (dccl.field).precision=1, | ||
4343 | 52 | (dccl.field).codec="dccl.default3"]; | ||
4344 | 53 | |||
4345 | 54 | repeated double d_repeat = 3 [(dccl.field).max_repeat=5]; | ||
4346 | 55 | optional EmbeddedMsg1 msg = 2; | ||
4347 | 56 | |||
4348 | 57 | } | ||
4349 | 58 | |||
4350 | 59 | |||
4351 | 60 | message TestMsgVersion | ||
4352 | 61 | { | ||
4353 | 62 | option (dccl.msg).id = 3; | ||
4354 | 63 | option (dccl.msg).max_bytes = 32; | ||
4355 | 64 | option (dccl.msg).codec_version = 2; | ||
4356 | 65 | |||
4357 | 66 | optional double d = 1 [(dccl.field).min=-100, | ||
4358 | 67 | (dccl.field).max=126, | ||
4359 | 68 | (dccl.field).precision=2]; | ||
4360 | 69 | |||
4361 | 70 | repeated double d_repeat = 3 [(dccl.field).min=12.0, | ||
4362 | 71 | (dccl.field).max=13.6, | ||
4363 | 72 | (dccl.field).precision=1, | ||
4364 | 73 | (dccl.field).max_repeat=5]; | ||
4365 | 74 | |||
4366 | 75 | optional EmbeddedMsg1 msg = 2; | ||
4367 | 76 | |||
4368 | 77 | } | ||
4369 | 0 | 78 | ||
4370 | === modified file 'src/test/dccl_custom_id/test.proto' | |||
4371 | --- src/test/dccl_custom_id/test.proto 2012-10-24 14:10:06 +0000 | |||
4372 | +++ src/test/dccl_custom_id/test.proto 2014-08-27 16:27:22 +0000 | |||
4373 | @@ -4,6 +4,7 @@ | |||
4374 | 4 | { | 4 | { |
4375 | 5 | option (dccl.msg).id = 1000001; | 5 | option (dccl.msg).id = 1000001; |
4376 | 6 | option (dccl.msg).max_bytes = 2; | 6 | option (dccl.msg).max_bytes = 2; |
4377 | 7 | option (dccl.msg).codec_version = 3; | ||
4378 | 7 | 8 | ||
4379 | 8 | required uint32 user = 1 [(dccl.field).min=0, | 9 | required uint32 user = 1 [(dccl.field).min=0, |
4380 | 9 | (dccl.field).max=0x03FF, | 10 | (dccl.field).max=0x03FF, |
4381 | @@ -14,6 +15,7 @@ | |||
4382 | 14 | { | 15 | { |
4383 | 15 | option (dccl.msg).id = 1000002; | 16 | option (dccl.msg).id = 1000002; |
4384 | 16 | option (dccl.msg).max_bytes = 2; | 17 | option (dccl.msg).max_bytes = 2; |
4385 | 18 | option (dccl.msg).codec_version = 3; | ||
4386 | 17 | 19 | ||
4387 | 18 | required uint32 clock_mode = 1 [(dccl.field).min=0, | 20 | required uint32 clock_mode = 1 [(dccl.field).min=0, |
4388 | 19 | (dccl.field).max=3, | 21 | (dccl.field).max=3, |
4389 | @@ -32,6 +34,7 @@ | |||
4390 | 32 | { | 34 | { |
4391 | 33 | option (dccl.msg).id = 1000003; | 35 | option (dccl.msg).id = 1000003; |
4392 | 34 | option (dccl.msg).max_bytes = 2; | 36 | option (dccl.msg).max_bytes = 2; |
4393 | 37 | option (dccl.msg).codec_version = 3; | ||
4394 | 35 | 38 | ||
4395 | 36 | required uint32 user = 1 [(dccl.field).min=0, | 39 | required uint32 user = 1 [(dccl.field).min=0, |
4396 | 37 | (dccl.field).max=0x03FF, | 40 | (dccl.field).max=0x03FF, |
4397 | 38 | 41 | ||
4398 | === modified file 'src/test/dccl_custom_message/test.proto' | |||
4399 | --- src/test/dccl_custom_message/test.proto 2012-10-19 16:41:36 +0000 | |||
4400 | +++ src/test/dccl_custom_message/test.proto 2014-08-27 16:27:22 +0000 | |||
4401 | @@ -6,6 +6,7 @@ | |||
4402 | 6 | option (dccl.msg).id = 3; | 6 | option (dccl.msg).id = 3; |
4403 | 7 | option (dccl.msg).max_bytes = 256; | 7 | option (dccl.msg).max_bytes = 256; |
4404 | 8 | option (dccl.msg).codec = "custom_codec"; | 8 | option (dccl.msg).codec = "custom_codec"; |
4405 | 9 | option (dccl.msg).codec_version = 3; | ||
4406 | 9 | 10 | ||
4407 | 10 | optional uint32 a = 1; | 11 | optional uint32 a = 1; |
4408 | 11 | optional bool b = 2; | 12 | optional bool b = 2; |
4409 | @@ -16,6 +17,7 @@ | |||
4410 | 16 | { | 17 | { |
4411 | 17 | option (dccl.msg).id = 4; | 18 | option (dccl.msg).id = 4; |
4412 | 18 | option (dccl.msg).max_bytes = 256; | 19 | option (dccl.msg).max_bytes = 256; |
4413 | 20 | option (dccl.msg).codec_version = 3; | ||
4414 | 19 | 21 | ||
4415 | 20 | optional CustomMsg msg = 1; | 22 | optional CustomMsg msg = 1; |
4416 | 21 | repeated int32 c = 3 [(dccl.field).max=100, | 23 | repeated int32 c = 3 [(dccl.field).max=100, |
4417 | 22 | 24 | ||
4418 | === modified file 'src/test/dccl_default_id/test.proto' | |||
4419 | --- src/test/dccl_default_id/test.proto 2012-10-19 16:41:36 +0000 | |||
4420 | +++ src/test/dccl_default_id/test.proto 2014-08-27 16:27:22 +0000 | |||
4421 | @@ -4,12 +4,14 @@ | |||
4422 | 4 | { | 4 | { |
4423 | 5 | option (dccl.msg).id = 2; | 5 | option (dccl.msg).id = 2; |
4424 | 6 | option (dccl.msg).max_bytes = 1; | 6 | option (dccl.msg).max_bytes = 1; |
4425 | 7 | option (dccl.msg).codec_version = 3; | ||
4426 | 7 | } | 8 | } |
4427 | 8 | 9 | ||
4428 | 9 | message ShortIDMsgWithData | 10 | message ShortIDMsgWithData |
4429 | 10 | { | 11 | { |
4430 | 11 | option (dccl.msg).id = 3; | 12 | option (dccl.msg).id = 3; |
4431 | 12 | option (dccl.msg).max_bytes = 10; | 13 | option (dccl.msg).max_bytes = 10; |
4432 | 14 | option (dccl.msg).codec_version = 3; | ||
4433 | 13 | 15 | ||
4434 | 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]; |
4435 | 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]; |
4436 | @@ -17,23 +19,28 @@ | |||
4437 | 17 | 19 | ||
4438 | 18 | message LongIDMsg | 20 | message LongIDMsg |
4439 | 19 | { | 21 | { |
4441 | 20 | option (dccl.msg).id = 10000; option (dccl.msg).max_bytes = 2; | 22 | option (dccl.msg).id = 10000; |
4442 | 23 | option (dccl.msg).max_bytes = 2; | ||
4443 | 24 | option (dccl.msg).codec_version = 3; | ||
4444 | 21 | } | 25 | } |
4445 | 22 | 26 | ||
4446 | 23 | message TooLongIDMsg | 27 | message TooLongIDMsg |
4447 | 24 | { | 28 | { |
4448 | 25 | option (dccl.msg).id = 32768; | 29 | option (dccl.msg).id = 32768; |
4449 | 26 | option (dccl.msg).max_bytes = 32; | 30 | option (dccl.msg).max_bytes = 32; |
4450 | 31 | option (dccl.msg).codec_version = 3; | ||
4451 | 27 | } | 32 | } |
4452 | 28 | 33 | ||
4453 | 29 | message LongIDEdgeMsg | 34 | message LongIDEdgeMsg |
4454 | 30 | { | 35 | { |
4455 | 31 | option (dccl.msg).id = 128; | 36 | option (dccl.msg).id = 128; |
4456 | 32 | option (dccl.msg).max_bytes = 2; | 37 | option (dccl.msg).max_bytes = 2; |
4457 | 38 | option (dccl.msg).codec_version = 3; | ||
4458 | 33 | } | 39 | } |
4459 | 34 | 40 | ||
4460 | 35 | message ShortIDEdgeMsg | 41 | message ShortIDEdgeMsg |
4461 | 36 | { | 42 | { |
4462 | 37 | option (dccl.msg).id = 127; | 43 | option (dccl.msg).id = 127; |
4463 | 38 | option (dccl.msg).max_bytes = 1; | 44 | option (dccl.msg).max_bytes = 1; |
4464 | 45 | option (dccl.msg).codec_version = 3; | ||
4465 | 39 | } | 46 | } |
4466 | 40 | 47 | ||
4467 | === modified file 'src/test/dccl_header/header.proto' | |||
4468 | --- src/test/dccl_header/header.proto 2013-08-22 18:58:12 +0000 | |||
4469 | +++ src/test/dccl_header/header.proto 2014-08-27 16:27:22 +0000 | |||
4470 | @@ -11,44 +11,35 @@ | |||
4471 | 11 | // microseconds since Unix | 11 | // microseconds since Unix |
4472 | 12 | 12 | ||
4473 | 13 | // second precision (default) | 13 | // second precision (default) |
4481 | 14 | required uint64 time = 10 [(dccl.field).codec="_time", | 14 | required uint64 time = 10 [(dccl.field).codec="_time"]; |
4482 | 15 | (dccl.field).in_head=true]; | 15 | |
4483 | 16 | 16 | optional int64 time_signed = 20 [(dccl.field).codec="_time"]; | |
4484 | 17 | optional int64 time_signed = 20 [(dccl.field).codec="_time", | 17 | optional double time_double = 21 [(dccl.field).codec="_time"]; |
4478 | 18 | (dccl.field).in_head=true]; | ||
4479 | 19 | optional double time_double = 21 [(dccl.field).codec="_time", | ||
4480 | 20 | (dccl.field).in_head=true]; | ||
4485 | 21 | optional double pasttime_double = 22 [(dccl.field).codec="_time", | 18 | optional double pasttime_double = 22 [(dccl.field).codec="_time", |
4488 | 22 | (dccl.field).num_days=6, | 19 | (dccl.field).num_days=6]; |
4487 | 23 | (dccl.field).in_head=true]; | ||
4489 | 24 | optional double futuretime_double = 23 [(dccl.field).codec="_time", | 20 | optional double futuretime_double = 23 [(dccl.field).codec="_time", |
4492 | 25 | (dccl.field).num_days=6, | 21 | (dccl.field).num_days=6]; |
4491 | 26 | (dccl.field).in_head=true]; | ||
4493 | 27 | 22 | ||
4494 | 28 | // microsecond precision | 23 | // microsecond precision |
4495 | 29 | optional int64 time_precision = 24 [(dccl.field).codec="_time", | 24 | optional int64 time_precision = 24 [(dccl.field).codec="_time", |
4496 | 30 | (dccl.field).in_head=true, | ||
4497 | 31 | (dccl.field).precision=-3]; | 25 | (dccl.field).precision=-3]; |
4498 | 32 | optional double time_double_precision = 25 [(dccl.field).codec="_time", | 26 | optional double time_double_precision = 25 [(dccl.field).codec="_time", |
4499 | 33 | (dccl.field).in_head=true, | ||
4500 | 34 | (dccl.field).precision=6]; | 27 | (dccl.field).precision=6]; |
4501 | 35 | 28 | ||
4502 | 36 | // | 29 | // |
4503 | 37 | // source | 30 | // source |
4504 | 38 | // | 31 | // |
4505 | 39 | required int32 source_platform = 11 [(dccl.field).min = 0, | 32 | required int32 source_platform = 11 [(dccl.field).min = 0, |
4508 | 40 | (dccl.field).max = 31, | 33 | (dccl.field).max = 31]; |
4507 | 41 | (dccl.field).in_head=true]; | ||
4509 | 42 | optional string source_app = 12 [(dccl.field).omit=true]; | 34 | optional string source_app = 12 [(dccl.field).omit=true]; |
4510 | 43 | 35 | ||
4511 | 44 | // | 36 | // |
4512 | 45 | // destination | 37 | // destination |
4513 | 46 | // | 38 | // |
4514 | 47 | enum PublishDestination { PUBLISH_SELF = 1; PUBLISH_OTHER = 2; PUBLISH_ALL = 3; } | 39 | enum PublishDestination { PUBLISH_SELF = 1; PUBLISH_OTHER = 2; PUBLISH_ALL = 3; } |
4516 | 48 | optional PublishDestination dest_type = 13 [default = PUBLISH_SELF, (dccl.field).in_head=true]; | 40 | optional PublishDestination dest_type = 13 [default = PUBLISH_SELF]; |
4517 | 49 | 41 | ||
4518 | 50 | optional int32 dest_platform = 14 [(dccl.field).min = 0, | 42 | optional int32 dest_platform = 14 [(dccl.field).min = 0, |
4521 | 51 | (dccl.field).max = 31, | 43 | (dccl.field).max = 31]; // required if dest_type == other |
4520 | 52 | (dccl.field).in_head=true]; // required if dest_type == other | ||
4522 | 53 | 44 | ||
4523 | 54 | } | 45 | } |
4524 | 55 | 46 | ||
4525 | === modified file 'src/test/dccl_header/test.cpp' | |||
4526 | --- src/test/dccl_header/test.cpp 2014-04-22 20:13:39 +0000 | |||
4527 | +++ src/test/dccl_header/test.cpp 2014-08-27 16:27:22 +0000 | |||
4528 | @@ -24,9 +24,9 @@ | |||
4529 | 24 | // tests proper encoding of standard Goby header | 24 | // tests proper encoding of standard Goby header |
4530 | 25 | 25 | ||
4531 | 26 | #include "dccl/codec.h" | 26 | #include "dccl/codec.h" |
4532 | 27 | #include "dccl/field_codec_default.h" | ||
4533 | 28 | #include "test.pb.h" | 27 | #include "test.pb.h" |
4534 | 29 | 28 | ||
4535 | 29 | #include <sys/time.h> | ||
4536 | 30 | 30 | ||
4537 | 31 | #include "dccl/binary.h" | 31 | #include "dccl/binary.h" |
4538 | 32 | 32 | ||
4539 | 33 | 33 | ||
4540 | === modified file 'src/test/dccl_header/test.proto' | |||
4541 | --- src/test/dccl_header/test.proto 2013-08-22 18:24:42 +0000 | |||
4542 | +++ src/test/dccl_header/test.proto 2014-08-27 16:27:22 +0000 | |||
4543 | @@ -5,9 +5,10 @@ | |||
4544 | 5 | { | 5 | { |
4545 | 6 | option (dccl.msg).id = 4; | 6 | option (dccl.msg).id = 4; |
4546 | 7 | option (dccl.msg).max_bytes = 64; | 7 | option (dccl.msg).max_bytes = 64; |
4547 | 8 | option (dccl.msg).codec_version = 3; | ||
4548 | 8 | 9 | ||
4549 | 9 | required string telegram = 1 [(dccl.field).max_length=10]; | 10 | required string telegram = 1 [(dccl.field).max_length=10]; |
4551 | 10 | required Header header = 2; | 11 | required Header header = 2 [(dccl.field).in_head = true]; |
4552 | 11 | 12 | ||
4553 | 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"]; |
4554 | 13 | } | 14 | } |
4555 | 14 | 15 | ||
4556 | === added directory 'src/test/dccl_message_fix' | |||
4557 | === added file 'src/test/dccl_message_fix/CMakeLists.txt' | |||
4558 | --- src/test/dccl_message_fix/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
4559 | +++ src/test/dccl_message_fix/CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
4560 | @@ -0,0 +1,6 @@ | |||
4561 | 1 | protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto) | ||
4562 | 2 | |||
4563 | 3 | add_executable(dccl_test_message_fix test.cpp ${PROTO_SRCS} ${PROTO_HDRS}) | ||
4564 | 4 | target_link_libraries(dccl_test_message_fix dccl) | ||
4565 | 5 | |||
4566 | 6 | add_test(dccl_test_message_fix ${dccl_BIN_DIR}/dccl_test_message_fix) | ||
4567 | 0 | 7 | ||
4568 | === added file 'src/test/dccl_message_fix/test.cpp' | |||
4569 | --- src/test/dccl_message_fix/test.cpp 1970-01-01 00:00:00 +0000 | |||
4570 | +++ src/test/dccl_message_fix/test.cpp 2014-08-27 16:27:22 +0000 | |||
4571 | @@ -0,0 +1,110 @@ | |||
4572 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
4573 | 2 | // Massachusetts Institute of Technology (2007-) | ||
4574 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
4575 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
4576 | 5 | // | ||
4577 | 6 | // | ||
4578 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
4579 | 8 | // ("DCCL"). | ||
4580 | 9 | // | ||
4581 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
4582 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
4583 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
4584 | 13 | // (at your option) any later version. | ||
4585 | 14 | // | ||
4586 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
4587 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4588 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4589 | 18 | // GNU Lesser General Public License for more details. | ||
4590 | 19 | // | ||
4591 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
4592 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
4593 | 22 | |||
4594 | 23 | |||
4595 | 24 | // tests all protobuf types with _default codecs, repeat and non repeat | ||
4596 | 25 | |||
4597 | 26 | #include <fstream> | ||
4598 | 27 | |||
4599 | 28 | #include <google/protobuf/descriptor.pb.h> | ||
4600 | 29 | |||
4601 | 30 | #include "dccl/codec.h" | ||
4602 | 31 | #include "dccl/codecs2/field_codec_default.h" | ||
4603 | 32 | |||
4604 | 33 | #include "test.pb.h" | ||
4605 | 34 | #include "dccl/binary.h" | ||
4606 | 35 | |||
4607 | 36 | |||
4608 | 37 | int main(int argc, char* argv[]) | ||
4609 | 38 | { | ||
4610 | 39 | // dccl::dlog.connect(dccl::logger::ALL, &std::cerr); | ||
4611 | 40 | // check the empty messages | ||
4612 | 41 | dccl::Codec codec; | ||
4613 | 42 | |||
4614 | 43 | codec.info<TestMsg>(&std::cout); | ||
4615 | 44 | codec.load<TestMsg>(); | ||
4616 | 45 | |||
4617 | 46 | { | ||
4618 | 47 | TestMsg msg_in, msg_out; | ||
4619 | 48 | int i = 0; | ||
4620 | 49 | |||
4621 | 50 | |||
4622 | 51 | std::cout << "Message in:\n" << msg_in.DebugString() << std::endl; | ||
4623 | 52 | |||
4624 | 53 | codec.load(msg_in.GetDescriptor()); | ||
4625 | 54 | |||
4626 | 55 | std::cout << "Try encode..." << std::endl; | ||
4627 | 56 | std::string bytes; | ||
4628 | 57 | codec.encode(&bytes, msg_in); | ||
4629 | 58 | std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl; | ||
4630 | 59 | |||
4631 | 60 | std::cout << "Try decode..." << std::endl; | ||
4632 | 61 | |||
4633 | 62 | codec.decode(bytes, &msg_out); | ||
4634 | 63 | |||
4635 | 64 | std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl; | ||
4636 | 65 | |||
4637 | 66 | assert(!msg_out.has_msg1()); | ||
4638 | 67 | assert(!msg_out.msg1_repeat_size()); | ||
4639 | 68 | assert(!msg_out.has_msg2()); | ||
4640 | 69 | assert(!msg_out.msg2_repeat_size()); | ||
4641 | 70 | assert(msg_in.SerializeAsString() == msg_out.SerializeAsString()); | ||
4642 | 71 | } | ||
4643 | 72 | |||
4644 | 73 | |||
4645 | 74 | // check partially full messages | ||
4646 | 75 | { | ||
4647 | 76 | TestMsg msg_in, msg_out; | ||
4648 | 77 | |||
4649 | 78 | msg_in.mutable_msg1()->set_val(0.1); | ||
4650 | 79 | msg_in.add_msg1_repeat()->set_val(0.11); | ||
4651 | 80 | msg_in.add_msg1_repeat()->set_val(0.12); | ||
4652 | 81 | msg_in.add_msg1_repeat()->set_val(0.13); | ||
4653 | 82 | msg_in.mutable_msg2()->set_val(0.2); | ||
4654 | 83 | msg_in.add_msg2_repeat()->set_val(0.21); | ||
4655 | 84 | msg_in.add_msg2_repeat()->set_val(0.22); | ||
4656 | 85 | msg_in.add_msg2_repeat()->set_val(0.23); | ||
4657 | 86 | |||
4658 | 87 | std::cout << "Message in:\n" << msg_in.DebugString() << std::endl; | ||
4659 | 88 | |||
4660 | 89 | std::cout << "Try encode..." << std::endl; | ||
4661 | 90 | std::string bytes; | ||
4662 | 91 | codec.encode(&bytes, msg_in); | ||
4663 | 92 | std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl; | ||
4664 | 93 | |||
4665 | 94 | std::cout << "Try decode..." << std::endl; | ||
4666 | 95 | |||
4667 | 96 | codec.decode(bytes, &msg_out); | ||
4668 | 97 | |||
4669 | 98 | std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl; | ||
4670 | 99 | |||
4671 | 100 | assert(msg_out.has_msg1()); | ||
4672 | 101 | assert(msg_out.msg1_repeat_size() == 3); | ||
4673 | 102 | assert(msg_out.has_msg2()); | ||
4674 | 103 | assert(msg_out.msg2_repeat_size() == 3); | ||
4675 | 104 | assert(msg_in.SerializeAsString() == msg_out.SerializeAsString()); | ||
4676 | 105 | } | ||
4677 | 106 | |||
4678 | 107 | |||
4679 | 108 | std::cout << "all tests passed" << std::endl; | ||
4680 | 109 | } | ||
4681 | 110 | |||
4682 | 0 | 111 | ||
4683 | === added file 'src/test/dccl_message_fix/test.proto' | |||
4684 | --- src/test/dccl_message_fix/test.proto 1970-01-01 00:00:00 +0000 | |||
4685 | +++ src/test/dccl_message_fix/test.proto 2014-08-27 16:27:22 +0000 | |||
4686 | @@ -0,0 +1,31 @@ | |||
4687 | 1 | import "dccl/protobuf/option_extensions.proto"; | ||
4688 | 2 | |||
4689 | 3 | message EmbeddedMsgOptional | ||
4690 | 4 | { | ||
4691 | 5 | optional double val = 1 [(dccl.field).min=0, | ||
4692 | 6 | (dccl.field).max=126, | ||
4693 | 7 | (dccl.field).precision=3]; | ||
4694 | 8 | } | ||
4695 | 9 | |||
4696 | 10 | message EmbeddedMsgRequired | ||
4697 | 11 | { | ||
4698 | 12 | required double val = 1 [(dccl.field).min=0, | ||
4699 | 13 | (dccl.field).max=126, | ||
4700 | 14 | (dccl.field).precision=3]; | ||
4701 | 15 | } | ||
4702 | 16 | |||
4703 | 17 | message TestMsg | ||
4704 | 18 | { | ||
4705 | 19 | option (dccl.msg).id = 1; | ||
4706 | 20 | option (dccl.msg).max_bytes = 32; | ||
4707 | 21 | option (dccl.msg).codec_version = 3; | ||
4708 | 22 | |||
4709 | 23 | optional EmbeddedMsgOptional msg1 = 1; | ||
4710 | 24 | repeated EmbeddedMsgOptional msg1_repeat = 3 [(dccl.field).max_repeat=5]; | ||
4711 | 25 | |||
4712 | 26 | // in DCCL v2, these will always be set upon receipt since it has required children. This test validates the fix in v3 | ||
4713 | 27 | optional EmbeddedMsgRequired msg2 = 2; | ||
4714 | 28 | repeated EmbeddedMsgRequired msg2_repeat = 4 [(dccl.field).max_repeat=5]; | ||
4715 | 29 | |||
4716 | 30 | } | ||
4717 | 31 | |||
4718 | 0 | 32 | ||
4719 | === modified file 'src/test/dccl_numeric_bounds/test.proto' | |||
4720 | --- src/test/dccl_numeric_bounds/test.proto 2014-03-26 17:27:11 +0000 | |||
4721 | +++ src/test/dccl_numeric_bounds/test.proto 2014-08-27 16:27:22 +0000 | |||
4722 | @@ -4,6 +4,7 @@ | |||
4723 | 4 | { | 4 | { |
4724 | 5 | option (dccl.msg).id = 10; | 5 | option (dccl.msg).id = 10; |
4725 | 6 | option (dccl.msg).max_bytes = 32; | 6 | option (dccl.msg).max_bytes = 32; |
4726 | 7 | option (dccl.msg).codec_version = 3; | ||
4727 | 7 | 8 | ||
4728 | 8 | optional double a = 1 [(dccl.field).max = 180, | 9 | optional double a = 1 [(dccl.field).max = 180, |
4729 | 9 | (dccl.field).min = -180, | 10 | (dccl.field).min = -180, |
4730 | @@ -30,6 +31,7 @@ | |||
4731 | 30 | { | 31 | { |
4732 | 31 | option (dccl.msg).id = 10; | 32 | option (dccl.msg).id = 10; |
4733 | 32 | option (dccl.msg).max_bytes = 32; | 33 | option (dccl.msg).max_bytes = 32; |
4734 | 34 | option (dccl.msg).codec_version = 3; | ||
4735 | 33 | 35 | ||
4736 | 34 | optional double a = 1 [(dccl.field).min = -20, | 36 | optional double a = 1 [(dccl.field).min = -20, |
4737 | 35 | (dccl.field).max = 20, | 37 | (dccl.field).max = 20, |
4738 | @@ -45,6 +47,7 @@ | |||
4739 | 45 | { | 47 | { |
4740 | 46 | option (dccl.msg).id = 11; | 48 | option (dccl.msg).id = 11; |
4741 | 47 | option (dccl.msg).max_bytes = 32; | 49 | option (dccl.msg).max_bytes = 32; |
4742 | 50 | option (dccl.msg).codec_version = 3; | ||
4743 | 48 | 51 | ||
4744 | 49 | optional double a = 1 [(dccl.field).max = 180, | 52 | optional double a = 1 [(dccl.field).max = 180, |
4745 | 50 | (dccl.field).min = -180, | 53 | (dccl.field).min = -180, |
4746 | 51 | 54 | ||
4747 | === modified file 'src/test/dccl_repeated/test.cpp' | |||
4748 | --- src/test/dccl_repeated/test.cpp 2014-04-22 20:13:39 +0000 | |||
4749 | +++ src/test/dccl_repeated/test.cpp 2014-08-27 16:27:22 +0000 | |||
4750 | @@ -25,7 +25,6 @@ | |||
4751 | 25 | 25 | ||
4752 | 26 | 26 | ||
4753 | 27 | #include "dccl/codec.h" | 27 | #include "dccl/codec.h" |
4754 | 28 | #include "dccl/field_codec_default.h" | ||
4755 | 29 | #include "dccl/binary.h" | 28 | #include "dccl/binary.h" |
4756 | 30 | 29 | ||
4757 | 31 | #include "test.pb.h" | 30 | #include "test.pb.h" |
4758 | 32 | 31 | ||
4759 | === modified file 'src/test/dccl_repeated/test.proto' | |||
4760 | --- src/test/dccl_repeated/test.proto 2012-10-23 00:46:12 +0000 | |||
4761 | +++ src/test/dccl_repeated/test.proto 2014-08-27 16:27:22 +0000 | |||
4762 | @@ -5,6 +5,7 @@ | |||
4763 | 5 | { | 5 | { |
4764 | 6 | option (dccl.msg).id = 4; | 6 | option (dccl.msg).id = 4; |
4765 | 7 | option (dccl.msg).max_bytes = 32; | 7 | option (dccl.msg).max_bytes = 32; |
4766 | 8 | option (dccl.msg).codec_version = 3; | ||
4767 | 8 | 9 | ||
4768 | 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]; |
4769 | 10 | } | 11 | } |
4770 | @@ -13,6 +14,7 @@ | |||
4771 | 13 | { | 14 | { |
4772 | 14 | option (dccl.msg).id = 5; | 15 | option (dccl.msg).id = 5; |
4773 | 15 | option (dccl.msg).max_bytes = 32; | 16 | option (dccl.msg).max_bytes = 32; |
4774 | 17 | option (dccl.msg).codec_version = 3; | ||
4775 | 16 | 18 | ||
4776 | 17 | optional bool bool_val = 1; | 19 | optional bool bool_val = 1; |
4777 | 18 | } | 20 | } |
4778 | @@ -21,6 +23,7 @@ | |||
4779 | 21 | { | 23 | { |
4780 | 22 | option (dccl.msg).id = 6; | 24 | option (dccl.msg).id = 6; |
4781 | 23 | option (dccl.msg).max_bytes = 32; | 25 | option (dccl.msg).max_bytes = 32; |
4782 | 26 | option (dccl.msg).codec_version = 3; | ||
4783 | 24 | 27 | ||
4784 | 25 | optional string string_val = 1 [(dccl.field).max_length=10]; | 28 | optional string string_val = 1 [(dccl.field).max_length=10]; |
4785 | 26 | } | 29 | } |
4786 | 27 | 30 | ||
4787 | === modified file 'src/test/dccl_required_optional/test.proto' | |||
4788 | --- src/test/dccl_required_optional/test.proto 2012-10-19 16:41:36 +0000 | |||
4789 | +++ src/test/dccl_required_optional/test.proto 2014-08-27 16:27:22 +0000 | |||
4790 | @@ -4,6 +4,7 @@ | |||
4791 | 4 | { | 4 | { |
4792 | 5 | option (dccl.msg).id = 10; | 5 | option (dccl.msg).id = 10; |
4793 | 6 | option (dccl.msg).max_bytes = 32; | 6 | option (dccl.msg).max_bytes = 32; |
4794 | 7 | option (dccl.msg).codec_version = 3; | ||
4795 | 7 | 8 | ||
4796 | 8 | required bytes req_bytes = 1 [(dccl.field).max_length=8]; | 9 | required bytes req_bytes = 1 [(dccl.field).max_length=8]; |
4797 | 9 | optional bytes opt_bytes = 2 [(dccl.field).max_length=8]; | 10 | optional bytes opt_bytes = 2 [(dccl.field).max_length=8]; |
4798 | 10 | 11 | ||
4799 | === modified file 'src/test/dccl_static_methods/test.proto' | |||
4800 | --- src/test/dccl_static_methods/test.proto 2012-10-23 00:46:12 +0000 | |||
4801 | +++ src/test/dccl_static_methods/test.proto 2014-08-27 16:27:22 +0000 | |||
4802 | @@ -5,6 +5,7 @@ | |||
4803 | 5 | { | 5 | { |
4804 | 6 | option (dccl.msg).id = 4; | 6 | option (dccl.msg).id = 4; |
4805 | 7 | option (dccl.msg).max_bytes = 32; | 7 | option (dccl.msg).max_bytes = 32; |
4806 | 8 | option (dccl.msg).codec_version = 3; | ||
4807 | 8 | 9 | ||
4808 | 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]; |
4809 | 10 | } | 11 | } |
4810 | @@ -13,6 +14,7 @@ | |||
4811 | 13 | { | 14 | { |
4812 | 14 | option (dccl.msg).id = 5; | 15 | option (dccl.msg).id = 5; |
4813 | 15 | option (dccl.msg).max_bytes = 32; | 16 | option (dccl.msg).max_bytes = 32; |
4814 | 17 | option (dccl.msg).codec_version = 3; | ||
4815 | 16 | 18 | ||
4816 | 17 | optional bool bool_val = 1; | 19 | optional bool bool_val = 1; |
4817 | 18 | } | 20 | } |
4818 | @@ -21,6 +23,7 @@ | |||
4819 | 21 | { | 23 | { |
4820 | 22 | option (dccl.msg).id = 6; | 24 | option (dccl.msg).id = 6; |
4821 | 23 | option (dccl.msg).max_bytes = 32; | 25 | option (dccl.msg).max_bytes = 32; |
4822 | 26 | option (dccl.msg).codec_version = 3; | ||
4823 | 24 | 27 | ||
4824 | 25 | optional string string_val = 1 [(dccl.field).max_length=10]; | 28 | optional string string_val = 1 [(dccl.field).max_length=10]; |
4825 | 26 | } | 29 | } |
4826 | 27 | 30 | ||
4827 | === added directory 'src/test/dccl_v2_all_fields' | |||
4828 | === added file 'src/test/dccl_v2_all_fields/CMakeLists.txt' | |||
4829 | --- src/test/dccl_v2_all_fields/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
4830 | +++ src/test/dccl_v2_all_fields/CMakeLists.txt 2014-08-27 16:27:22 +0000 | |||
4831 | @@ -0,0 +1,6 @@ | |||
4832 | 1 | protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS test.proto) | ||
4833 | 2 | |||
4834 | 3 | add_executable(dccl_test_v2_all_fields test.cpp ${PROTO_SRCS} ${PROTO_HDRS}) | ||
4835 | 4 | target_link_libraries(dccl_test_v2_all_fields dccl) | ||
4836 | 5 | |||
4837 | 6 | add_test(dccl_test_v2_all_fields ${dccl_BIN_DIR}/dccl_test_v2_all_fields) | ||
4838 | 0 | 7 | ||
4839 | === added file 'src/test/dccl_v2_all_fields/test.cpp' | |||
4840 | --- src/test/dccl_v2_all_fields/test.cpp 1970-01-01 00:00:00 +0000 | |||
4841 | +++ src/test/dccl_v2_all_fields/test.cpp 2014-08-27 16:27:22 +0000 | |||
4842 | @@ -0,0 +1,175 @@ | |||
4843 | 1 | // Copyright 2009-2013 Toby Schneider (https://launchpad.net/~tes) | ||
4844 | 2 | // Massachusetts Institute of Technology (2007-) | ||
4845 | 3 | // Woods Hole Oceanographic Institution (2007-) | ||
4846 | 4 | // DCCL Developers Team (https://launchpad.net/~dccl-dev) | ||
4847 | 5 | // | ||
4848 | 6 | // | ||
4849 | 7 | // This file is part of the Dynamic Compact Control Language Library | ||
4850 | 8 | // ("DCCL"). | ||
4851 | 9 | // | ||
4852 | 10 | // DCCL is free software: you can redistribute them and/or modify | ||
4853 | 11 | // them under the terms of the GNU Lesser General Public License as published by | ||
4854 | 12 | // the Free Software Foundation, either version 3 of the License, or | ||
4855 | 13 | // (at your option) any later version. | ||
4856 | 14 | // | ||
4857 | 15 | // DCCL is distributed in the hope that they will be useful, | ||
4858 | 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
4859 | 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
4860 | 18 | // GNU Lesser General Public License for more details. | ||
4861 | 19 | // | ||
4862 | 20 | // You should have received a copy of the GNU Lesser General Public License | ||
4863 | 21 | // along with DCCL. If not, see <http://www.gnu.org/licenses/>. | ||
4864 | 22 | |||
4865 | 23 | |||
4866 | 24 | // tests all protobuf types with _default codecs, repeat and non repeat | ||
4867 | 25 | |||
4868 | 26 | #include <fstream> | ||
4869 | 27 | |||
4870 | 28 | #include <google/protobuf/descriptor.pb.h> | ||
4871 | 29 | |||
4872 | 30 | #include "dccl/codec.h" | ||
4873 | 31 | #include "test.pb.h" | ||
4874 | 32 | #include "dccl/binary.h" | ||
4875 | 33 | |||
4876 | 34 | void decode_check(const std::string& encoded); | ||
4877 | 35 | dccl::Codec codec; | ||
4878 | 36 | TestMsg msg_in; | ||
4879 | 37 | |||
4880 | 38 | int main(int argc, char* argv[]) | ||
4881 | 39 | { | ||
4882 | 40 | dccl::dlog.connect(dccl::logger::ALL, &std::cerr); | ||
4883 | 41 | |||
4884 | 42 | int i = 0; | ||
4885 | 43 | msg_in.set_double_default_optional(++i + 0.1); | ||
4886 | 44 | msg_in.set_float_default_optional(++i + 0.2); | ||
4887 | 45 | |||
4888 | 46 | msg_in.set_int32_default_optional(++i); | ||
4889 | 47 | msg_in.set_int64_default_optional(-++i); | ||
4890 | 48 | msg_in.set_uint32_default_optional(++i); | ||
4891 | 49 | msg_in.set_uint64_default_optional(++i); | ||
4892 | 50 | msg_in.set_sint32_default_optional(-++i); | ||
4893 | 51 | msg_in.set_sint64_default_optional(++i); | ||
4894 | 52 | msg_in.set_fixed32_default_optional(++i); | ||
4895 | 53 | msg_in.set_fixed64_default_optional(++i); | ||
4896 | 54 | msg_in.set_sfixed32_default_optional(++i); | ||
4897 | 55 | msg_in.set_sfixed64_default_optional(-++i); | ||
4898 | 56 | |||
4899 | 57 | msg_in.set_bool_default_optional(true); | ||
4900 | 58 | |||
4901 | 59 | msg_in.set_string_default_optional("abc123"); | ||
4902 | 60 | msg_in.set_bytes_default_optional(dccl::hex_decode("00112233aabbcc1234")); | ||
4903 | 61 | |||
4904 | 62 | msg_in.set_enum_default_optional(ENUM_C); | ||
4905 | 63 | msg_in.mutable_msg_default_optional()->set_val(++i + 0.3); | ||
4906 | 64 | msg_in.mutable_msg_default_optional()->mutable_msg()->set_val(++i); | ||
4907 | 65 | |||
4908 | 66 | msg_in.set_double_default_required(++i + 0.1); | ||
4909 | 67 | msg_in.set_float_default_required(++i + 0.2); | ||
4910 | 68 | |||
4911 | 69 | msg_in.set_int32_default_required(++i); | ||
4912 | 70 | msg_in.set_int64_default_required(-++i); | ||
4913 | 71 | msg_in.set_uint32_default_required(++i); | ||
4914 | 72 | msg_in.set_uint64_default_required(++i); | ||
4915 | 73 | msg_in.set_sint32_default_required(-++i); | ||
4916 | 74 | msg_in.set_sint64_default_required(++i); | ||
4917 | 75 | msg_in.set_fixed32_default_required(++i); | ||
4918 | 76 | msg_in.set_fixed64_default_required(++i); | ||
4919 | 77 | msg_in.set_sfixed32_default_required(++i); | ||
4920 | 78 | msg_in.set_sfixed64_default_required(-++i); | ||
4921 | 79 | |||
4922 | 80 | msg_in.set_bool_default_required(true); | ||
4923 | 81 | |||
4924 | 82 | msg_in.set_string_default_required("abc123"); | ||
4925 | 83 | msg_in.set_bytes_default_required(dccl::hex_decode("00112233aabbcc1234")); | ||
4926 | 84 | |||
4927 | 85 | msg_in.set_enum_default_required(ENUM_C); | ||
4928 | 86 | msg_in.mutable_msg_default_required()->set_val(++i + 0.3); | ||
4929 | 87 | msg_in.mutable_msg_default_required()->mutable_msg()->set_val(++i); | ||
4930 | 88 | |||
4931 | 89 | |||
4932 | 90 | for(int j = 0; j < 2; ++j) | ||
4933 | 91 | { | ||
4934 | 92 | msg_in.add_double_default_repeat(++i + 0.1); | ||
4935 | 93 | msg_in.add_float_default_repeat(++i + 0.2); | ||
4936 | 94 | |||
4937 | 95 | msg_in.add_int32_default_repeat(++i); | ||
4938 | 96 | msg_in.add_int64_default_repeat(-++i); | ||
4939 | 97 | msg_in.add_uint32_default_repeat(++i); | ||
4940 | 98 | msg_in.add_uint64_default_repeat(++i); | ||
4941 | 99 | msg_in.add_sint32_default_repeat(-++i); | ||
4942 | 100 | msg_in.add_sint64_default_repeat(++i); | ||
4943 | 101 | msg_in.add_fixed32_default_repeat(++i); | ||
4944 | 102 | msg_in.add_fixed64_default_repeat(++i); | ||
4945 | 103 | msg_in.add_sfixed32_default_repeat(++i); | ||
4946 | 104 | msg_in.add_sfixed64_default_repeat(-++i); | ||
4947 | 105 | |||
4948 | 106 | msg_in.add_bool_default_repeat(true); | ||
4949 | 107 | |||
4950 | 108 | msg_in.add_string_default_repeat("abc123"); | ||
4951 | 109 | |||
4952 | 110 | if(j) | ||
4953 | 111 | msg_in.add_bytes_default_repeat(dccl::hex_decode("00aabbcc")); | ||
4954 | 112 | else | ||
4955 | 113 | msg_in.add_bytes_default_repeat(dccl::hex_decode("ffeedd12")); | ||
4956 | 114 | |||
4957 | 115 | msg_in.add_enum_default_repeat(static_cast<Enum1>((++i % 3) + 1)); | ||
4958 | 116 | EmbeddedMsg1* em_msg = msg_in.add_msg_default_repeat(); | ||
4959 | 117 | em_msg->set_val(++i + 0.3); | ||
4960 | 118 | em_msg->mutable_msg()->set_val(++i); | ||
4961 | 119 | } | ||
4962 | 120 | |||
4963 | 121 | codec.info(msg_in.GetDescriptor()); | ||
4964 | 122 | |||
4965 | 123 | std::ofstream fout("/tmp/testmessage.pb"); | ||
4966 | 124 | msg_in.SerializeToOstream(&fout); | ||
4967 | 125 | |||
4968 | 126 | |||
4969 | 127 | std::cout << "Message in:\n" << msg_in.DebugString() << std::endl; | ||
4970 | 128 | |||
4971 | 129 | codec.load(msg_in.GetDescriptor()); | ||
4972 | 130 | |||
4973 | 131 | std::cout << "Try encode..." << std::endl; | ||
4974 | 132 | std::string bytes; | ||
4975 | 133 | codec.encode(&bytes, msg_in); | ||
4976 | 134 | std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl; | ||
4977 | 135 | |||
4978 | 136 | std::cout << "Try decode..." << std::endl; | ||
4979 | 137 | decode_check(bytes); | ||
4980 | 138 | |||
4981 | 139 | // make sure DCCL defaults stay wire compatible | ||
4982 | 140 | decode_check(dccl::hex_decode("047f277b9628060000b95660c0b0188000d8c0132858800008000dc2c4c6626466024488cca8ee324bd05c3f23af0000ad9112a09509788013e0820b18e0005ed0204c6c2c4666062042644675975982c65235f10a00ad718a5801000000905f27121600000000a0170050640300309201001a0b00007d320a0000a61a0070b20100a81b00d09c6f0000a0401026361643102636160300f0dfbd5b2280ea2e330f3da59a2100aabfa55a000000000000000000000000")); | ||
4983 | 141 | |||
4984 | 142 | // run a bunch of tests with random strings | ||
4985 | 143 | std::string random = bytes; | ||
4986 | 144 | for(unsigned i = 0; i < 10; ++i) | ||
4987 | 145 | { | ||
4988 | 146 | random[(rand() % (bytes.size()-1)+1)] = rand() % 256; | ||
4989 | 147 | std::cout << "Using junk bytes: " << dccl::hex_encode(random) << std::endl; | ||
4990 | 148 | |||
4991 | 149 | try | ||
4992 | 150 | { | ||
4993 | 151 | TestMsg msg_out; | ||
4994 | 152 | codec.decode(random, &msg_out); | ||
4995 | 153 | } | ||
4996 | 154 | catch(dccl::Exception&) | ||
4997 | 155 | { | ||
4998 | 156 | } | ||
4999 | 157 | } | ||
5000 | 158 |
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.