1 /* 2 3 Copyright (c) 2002-2008, Yauheni Akhotnikau 4 Copyright (c) 2008-2013, The SObjectizer Project 5 All rights reserved. 6 7 Redistribution and use in source and binary forms, with or without 8 modification, are permitted provided that the following conditions are met: 9 10 - Redistributions of source code must retain the above copyright notice, this 11 list of conditions and the following disclaimer. 12 13 - Redistributions in binary form must reproduce the above copyright notice, this 14 list of conditions and the following disclaimer in the documentation and/or 15 other materials provided with the distribution. 16 17 - The name of the author may not be used to endorse or promote products derived 18 from this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 25 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 29 OF SUCH DAMAGE. 30 31 */ 32 33 /*! 34 \file oess_2/tlv/h/compound.hpp 35 \brief ����� %oess_2::tlv::coumpound_tlv_t. 36 */ 37 38 #if !defined( _OESS_2__TLV__COMPOUND_HPP_ ) 39 #define _OESS_2__TLV__COMPOUND_HPP_ 40 41 #include <oess_2/tlv/h/declspec.hpp> 42 43 #include <map> 44 #include <string> 45 #include <functional> 46 #include <algorithm> 47 48 #include <cpp_util_2/h/nocopy.hpp> 49 50 #include <oess_2/defs/h/ex.hpp> 51 52 #include <oess_2/io/h/substream.hpp> 53 54 #include <oess_2/tlv/h/errno.hpp> 55 #include <oess_2/tlv/h/base.hpp> 56 #include <oess_2/tlv/h/default_processors.hpp> 57 58 namespace oess_2 59 { 60 61 namespace tlv 62 { 63 64 // 65 // tlv_add_caller_t 66 // 67 68 //! ��������������� ����� ��� ��������� ��������� 69 //! ����������� TLV � ���������� TLV. 70 /*! 71 \since v.1.0.9 72 73 ��� ������������� compound_tlv_t ��������� ���� ���������: 74 ��� ����������� TLV ������ ���� �������� � ���������� 75 TLV ����������� compound_tlv_t::tlv_add(). ���� �� ���������� 76 TLV ����� ����� ����������� TLV, �� ����� ������ ������� 77 tlv_add ��� ������-�� �� ���. ��� �������� � �������������������� 78 ������. 79 80 ����� tlv_add_caller_t �������� ��� �������� ��������� �������: 81 - ��� ������� ������������ TLV, ������������ � �������������� 82 ������ compound_tlv_t::tlv_add(), ����������� ������� ���� 83 tlv_add_caller_t; 84 - � ����������� ������� �� �������� ���������� ���������� 85 ������ �� ������ compound_tlv_t: 86 87 \code 88 typedef oess_2::tlv::compound_tlv_t<tag_type_t > compound_t; 89 class my_compound_tlv_t : 90 public compound_t 91 { 92 private : 93 oess_2::tlv::tagged_scalar_wrapper_t< 94 0x02, string_tlv_t > 95 m_member_1; 96 const tlv_add_t m_member_1_inserter; 97 98 oess_2::tlv::tagged_scalar_wrapper_t< 99 0x05, oess_2::tlv::scalar_tlv_t< 100 tag_type_t, oess_2::ushort_t > > 101 m_member_2; 102 const tlv_add_t m_member_2_inserter; 103 104 public : 105 my_compound_tlv_t( 106 const std::string & member_1, 107 oess_2::ushort_t member_2 ) 108 : 109 compound_t( 0x01 ), 110 m_member_1( member_1 ), 111 m_member_1_inserter( tlv_self(), m_member_1 ), 112 113 m_member_2( member_2 ), 114 m_member_2_inserter( tlv_self(), m_member_2 ), 115 { 116 } 117 118 my_compound_tlv_t() 119 : 120 compound_t( 0x01 ), 121 m_member_1_inserter( tlv_self(), m_member_1 ), 122 m_member_2_inserter( tlv_self(), m_member_2 ) 123 { 124 } 125 }; 126 \endcode 127 */ 128 template< class Compound > 129 class tlv_add_caller_t 130 { 131 public : 132 /*! 133 ������ �������� ����� tlv_add() � ������� owner. 134 */ tlv_add_caller_t(Compound & owner,tlv_base_t & nested)135 tlv_add_caller_t( 136 //! ���������� TLV. 137 Compound & owner, 138 //! ��������� TLV. 139 tlv_base_t & nested ) 140 { 141 owner.tlv_add( nested ); 142 } 143 }; 144 145 // 146 // compound_tlv_t 147 // 148 149 //! TLV ��� ������������ ��������� ��������. 150 /*! 151 ������� compound_tlv_t �� ����� ������������. 152 153 \par ������ (��. oess_2::tlv::basic_string_tlv_t) 154 \code 155 typedef oess_2::tlv::compound_tlv_t<oess_2::ushort_t > compound_t; 156 class my_compound_tlv_t : 157 public compound_t 158 { 159 private : 160 oess_2::tlv::basic_string_tlv_t< 161 oess_2::ushort, oess_2::char_t > 162 m_member_1; 163 oess_2::tlv::basic_string_tlv_t< 164 oess_2::ushort, oess_2::char_t > 165 m_member_2; 166 public : 167 my_compound_tlv_t() : 168 compound_t( 0x01 ), 169 m_member_1( 0x02 ), 170 m_member_2( 0x03 ) 171 { 172 tlv_add( 0x02, m_member_1 ); 173 tlv_add( 0x03, m_member_2 ); 174 } 175 }; 176 \endcode 177 */ 178 template< 179 class Tag_type, 180 class Tag_processor = default_tag_processor_t< Tag_type >, 181 class Length_processor = default_length_processor_t< Tag_type > > 182 class compound_tlv_t : 183 public tlv_base_t, 184 private cpp_util_2::nocopy_t 185 { 186 public : 187 //! ������� ��� compound_tlv_t< Tag_type, 188 //! Tag_processor, Length_processor >. 189 typedef compound_tlv_t< Tag_type, 190 Tag_processor, Length_processor > 191 self_t; 192 193 //! ��� ������� %tlv_add_caller_t ��� 194 //! ������� ���������� TLV. 195 /*! \since v.1.0.9 */ 196 typedef tlv_add_caller_t< self_t > tlv_add_t; 197 198 private : 199 //! ��� ������� �������� TLV. 200 typedef std::map< default_tag_type_t, tlv_base_t * > 201 tlv_map_t; 202 203 //! �������� ��� std::for_each. 204 /*! 205 ��������� ������ ���� �������� TLV. 206 */ 207 class length_calc_t : 208 public std::unary_function< 209 const typename tlv_map_t::value_type &, void > 210 { 211 private : 212 size_t & m_length; 213 public : length_calc_t(size_t & length)214 length_calc_t( size_t & length ) 215 : 216 m_length( length ) 217 { 218 } 219 220 result_type operator ()(argument_type a)221 operator()( argument_type a ) 222 { 223 m_length += a.second->tlv_size(); 224 } 225 }; 226 227 //! �������� ��� std::for_each. 228 /*! 229 ���������� ��� �������� TLV. 230 */ 231 class packer_t : 232 public std::unary_function< 233 const typename tlv_map_t::value_type &, void > 234 { 235 private : 236 oess_2::io::ostream_t & m_stream; 237 public : packer_t(oess_2::io::ostream_t & stream)238 packer_t( oess_2::io::ostream_t & stream ) 239 : 240 m_stream( stream ) 241 { 242 } 243 244 result_type operator ()(argument_type a)245 operator()( argument_type a ) 246 { 247 a.second->tlv_pack( m_stream ); 248 } 249 }; 250 251 //! �������� ���� Tag. 252 Tag_processor m_tag; 253 254 //! ���������� ���� Length. 255 Length_processor m_length; 256 257 //! �������� TLV. 258 tlv_map_t m_tlvs; 259 260 //! ������� ������� TLV �� ������. 261 /*! 262 ����������, ����� �� ������ ��� ���� ��������� ���� Tag. 263 */ 264 void try_unpack_tlv(default_tag_type_t tag,oess_2::io::istream_t & s)265 try_unpack_tlv( 266 //! ���� Tag, ����������� �� ������. 267 default_tag_type_t tag, 268 //! �����, �� �������� ���������� ������. 269 oess_2::io::istream_t & s ) 270 { 271 typename tlv_map_t::iterator it = m_tlvs.find( tag ); 272 if( it != m_tlvs.end() ) 273 // ��� ��������. 274 it->second->tlv_unpack( s, tag ); 275 else 276 // ��� �� ��������. 277 tlv_on_unexpected_tag( tag, s ); 278 } 279 280 281 protected : 282 //! ���������� �� ���������� TLV, ������� ��� 283 //! ��������� �� ������� ������. 284 /*! 285 ���������� � ������� ������ ��������� ���������� 286 oess_2::io::physic_ex_t � ����� 287 oess_2::tlv::err::c_unexpected_tag. 288 */ 289 virtual void tlv_on_unexpected_tag(default_tag_type_t tag,oess_2::io::istream_t & s)290 tlv_on_unexpected_tag( 291 //! ���� Tag, ����������� �� ������. 292 default_tag_type_t tag, 293 //! �����, �� �������� ���������� ������. 294 /*! 295 ����������� ������ ����� ������������ ������ 296 �������� ��� ���������� �� ������ �������� TLV. 297 */ 298 oess_2::io::istream_t & s ) 299 { 300 OESS_THROW_PHYSIC( oess_2::tlv::err::c_unexpected_tag, 301 "compound tag: " << m_tag.query_tag() 302 << ", child tag found: " << tag ) 303 } 304 305 public : compound_tlv_t(Tag_type id)306 compound_tlv_t( Tag_type id ) 307 : 308 m_tag( id ) 309 { 310 } 311 ~compound_tlv_t()312 virtual ~compound_tlv_t() 313 { 314 } 315 316 //! �������� �������� Tag. 317 virtual default_tag_type_t tlv_tag() const318 tlv_tag() const 319 { 320 return m_tag.query_tag(); 321 } 322 323 //! �������� �������� TLV. 324 /*! 325 ���� � compound_tlv_t ��� ��� ������ TLV 326 Tag, ������ tlv.tlv_tag(), �� ��� �������� ��������. 327 */ 328 void tlv_add(tlv_base_t & tlv)329 tlv_add( 330 //! �������� TLV. 331 /*! 332 ��������� ������ ������ ������������ ��� �����, 333 ���� �� ������ � ������� compound_tlv_t. 334 */ 335 tlv_base_t & tlv ) 336 { 337 m_tlvs[ tlv.tlv_tag() ] = &tlv; 338 } 339 340 //! �������� �������� TLV � ��������� ����� Tag. 341 /*! 342 ���� � compound_tlv_t ��� ��� ������ TLV � ����� 343 Tag, �� ��� �������� ��������. 344 345 ������ ����� ������������ ��� �������, ����� 346 �������� ������ tlv ������ ������������ TLV � 347 ���� Tag (�.�. tag != tlv.tlv_tag()). 348 349 ���� ��� �������, ����� ������ tlv ����� �������� 350 � ����������� ��������������� TLV, ������ �� ������� 351 ����� ����������� �������� Tag. 352 */ 353 void tlv_add(default_tag_type_t tag,tlv_base_t & tlv)354 tlv_add( 355 //! ���� Tag ��� ��������� TLV. 356 default_tag_type_t tag, 357 //! �������� TLV. 358 /*! 359 ��������� ������ ������ ������������ ��� �����, 360 ���� �� ������ � ������� compound_tlv_t. 361 */ 362 tlv_base_t & tlv ) 363 { 364 m_tlvs[ tag ] = &tlv; 365 } 366 367 //! ������ �������� TLV � ��������� ����� Tag. 368 /*! 369 ���������� ��������� TLV ������� �� ���������. 370 */ 371 void tlv_remove(default_tag_type_t tag)372 tlv_remove( 373 //! ������������� ���������� TLV. 374 default_tag_type_t tag ) 375 { 376 m_tlvs.erase( tag ); 377 } 378 379 //! ���������� ����, ������� ��������� 380 //! ��� ������������� ����� TLV (� ������ Tag, Length, 381 //! Value). 382 virtual size_t tlv_size() const383 tlv_size() const 384 { 385 size_t length = 0; 386 std::for_each( m_tlvs.begin(), m_tlvs.end(), 387 length_calc_t( length ) ); 388 389 length += m_length.tlv_length_size( length ); 390 length += m_tag.tlv_tag_size(); 391 392 return length; 393 } 394 395 //! ���������� �������� TLV �� ������. 396 virtual void tlv_unpack(oess_2::io::istream_t & s,default_tag_type_t)397 tlv_unpack( 398 //! �����, � ������� ������� �������� ����� 399 //! �������������� ������ ����� Length � Value. 400 oess_2::io::istream_t & s, 401 //! � ������ ������ ������������. 402 default_tag_type_t ) 403 { 404 size_t length; 405 m_length.tlv_unpack_length( s, length ); 406 407 // ��������������� ��������� �������� TLV. 408 oess_2::io::isubstream_t tmp_istream( s, length ); 409 while( !tmp_istream.eof() ) 410 { 411 Tag_processor tag; 412 tag.tlv_unpack_tag( tmp_istream ); 413 414 try_unpack_tlv( tag.query_tag(), tmp_istream ); 415 } 416 } 417 418 //! ������ TLV � �������� �����. 419 virtual void tlv_pack(oess_2::io::ostream_t & s) const420 tlv_pack( 421 //! �����, � ������� ������� �������� ����� 422 //! �������������� ������ TLV. 423 oess_2::io::ostream_t & s ) const 424 { 425 // ����� ���� �������� �����. 426 size_t length = 0; 427 std::for_each( m_tlvs.begin(), m_tlvs.end(), 428 length_calc_t( length ) ); 429 430 m_tag.tlv_pack_tag( s ); 431 m_length.tlv_pack_length( s, length ); 432 if( length ) 433 { 434 packer_t packer( s ); 435 std::for_each( m_tlvs.begin(), m_tlvs.end(), packer ); 436 } 437 } 438 439 //! ���������� ������ �� ������ ����. 440 /*! \since v.1.0.9 441 442 ������������ ��� ������������� ������ 443 tlv_add_caller_t. */ 444 self_t & tlv_self()445 tlv_self() 446 { 447 return *this; 448 } 449 }; 450 451 } /* namespace tlv */ 452 453 } /* namespace oess_2 */ 454 455 #endif 456 457