00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00037 #if !defined( _OESS_1__TLV__COMPOUND_HPP_ )
00038 #define _OESS_1__TLV__COMPOUND_HPP_
00039
00040 #include <oess_1/tlv/h/declspec.hpp>
00041
00042 #include <map>
00043 #include <string>
00044 #include <functional>
00045 #include <algorithm>
00046
00047 #include <cpp_util_2/h/nocopy.hpp>
00048
00049 #include <oess_1/defs/h/ex.hpp>
00050
00051 #include <oess_1/io/h/subbinstream.hpp>
00052
00053 #include <oess_1/tlv/h/errno.hpp>
00054 #include <oess_1/tlv/h/base.hpp>
00055 #include <oess_1/tlv/h/default_processors.hpp>
00056
00057 namespace oess_1
00058 {
00059
00060 namespace tlv
00061 {
00062
00063
00064
00065
00066
00069
00127 template< class Compound >
00128 class tlv_add_caller_t
00129 {
00130 public :
00134 tlv_add_caller_t(
00136 Compound & owner,
00138 tlv_base_t & nested )
00139 {
00140 owner.tlv_add( nested );
00141 }
00142 };
00143
00144
00145
00146
00147
00149
00177 template<
00178 class Tag_type,
00179 class Tag_processor = default_tag_processor_t< Tag_type >,
00180 class Length_processor = default_length_processor_t< Tag_type > >
00181 class compound_tlv_t :
00182 public tlv_base_t,
00183 private cpp_util_2::nocopy_t
00184 {
00185 public :
00188 typedef compound_tlv_t< Tag_type,
00189 Tag_processor, Length_processor >
00190 self_t;
00191
00194
00195 typedef tlv_add_caller_t< self_t > tlv_add_t;
00196
00197 private :
00199 typedef std::map< default_tag_type_t, tlv_base_t * >
00200 tlv_map_t;
00201
00203
00206 class length_calc_t :
00207 public std::unary_function<
00208 const typename tlv_map_t::value_type &, void >
00209 {
00210 private :
00211 size_t & m_length;
00212 public :
00213 length_calc_t( size_t & length )
00214 :
00215 m_length( length )
00216 {
00217 }
00218
00219 result_type
00220 operator()( argument_type a )
00221 {
00222 m_length += a.second->tlv_size();
00223 }
00224 };
00225
00227
00230 class packer_t :
00231 public std::unary_function<
00232 const typename tlv_map_t::value_type &, void >
00233 {
00234 private :
00235 oess_1::io::obinstream_t & m_stream;
00236 public :
00237 packer_t( oess_1::io::obinstream_t & stream )
00238 :
00239 m_stream( stream )
00240 {
00241 }
00242
00243 result_type
00244 operator()( argument_type a )
00245 {
00246 a.second->tlv_pack( m_stream );
00247 }
00248 };
00249
00251 Tag_processor m_tag;
00252
00254 Length_processor m_length;
00255
00257 tlv_map_t m_tlvs;
00258
00260
00263 void
00264 try_unpack_tlv(
00266 default_tag_type_t tag,
00268 oess_1::io::ibinstream_t & s )
00269 {
00270 typename tlv_map_t::iterator it = m_tlvs.find( tag );
00271 if( it != m_tlvs.end() )
00272
00273 it->second->tlv_unpack( s, tag );
00274 else
00275
00276 tlv_on_unexpected_tag( tag, s );
00277 }
00278
00279
00280 protected :
00283
00288 virtual void
00289 tlv_on_unexpected_tag(
00291 default_tag_type_t tag,
00293
00297 oess_1::io::ibinstream_t & s )
00298 {
00299 OESS_THROW_PHYSIC( oess_1::tlv::err::c_unexpected_tag,
00300 "compound tag: " << m_tag.query_tag()
00301 << ", child tag found: " << tag )
00302 }
00303
00304 public :
00305 compound_tlv_t( Tag_type id )
00306 :
00307 m_tag( id )
00308 {
00309 }
00310
00311 virtual ~compound_tlv_t()
00312 {
00313 }
00314
00316 virtual default_tag_type_t
00317 tlv_tag() const
00318 {
00319 return m_tag.query_tag();
00320 }
00321
00323
00327 void
00328 tlv_add(
00330
00334 tlv_base_t & tlv )
00335 {
00336 m_tlvs[ tlv.tlv_tag() ] = &tlv;
00337 }
00338
00340
00352 void
00353 tlv_add(
00355 default_tag_type_t tag,
00357
00361 tlv_base_t & tlv )
00362 {
00363 m_tlvs[ tag ] = &tlv;
00364 }
00365
00367
00370 void
00371 tlv_remove(
00373 default_tag_type_t tag )
00374 {
00375 m_tlvs.erase( tag );
00376 }
00377
00381 virtual size_t
00382 tlv_size() const
00383 {
00384 size_t length = 0;
00385 std::for_each( m_tlvs.begin(), m_tlvs.end(),
00386 length_calc_t( length ) );
00387
00388 length += m_length.tlv_length_size( length );
00389 length += m_tag.tlv_tag_size();
00390
00391 return length;
00392 }
00393
00395 virtual void
00396 tlv_unpack(
00399 oess_1::io::ibinstream_t & s,
00401 default_tag_type_t )
00402 {
00403 size_t length;
00404 m_length.tlv_unpack_length( s, length );
00405
00406
00407 oess_1::io::isubbinstream_t tmp_istream( s, length );
00408 while( !tmp_istream.eof() )
00409 {
00410 Tag_processor tag;
00411 tag.tlv_unpack_tag( tmp_istream );
00412
00413 try_unpack_tlv( tag.query_tag(), tmp_istream );
00414 }
00415 }
00416
00418 virtual void
00419 tlv_pack(
00422 oess_1::io::obinstream_t & s ) const
00423 {
00424
00425 size_t length = 0;
00426 std::for_each( m_tlvs.begin(), m_tlvs.end(),
00427 length_calc_t( length ) );
00428
00429 m_tag.tlv_pack_tag( s );
00430 m_length.tlv_pack_length( s, length );
00431 if( length )
00432 {
00433 packer_t packer( s );
00434 std::for_each( m_tlvs.begin(), m_tlvs.end(), packer );
00435 }
00436 }
00437
00439
00443 self_t &
00444 tlv_self()
00445 {
00446 return *this;
00447 }
00448 };
00449
00450 }
00451
00452 }
00453
00454 #endif
00455