compound.hpp

См. документацию.
00001 /*
00002 
00003 Copyright (c) 2002-2005, Yauheni Akhotnikau
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008 
00009 - Redistributions of source code must retain the above copyright notice, this
00010 list of conditions and the following disclaimer.
00011 
00012 - Redistributions in binary form must reproduce the above copyright notice, this
00013 list of conditions and the following disclaimer in the documentation and/or
00014 other materials provided with the distribution.
00015 
00016 - The name of the author may not be used to endorse or promote products derived
00017 from this software without specific prior written permission.
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00020 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00022 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00024 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00027 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00028 OF SUCH DAMAGE.
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 // tlv_add_caller_t
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 // compound_tlv_t
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       // Последовательно считываем дочерние TLV.
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 } /* namespace tlv */
00451 
00452 } /* namespace oess_1 */
00453 
00454 #endif
00455 

Документация по ObjESSty. Последние изменения: Fri Oct 13 18:35:36 2006. Создано системой  doxygen 1.4.7
Hosted by uCoz