22 #ifndef FieldCodecManager20110405H
23 #define FieldCodecManager20110405H
25 #include <boost/utility/enable_if.hpp>
26 #include <boost/type_traits.hpp>
27 #include <boost/mpl/and.hpp>
28 #include <boost/mpl/not.hpp>
29 #include <boost/mpl/logical.hpp>
31 #include "internal/type_helper.h"
32 #include "field_codec.h"
33 #include "dccl/logger.h"
57 typename boost::enable_if<
58 boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
59 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
70 typename boost::disable_if<
71 boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
72 boost::mpl::not_<boost::is_same<google::protobuf::Message,typename Codec::wire_type> >
82 template<
class Codec, google::protobuf::FieldDescriptor::Type type>
83 static void add(
const std::string& name);
91 typename boost::enable_if<
92 boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
93 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
103 template<
class Codec>
104 typename boost::disable_if<
105 boost::mpl::and_<boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
106 boost::mpl::not_<boost::is_same<google::protobuf::Message,typename Codec::wire_type> >
116 template<
class Codec, google::protobuf::FieldDescriptor::Type type>
117 static void remove(
const std::string& name);
121 static boost::shared_ptr<FieldCodecBase>
find(
122 const google::protobuf::FieldDescriptor* field,
123 bool has_codec_group,
124 const std::string& codec_group)
126 std::string name = __find_codec(field, has_codec_group, codec_group);
128 if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
129 return find(field->message_type(), name);
131 return __find(field->type(), name);
138 static boost::shared_ptr<FieldCodecBase>
find(
139 const google::protobuf::Descriptor* desc,
140 std::string name =
"")
146 if(desc->options().GetExtension(dccl::msg).has_codec())
147 name = desc->options().GetExtension(dccl::msg).codec();
149 name = FieldCodecBase::codec_group(desc);
152 return __find(google::protobuf::FieldDescriptor::TYPE_MESSAGE,
153 name, desc->full_name());
156 static boost::shared_ptr<FieldCodecBase>
find(
157 google::protobuf::FieldDescriptor::Type type,
160 return __find(type, name);
165 internal::TypeHelper::reset();
171 FieldCodecManager() { }
172 ~FieldCodecManager() { }
173 FieldCodecManager(
const FieldCodecManager&);
174 FieldCodecManager& operator= (
const FieldCodecManager&);
178 static boost::shared_ptr<FieldCodecBase> __find(
179 google::protobuf::FieldDescriptor::Type type,
180 const std::string& codec_name,
181 const std::string& type_name =
"");
183 static std::string __mangle_name(
const std::string& codec_name,
184 const std::string& type_name)
185 {
return type_name.empty() ? codec_name : codec_name +
"[" + type_name +
"]"; }
188 template<
typename WireType,
typename FieldType,
class Codec>
189 static void add_all_types(
const std::string& name);
191 template<
class Codec>
192 static void add_single_type(
const std::string& name,
193 google::protobuf::FieldDescriptor::Type field_type,
194 google::protobuf::FieldDescriptor::CppType wire_type);
196 template<
typename WireType,
typename FieldType,
class Codec>
197 static void remove_all_types(
const std::string& name);
199 template<
class Codec>
200 static void remove_single_type(
const std::string& name,
201 google::protobuf::FieldDescriptor::Type field_type,
202 google::protobuf::FieldDescriptor::CppType wire_type);
205 static std::string __find_codec(
const google::protobuf::FieldDescriptor* field,
206 bool has_codec_group,
const std::string& codec_group)
211 if(dccl_field_options.has_codec())
212 return dccl_field_options.codec();
214 else if(field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE && field->message_type()->options().GetExtension(dccl::msg).has_codec())
215 return field->message_type()->options().GetExtension(dccl::msg).codec();
217 else if(has_codec_group)
221 return dccl_field_options.codec();
225 typedef std::map<std::string, boost::shared_ptr<FieldCodecBase> > InsideMap;
226 static std::map<google::protobuf::FieldDescriptor::Type, InsideMap> codecs_;
230 template<
class Codec>
231 typename boost::enable_if<
233 boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
234 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
239 internal::TypeHelper::add<typename Codec::wire_type>();
240 add_single_type<Codec>(__mangle_name(name, Codec::wire_type::descriptor()->full_name()),
241 google::protobuf::FieldDescriptor::TYPE_MESSAGE,
242 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
245 template<
class Codec>
246 typename boost::disable_if<
248 boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
249 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
254 add_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name);
257 template<
class Codec, google::protobuf::FieldDescriptor::Type type>
260 add_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));
264 template<
typename WireType,
typename FieldType,
class Codec>
265 void dccl::FieldCodecManager::add_all_types(
const std::string& name)
267 using google::protobuf::FieldDescriptor;
271 for(
int i = 1, n = FieldDescriptor::MAX_TYPE; i <= n; ++i)
273 FieldDescriptor::Type field_type =
static_cast<FieldDescriptor::Type
>(i);
274 if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)
276 add_single_type<Codec>(name, field_type, cpp_wire_type);
281 template<
class Codec>
282 void dccl::FieldCodecManager::add_single_type(
const std::string& name,
283 google::protobuf::FieldDescriptor::Type field_type,
284 google::protobuf::FieldDescriptor::CppType wire_type)
286 using google::protobuf::FieldDescriptor;
287 if(!codecs_[field_type].count(name))
289 boost::shared_ptr<FieldCodecBase> new_field_codec(
new Codec());
290 new_field_codec->set_name(name);
291 new_field_codec->set_field_type(field_type);
292 new_field_codec->set_wire_type(wire_type);
294 codecs_[field_type][name] = new_field_codec;
295 dccl::dlog.
is(dccl::logger::DEBUG1) && dccl::dlog <<
"Adding codec " << *new_field_codec << std::endl;
299 boost::shared_ptr<FieldCodecBase> new_field_codec(
new Codec());
300 new_field_codec->set_name(name);
301 new_field_codec->set_field_type(field_type);
302 new_field_codec->set_wire_type(wire_type);
304 dccl::dlog.
is(dccl::logger::DEBUG1) && dccl::dlog <<
"Trying to add: " << *new_field_codec
305 <<
", but already have duplicate codec (For `name`/`field type` pair) "
306 << *(codecs_[field_type].find(name)->second)
313 template<
class Codec>
314 typename boost::enable_if<
316 boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
317 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
322 internal::TypeHelper::remove<typename Codec::wire_type>();
323 remove_single_type<Codec>(__mangle_name(name, Codec::wire_type::descriptor()->full_name()),
324 google::protobuf::FieldDescriptor::TYPE_MESSAGE,
325 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
328 template<
class Codec>
329 typename boost::disable_if<
331 boost::is_base_of<google::protobuf::Message, typename Codec::wire_type>,
332 boost::mpl::not_<boost::is_same<google::protobuf::Message, typename Codec::wire_type> >
337 remove_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name);
340 template<
class Codec, google::protobuf::FieldDescriptor::Type type>
343 remove_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));
347 template<
typename WireType,
typename FieldType,
class Codec>
348 void dccl::FieldCodecManager::remove_all_types(
const std::string& name)
350 using google::protobuf::FieldDescriptor;
354 for(
int i = 1, n = FieldDescriptor::MAX_TYPE; i <= n; ++i)
356 FieldDescriptor::Type field_type =
static_cast<FieldDescriptor::Type
>(i);
357 if(FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)
359 remove_single_type<Codec>(name, field_type, cpp_wire_type);
364 template<
class Codec>
365 void dccl::FieldCodecManager::remove_single_type(
const std::string& name,
366 google::protobuf::FieldDescriptor::Type field_type,
367 google::protobuf::FieldDescriptor::CppType wire_type)
369 using google::protobuf::FieldDescriptor;
370 if(codecs_[field_type].count(name))
372 dccl::dlog.
is(dccl::logger::DEBUG1) && dccl::dlog <<
"Removing codec " << *codecs_[field_type][name] << std::endl;
373 codecs_[field_type].erase(name);
377 boost::shared_ptr<FieldCodecBase> new_field_codec(
new Codec());
378 new_field_codec->set_name(name);
379 new_field_codec->set_field_type(field_type);
380 new_field_codec->set_wire_type(wire_type);
382 dccl::dlog.
is(dccl::logger::DEBUG1) && dccl::dlog <<
"Trying to remove: " << *new_field_codec
383 <<
", but no such codec exists"