inout_templ.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 
00051 #if !defined( _OESS_1__STDSN__INOUT_TEMPL_HPP_ )
00052 #define _OESS_1__STDSN__INOUT_TEMPL_HPP_
00053 
00054 #include <memory>
00055 
00056 #include <oess_1/defs/h/ex.hpp>
00057 
00058 #include <oess_1/stdsn/h/ent.hpp>
00059 #include <oess_1/stdsn/h/serializable.hpp>
00060 #include <oess_1/stdsn/h/errno.hpp>
00061 
00062 namespace oess_1 {
00063 
00064 namespace stdsn {
00065 
00066 //
00067 // iobj_t
00068 //
00069 
00075 template< class Type >
00076 class iobj_t {
00077   private :
00078     Type &  m_value;
00079 
00080     typedef iobj_t< Type > self_type_t;
00081 
00082     iobj_t( const self_type_t & );
00083     iobj_t &
00084     operator=( const self_type_t & );
00085 
00086   public :
00087     iobj_t( Type & o ) : m_value( o ) {
00088     }
00089     ~iobj_t() {
00090     }
00091 
00092     void
00093     unpack( oess_1::stdsn::ient_t & s ) {
00094       m_value.oess_unpack( s );
00095     }
00096 };
00097 
00098 //
00099 // oobj_t
00100 //
00101 
00107 template< class Type >
00108 class oobj_t {
00109   private :
00110     const Type &  m_value;
00111 
00112     typedef oobj_t< Type > self_type_t;
00113 
00114     oobj_t( const self_type_t & );
00115     oobj_t &
00116     operator=( const self_type_t & );
00117 
00118   public :
00119     oobj_t( const Type & o ) : m_value( o ) {
00120     }
00121     ~oobj_t() {
00122     }
00123 
00124     void
00125     pack( oess_1::stdsn::oent_t & s ) const {
00126       m_value.oess_pack( s );
00127     }
00128 };
00129 
00130 template< class Type >
00131 oess_1::stdsn::oent_t &
00132 operator<<( oess_1::stdsn::oent_t & s, const oobj_t< Type > & o ) {
00133   o.pack( s );
00134   return s;
00135 }
00136 
00137 template< class Type >
00138 oess_1::stdsn::ient_t &
00139 operator>>( oess_1::stdsn::ient_t & s, iobj_t< Type > & o ) {
00140   o.unpack( s );
00141   return s;
00142 }
00143 
00144 //
00145 // Макросы для облегчения специализации шаблонов для
00146 // встроенных типов ObjESSty
00147 //
00148 
00149 #define OESS_1_STDSN_SPECIALIZE_IOBJ_IMPL(T) \
00150 template<> \
00151 class iobj_t< T > { \
00152   typedef T Type; \
00153   private : \
00154     Type &  m_value; \
00155  \
00156     typedef iobj_t< Type > self_type_t; \
00157  \
00158     iobj_t( const self_type_t & ); \
00159     iobj_t & \
00160     operator=( const self_type_t & ); \
00161  \
00162   public : \
00163     iobj_t( Type & o ) : m_value( o ) { \
00164     } \
00165     ~iobj_t() { \
00166     } \
00167  \
00168     void \
00169     unpack( oess_1::stdsn::ient_t & s ) { \
00170       s.query_stream() >> m_value; \
00171     } \
00172 };
00173 
00174 #define OESS_1_STDSN_SPECIALIZE_OOBJ_IMPL(T) \
00175 template<> \
00176 class oobj_t< T > { \
00177   typedef T Type; \
00178   private : \
00179     const Type &  m_value; \
00180  \
00181     typedef oobj_t< Type > self_type_t; \
00182  \
00183     oobj_t( const self_type_t & ); \
00184     oobj_t & \
00185     operator=( const self_type_t & ); \
00186  \
00187   public : \
00188     oobj_t( const Type & o ) : m_value( o ) { \
00189     } \
00190     ~oobj_t() { \
00191     } \
00192  \
00193     void \
00194     pack( oess_1::stdsn::oent_t & s ) const { \
00195       s.query_stream() << m_value; \
00196     } \
00197 };
00198 
00199 #define OESS_1_STDSN_SPECIALIZE_TYPE_IMPL(T) \
00200 OESS_1_STDSN_SPECIALIZE_IOBJ_IMPL(T) \
00201 OESS_1_STDSN_SPECIALIZE_OOBJ_IMPL(T)
00202 
00203 //
00204 // Специализация шаблонов для основных типов.
00205 //
00206 
00207 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::char_t )
00208 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::schar_t )
00209 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::uchar_t )
00210 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::short_t )
00211 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::ushort_t )
00212 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::int_t )
00213 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::uint_t )
00214 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::single_t )
00215 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::double_t )
00216 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( std::string )
00217 OESS_1_STDSN_SPECIALIZE_TYPE_IMPL( oess_1::ent_id_t )
00218 
00219 //
00220 // iptr_t
00221 //
00222 
00229 template< class Type >
00230 class iptr_t {
00231   private :
00232     Type * &  m_value;
00233 
00234     typedef iptr_t< Type > self_type_t;
00235 
00236     iptr_t( const self_type_t & );
00237     iptr_t &
00238     operator=( const self_type_t & );
00239 
00240   public :
00241     iptr_t( Type * & o ) :
00242       m_value( o )
00243     {
00244       m_value = 0;
00245     }
00246     ~iptr_t() {
00247     }
00248 
00249     void
00250     oess_unpack( oess_1::stdsn::ient_t & s ) {
00251       // Первым идет байт, который указывает, есть
00252       // ли значение объекта в потоке или нет.
00253       oess_1::uchar_t is_exists;
00254       s.query_stream() >> is_exists;
00255       if( is_exists ) {
00256         // Значение объекта есть в потоке.
00257         std::string type_name;
00258         s.unpack_type_name( type_name );
00259 
00260         typedef typename Type::oess_serializer_t serializer_t;
00261         auto_ptr_3::obj_ptr_t< serializable_t > ptr(
00262           obj_factory_t::create(
00263             type_name, serializer_t::type_name() ) );
00264         ptr->oess_unpack( s );
00265         m_value = (Type *)ptr->oess_cast(
00266           serializer_t::type_name() );
00267         ptr.release();
00268       }
00269     }
00270 };
00271 
00272 //
00273 // optr_t
00274 //
00275 
00281 template< class Type >
00282 class optr_t {
00283   private :
00284     const Type *  m_value;
00285 
00286     typedef optr_t< Type > self_type_t;
00287 
00288     optr_t( const self_type_t & );
00289     optr_t &
00290     operator=( const self_type_t & );
00291 
00292   public :
00293     optr_t( const Type * o ) : m_value( o ) {
00294     }
00295     ~optr_t() {
00296     }
00297 
00298     void
00299     oess_pack( oess_1::stdsn::oent_t & s ) const {
00300       // Первым идет байт, который указывает, есть
00301       // ли значение объекта в потоке или нет.
00302       oess_1::uchar_t is_exists = ( m_value ? 1 : 0 );
00303       s.query_stream() << is_exists;
00304       if( is_exists ) {
00305         // Значение объекта должно быть в потоке.
00306         s.pack_type_name( m_value->oess_type_name(),
00307           m_value->oess_scheme() );
00308 
00309         m_value->oess_pack( s );
00310       }
00311     }
00312 };
00313 
00314 template< class Type >
00315 oess_1::stdsn::oent_t &
00316 operator<<( oess_1::stdsn::oent_t & s, const optr_t< Type > & o ) {
00317   o.oess_pack( s );
00318   return s;
00319 }
00320 
00321 template< class Type >
00322 oess_1::stdsn::ient_t &
00323 operator>>( oess_1::stdsn::ient_t & s, iptr_t< Type > & o ) {
00324   o.oess_unpack( s );
00325   return s;
00326 }
00327 
00328 //
00329 // iextension_of_t
00330 //
00331 
00337 inline void
00338 operator>>(
00339   oess_1::stdsn::ient_t & s,
00340   oess_1::stdsn::subclass_extension_path_t & path )
00341   {
00342     // Сначала извлекаем общее количество элементов,
00343     // а затем все элементы поочереди.
00344     oess_1::uint_t quantity = 0;
00345     s.query_stream() >> quantity;
00346     while( quantity-- )
00347       {
00348         std::string type_name;
00349         s.unpack_type_name( type_name );
00350 
00351         path.push_back( type_name, std::string() );
00352       }
00353   }
00354 
00360 template< class Type >
00361 class iextension_of_t
00362   {
00363     private :
00364       Type * &  m_value;
00365 
00366       typedef iextension_of_t< Type > self_type_t;
00367       typedef typename Type::oess_serializer_t serializer_t;
00368 
00369       iextension_of_t( const self_type_t & );
00370       iextension_of_t &
00371       operator=( const self_type_t & );
00372 
00373     public :
00374       iextension_of_t( Type * & o )
00375         : m_value( o )
00376         {
00377           m_value = 0;
00378         }
00379       ~iextension_of_t()
00380         {}
00381 
00382       void
00383       oess_unpack( oess_1::stdsn::ient_t & s )
00384         {
00385           // Первым идет байт, который указывает, есть
00386           // ли значение объекта в потоке или нет.
00387           oess_1::uchar_t is_exists;
00388           s.query_stream() >> is_exists;
00389           if( is_exists )
00390             {
00391               // Теперь нужно извлечь из потока цепочку
00392               // наследования.
00393               subclass_extension_path_t path;
00394               s >> path;
00395 
00396               // Идем по цепочке и пытаемся найти ближайший
00397               // базовый тип.
00398               for( subclass_extension_path_t::const_iterator
00399                   it = path.begin(), it_end = path.end();
00400                 it != it_end; ++it )
00401                 {
00402                   auto_ptr_3::obj_ptr_t< serializable_t > ptr(
00403                     obj_factory_t::create(
00404                       it->m_type_name, serializer_t::type_name(),
00405                       obj_factory_t::no_throw_exception ) );
00406                   if( ptr.get() )
00407                     {
00408                       // Удалось создать объект, который сможет
00409                       // десериализовать входной поток.
00410                       ptr->oess_unpack( s );
00411                       m_value = dynamic_cast< Type *>(
00412                         reinterpret_cast< oess_1::stdsn::serializable_t * >(
00413                           ptr->oess_cast(
00414                             serializer_t::type_name() ) ) );
00415                       ptr.release();
00416 
00417                       setup_unknown_extension_path( *m_value, path );
00418 
00419                       // Обработку нужно завершать.
00420                       return;
00421                     }
00422                 }
00423 
00424               // Если мы оказались здесь, значит ничего
00425               // десериализовать нельзя.
00426               OESS_THROW_PHYSIC(
00427                 oess_1::stdsn::err::c_nearest_base_not_found,
00428                 "terminator: " << serializer_t::type_name() );
00429             }
00430         }
00431 
00432     private :
00440       void
00441       setup_unknown_extension_path(
00442         Type & o,
00443         const subclass_extension_path_t & actual_path )
00444         {
00445           subclass_extension_path_t memory_path;
00446           o.oess_get_subclass_extension_path( memory_path,
00447             /*Type::oess_*/serializer_t::type_name() );
00448           if( !( actual_path == memory_path ) )
00449             o.oess_store_unknown_subclass_extension_path(
00450               actual_path );
00451         }
00452   };
00453 
00454 template< class Type >
00455 oess_1::stdsn::ient_t &
00456 operator>>( oess_1::stdsn::ient_t & s, iextension_of_t< Type > & o )
00457 {
00458   o.oess_unpack( s );
00459   return s;
00460 }
00461 
00462 //
00463 // oextension_of_t
00464 //
00465 
00470 inline void
00471 operator<<(
00472   oess_1::stdsn::oent_t & s,
00473   const oess_1::stdsn::subclass_extension_path_t & path )
00474   {
00475     // Сначала сохраняем общее количество элементов,
00476     // а затем все элементы поочереди.
00477     s.query_stream() << path.size();
00478     for( subclass_extension_path_t::const_iterator
00479         it = path.begin(), it_end = path.end();
00480       it != it_end; ++it )
00481       {
00482         s.pack_type_name( it->m_type_name, it->m_scheme );
00483       }
00484   }
00485 
00491 template< class Type >
00492 class oextension_of_t
00493   {
00494     private :
00495       const Type *  m_value;
00496 
00497       typedef oextension_of_t< Type > self_type_t;
00498       typedef typename Type::oess_serializer_t  serializer_t;
00499 
00500       oextension_of_t( const self_type_t & );
00501       oextension_of_t &
00502       operator=( const self_type_t & );
00503 
00504     public :
00505       oextension_of_t( const Type * o ) : m_value( o )
00506         {}
00507       ~oextension_of_t()
00508         {}
00509 
00510       void
00511       oess_pack( oess_1::stdsn::oent_t & s ) const
00512         {
00513           // Первым идет байт, который указывает, есть
00514           // ли значение объекта в потоке или нет.
00515           oess_1::uchar_t is_exists = ( m_value ? 1 : 0 );
00516           s.query_stream() << is_exists;
00517           if( is_exists )
00518             {
00519               oess_1::stdsn::subclass_extension_path_t path;
00520               m_value->oess_get_subclass_extension_path( path,
00521                 serializer_t::type_name() );
00522 
00523               s << path;
00524 
00525               // Значение объекта должно быть в потоке.
00526               m_value->oess_pack( s );
00527             }
00528         }
00529   };
00530 
00531 template< class Type >
00532 oess_1::stdsn::oent_t &
00533 operator<<( oess_1::stdsn::oent_t & s,
00534   const oextension_of_t< Type > & o )
00535 {
00536   o.oess_pack( s );
00537   return s;
00538 }
00539 
00540 //
00541 // Шаблоны для таких контейнеров, как vector, list, deque
00542 //
00543 
00547 template< class List, class Item, class Reader >
00548 class ilist_t {
00549   private :
00550     typedef ilist_t< List, Item, Reader > self_type_t;
00551 
00552     List &  m_value;
00553 
00554     ilist_t( const self_type_t & );
00555     ilist_t &
00556     operator=( const self_type_t & );
00557 
00558   public :
00559     ilist_t( List & o ) : m_value( o ) {
00560     }
00561     ~ilist_t() {
00562     }
00563 
00564     void
00565     oess_unpack( oess_1::stdsn::ient_t & s ) {
00566       m_value.erase( m_value.begin(), m_value.end() );
00567 
00568       oess_1::uint_t size;
00569       iobj_t< oess_1::uint_t > i_size( size );
00570 
00571       for( s >> i_size; size; --size ) {
00572         Item obj;
00573         Reader i_obj( obj );
00574         s >> i_obj;
00575 
00576         m_value.push_back( obj );
00577       }
00578     }
00579 };
00580 
00584 template< class List, class Item, class Writter >
00585 class olist_t {
00586   private :
00587     typedef olist_t< List, Item, Writter >  self_type_t;
00588 
00589     const List &  m_value;
00590 
00591     olist_t( const self_type_t & );
00592     olist_t &
00593     operator=( const self_type_t & );
00594 
00595   public :
00596     olist_t( const List & o ) : m_value( o ) {
00597     }
00598     ~olist_t() {
00599     }
00600 
00601     void
00602     oess_pack( oess_1::stdsn::oent_t & s ) const {
00603       oess_1::uint_t size = m_value.size();
00604       oobj_t< oess_1::uint_t > o_size( size );
00605 
00606       s << o_size;
00607 
00608       for( typename List::const_iterator
00609         it = m_value.begin(), it_end = m_value.end();
00610         it != it_end; ++it ) {
00611         Writter o_obj( (*it) );
00612         s << o_obj;
00613       }
00614     }
00615 };
00616 
00617 //
00618 // Шаблоны для таких контейнеров, как set, multiset
00619 //
00620 
00624 template< class Set, class Item, class Reader >
00625 class iset_t {
00626   private :
00627     typedef iset_t< Set, Item, Reader > self_type_t;
00628 
00629     Set & m_value;
00630 
00631     iset_t( const self_type_t & );
00632     iset_t &
00633     operator=( const self_type_t & );
00634 
00635   public :
00636     iset_t( Set & o ) : m_value( o ) {
00637     }
00638     ~iset_t() {
00639     }
00640 
00641     void
00642     oess_unpack( oess_1::stdsn::ient_t & s ) {
00643       m_value.erase( m_value.begin(), m_value.end() );
00644 
00645       oess_1::uint_t size;
00646       iobj_t< oess_1::uint_t > i_size( size );
00647 
00648       for( s >> i_size; size; --size ) {
00649         Item obj;
00650         Reader i_obj( obj );
00651         s >> i_obj;
00652 
00653         m_value.insert( obj );
00654       }
00655     }
00656 };
00657 
00661 template< class Set, class Item, class Writter >
00662 class oset_t {
00663   private :
00664     typedef oset_t< Set, Item, Writter >  self_type_t;
00665 
00666     const Set & m_value;
00667 
00668     oset_t( const self_type_t & );
00669     oset_t &
00670     operator=( const self_type_t & );
00671 
00672   public :
00673     oset_t( const Set & o ) : m_value( o ) {
00674     }
00675     ~oset_t() {
00676     }
00677 
00678     void
00679     oess_pack( oess_1::stdsn::oent_t & s ) const {
00680       oess_1::uint_t size = m_value.size();
00681       oobj_t< oess_1::uint_t > o_size( size );
00682 
00683       s << o_size;
00684       for( typename Set::const_iterator
00685         it = m_value.begin(), it_end = m_value.end();
00686         it != it_end; ++it ) {
00687         Writter o_obj( (*it) );
00688         s << o_obj;
00689       }
00690     }
00691 };
00692 
00693 //
00694 // Шаблоны для таких контейнеров, как map, multimap
00695 //
00696 
00700 template< class Map, class Item, class Reader >
00701 class imap_t {
00702   private :
00703     typedef typename Map::key_type  key_type_t;
00704 
00705     typedef imap_t< Map, Item, Reader > self_type_t;
00706 
00707     Map & m_value;
00708 
00709     imap_t( const self_type_t & );
00710     imap_t &
00711     operator=( const self_type_t & );
00712 
00713   public :
00714     imap_t( Map & o ) : m_value( o ) {
00715     }
00716     ~imap_t() {
00717     }
00718 
00719     void
00720     oess_unpack( oess_1::stdsn::ient_t & s ) {
00721       m_value.erase( m_value.begin(), m_value.end() );
00722 
00723       oess_1::uint_t size;
00724       iobj_t< oess_1::uint_t > i_size( size );
00725 
00726       typedef typename Map::value_type map_item_t;
00727       for( s >> i_size; size; --size ) {
00728         key_type_t key;
00729         iobj_t< key_type_t > i_key( key );
00730 
00731         Item obj;
00732         Reader i_obj( obj );
00733         s >> i_key >> i_obj;
00734 
00735         m_value.insert( map_item_t( key, obj ) );
00736       }
00737     }
00738 };
00739 
00743 template< class Map, class Item, class Writter >
00744 class omap_t {
00745   private :
00746     typedef typename Map::key_type  key_type_t;
00747 
00748     typedef omap_t< Map, Item, Writter >  self_type_t;
00749 
00750     const Map & m_value;
00751 
00752     omap_t( const self_type_t & );
00753     omap_t &
00754     operator=( const self_type_t & );
00755 
00756   public :
00757     omap_t( const Map & o ) : m_value( o ) {
00758     }
00759     ~omap_t() {
00760     }
00761 
00762     void
00763     oess_pack( oess_1::stdsn::oent_t & s ) const {
00764       oess_1::uint_t size = m_value.size();
00765       oobj_t< oess_1::uint_t > o_size( size );
00766 
00767       s << o_size;
00768 
00769       for( typename Map::const_iterator
00770         it = m_value.begin(), it_end = m_value.end();
00771         it != it_end; ++it ) {
00772         oobj_t< key_type_t > o_key( (*it).first );
00773         Writter o_obj( (*it).second );
00774         s << o_key << o_obj;
00775       }
00776     }
00777 };
00778 
00779 //
00780 // Шаблон вектора фиксированного размера.
00781 //
00782 
00786 template< class Item, size_t Capacity, class Reader >
00787 class ifixed_vector_t {
00788   private :
00789     typedef ifixed_vector_t< Item, Capacity, Reader > self_type_t;
00790 
00791     Item *  m_value;
00792 
00793     ifixed_vector_t( const self_type_t & );
00794     ifixed_vector_t &
00795     operator=( const self_type_t & );
00796 
00797   public :
00798     ifixed_vector_t( Item * o ) : m_value( o ) {
00799     }
00800     ~ifixed_vector_t() {
00801     }
00802 
00803     void
00804     oess_unpack( oess_1::stdsn::ient_t & s ) {
00805       for( size_t i = 0; i != Capacity; ++i ) {
00806         Reader i_obj( m_value[ i ] );
00807         s >> i_obj;
00808       }
00809     }
00810 };
00811 
00815 template< class Item, size_t Capacity, class Writter >
00816 class ofixed_vector_t {
00817   private :
00818     typedef ofixed_vector_t< Item, Capacity, Writter >  self_type_t;
00819 
00820     const Item *  m_value;
00821 
00822     ofixed_vector_t( const self_type_t & );
00823     ofixed_vector_t &
00824     operator=( const self_type_t & );
00825 
00826   public :
00827     ofixed_vector_t( const Item * o ) : m_value( o ) {
00828     }
00829     ~ofixed_vector_t() {
00830     }
00831 
00832     void
00833     oess_pack( oess_1::stdsn::oent_t & s ) const {
00834       for( size_t i = 0; i != Capacity; ++i ) {
00835         Writter o_obj( m_value[ i ] );
00836         s << o_obj;
00837       }
00838     }
00839 };
00840 
00841 } /* namespace oess_1 */
00842 
00843 } /* namespace stdsn */
00844 
00845 #endif
00846 

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