/*************************************************************************** * * Copyright (c) 2008 Baidu.com, Inc. All Rights Reserved * $Id: MagicDict.h,v 1.2 2010/04/28 12:45:33 scmpf Exp $ * **************************************************************************/ /** * @file MagicDict.h * @author chenxm(chenxiaoming@baidu.com) * @date 2008/09/24 01:36:18 * @version $Revision: 1.2 $ * @brief * **/ #ifndef __BSL_VAR_MAGIC_DICT_H__ #define __BSL_VAR_MAGIC_DICT_H__ #include #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 #include #elif __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 #include #elif __GNUC__ >= 3 #include #else #include #endif #include "bsl/pool/bsl_pool.h" #include "bsl/var/IVar.h" #include "bsl/var/MagicRef.h" #include "bsl/var/Null.h" #include "bsl/var/utils.h" #if __GNUC__ < 3 namespace __gnu_cxx{ /** * @brief ʹg++2.96ҲͳһΪ__gnu_cxxÃüÃû¿Õ¼ä * * */ using std::hash_map; using std::hash; #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 using std::tr1; #endif } #endif namespace bsl{ namespace var{ //forward declarations & typedefs template class MagicBasicDict; templateclass Alloc> class __MagicStdMapAdapter; templateclass Alloc> class __MagicGnuHashMapAdapter; /** * @brief ·â×°ÁËstd::map£¬²¢Ê¹ÓÃbsl::pool_allocatorµÄ×Öµä * */ typedef MagicBasicDict<__MagicStdMapAdapter > MagicStdMapDict; /** * @brief ·â×°ÁË__gnu_cxx::hash_map£¬²¢Ê¹ÓÃbsl::pool_allocatorµÄ×Öµä * * */ typedef MagicBasicDict<__MagicGnuHashMapAdapter >MagicGnuHashDict; /** * @brief ×îÍÆ¼öʹÓõÄ×Öµä * * Ŀǰ×îÍÆ¼öʹÓõÄÊÇ·â×°ÁËstd::map£¬²¢Ê¹ÓÃbsl::pool_allocatorµÄStdMapDict */ typedef MagicStdMapDict MagicDict; template class MagicBasicDict: public IVar{ public: typedef IVar::string_type string_type; typedef IVar::field_type field_type; typedef typename implement_t::allocator_type allocator_type; typedef DictIterator dict_iterator; typedef DictConstIterator dict_const_iterator; typedef MagicRef reference_type; public: MagicBasicDict(bsl::ResourcePool& rp) :_dict(), _alloc(), _rp(rp) {} explicit MagicBasicDict( bsl::ResourcePool& rp, size_t init_capacity, const allocator_type& alloc_ = allocator_type() ) :_dict(init_capacity, alloc_), _alloc(alloc_), _rp(rp) {} explicit MagicBasicDict( bsl::ResourcePool& rp, const allocator_type& alloc_ ) :_dict(alloc_), _alloc(alloc_), _rp(rp) {} MagicBasicDict( const MagicBasicDict& other ) :IVar(other), _dict(other._dict), _alloc(other._alloc), _rp(other._rp) {} MagicBasicDict& operator = ( const MagicBasicDict& other ){ try{ _dict = other._dict; _alloc= other._alloc; }catch(bsl::Exception& e){ e<<"{"<<__PRETTY_FUNCTION__<<"("<key(), (iter->value()).clone(rp, is_deep_copy)); } } return res; } /** * @brief µÝ¹é´òÓ¡×ÔÉí¼°Ï¼¶½áµãÐÅÏ¢ * * @param [in] verbose_level : size_t * @return string_type * @retval * @see * @author chenxm * @date 2009/05/14 17:34:58 **/ /** * @brief Êä³öµ÷ÊÔÐÅÏ¢£¨½öÓÃÓÚµ÷ÊÔ£©¿Éͨ¹ýverbose_level¿ØÖƵݹé²ãÊý * * @return string_type * @retval * @see * @author chenxm * @date 2010/03/17 19:44:20 **/ virtual string_type dump(size_t verbose_level = 0) const { string_type res; if ( verbose_level == 0 ){ res.appendf("[bsl::var::MagicBasicDict] this[%p] size[%zd]", this, _dict.size() ); }else{ dump_to_string(*this, res, verbose_level, "", 0 ); } return res; } /** * @brief ת»¯Îª×Ö·û´® * * @return string_type * @retval * @see * @author chenxm * @date 2010/03/17 19:44:20 **/ virtual string_type to_string() const { return dump(0); } virtual MagicBasicDict& operator = ( IVar& var ) { if ( typeid(var) == typeid(*this) ){ _dict = dynamic_cast(var)._dict; }else if ( var.is_dict() ){ _dict.clear(); IVar::dict_iterator iter_ = var.dict_begin(); IVar::dict_iterator end = var.dict_end(); for( ; iter_ != end ; ++ iter_ ){ bsl::var::MagicRef mr(_rp); mr = iter_->value(); _dict.insert(std::make_pair(iter_->key(), mr)); } }else{ throw bsl::InvalidOperationException()<second; } virtual IVar& get( const field_type& name, IVar& default_value ) { iter_impl_t iter_ = _dict.find( name ); if ( iter_ == _dict.end() ){ return default_value; } return iter_->second; } virtual const IVar& get( const field_type& name ) const { const_iter_impl_t iter_ = _dict.find( name ); if ( iter_ == _dict.end() ){ return bsl::var::Null::null; } return iter_->second; } virtual const IVar& get( const field_type& name, const IVar& default_value ) const { const_iter_impl_t iter_ = _dict.find( name ); if ( iter_ == _dict.end() ){ return default_value; } return iter_->second; } virtual void set( const field_type& name, IVar& value ){ bsl::var::MagicRef mr(_rp); mr = value; typedef std::pair pair_t; pair_t res = _dict.insert( std::pair( name, mr ) ); if ( !res.second ){ //already exist res.first->second = mr; } } virtual bool del( const field_type& name ) { iter_impl_t iter_ = _dict.find( name ); if ( iter_ == _dict.end() ){ return false; } _dict.erase( iter_ ); return true; } virtual dict_const_iterator dict_begin() const { return dict_const_iterator( _s_create_const_iterator( _dict.begin(), &_alloc ), _s_clone_const_iterator, _s_destroy_const_iterator, &_alloc ); } virtual dict_iterator dict_begin() { return dict_iterator( _s_create_iterator( _dict.begin(), &_alloc ), _s_clone_iterator, _s_destroy_iterator, &_alloc ); } virtual dict_const_iterator dict_end() const { return dict_const_iterator( _s_create_const_iterator( _dict.end(), &_alloc ), _s_clone_const_iterator, _s_destroy_const_iterator, &_alloc ); } virtual dict_iterator dict_end() { return dict_iterator( _s_create_iterator( _dict.end(), &_alloc ), _s_clone_iterator, _s_destroy_iterator, &_alloc ); } virtual const IVar& operator []( const field_type& name ) const { const_iter_impl_t iter_ = _dict.find(name); if ( iter_ == _dict.end() ){ throw bsl::KeyNotFoundException()<second; } virtual IVar& operator []( const field_type& name ){ iter_impl_t iter_ = _dict.find(name); if ( iter_ == _dict.end() ){ iter_ = _dict.insert(std::make_pair(name, bsl::var::MagicRef(_rp))).first; } return iter_->second; } //methods for array #if __GNUC__ > 2 using IVar::operator []; using IVar::get; using IVar::set; using IVar::del; #else //avoid using bug of g++ 2.96 virtual IVar& get( size_t idx ) { throw bsl::InvalidOperationException()<first; } virtual IVar& value() const { return _iter->second; } virtual void iterate(){ ++ _iter; } virtual void assign( const IDictIteratorImpl& other ) { const DictIteratorImpl *p = dynamic_cast(&other); if ( !p ){ throw bsl::BadCastException()<_iter; } virtual bool equal_to( const IDictIteratorImpl& other ) const; virtual bool equal_to( const IDictConstIteratorImpl& other ) const; private: iter_impl_t _iter; }; class DictConstIteratorImpl: public IDictConstIteratorImpl{ friend class DictIteratorImpl; public: DictConstIteratorImpl( const const_iter_impl_t& iter_ ) :_iter(iter_){} virtual ~DictConstIteratorImpl() { //pass } virtual const string_type& key() const { return _iter->first; } virtual const IVar& value() const { return _iter->second; } virtual void iterate(){ ++ _iter; } virtual void assign( const IDictIteratorImpl& other ) { const DictIteratorImpl *p = dynamic_cast(&other); if ( !p ){ throw bsl::BadCastException()<_iter; } virtual void assign( const IDictConstIteratorImpl& other ) { const DictConstIteratorImpl *p = dynamic_cast(&other); if ( !p ){ throw bsl::BadCastException()<_iter; } virtual bool equal_to( const IDictConstIteratorImpl& other ) const; virtual bool equal_to( const IDictIteratorImpl& other ) const; private: const_iter_impl_t _iter; }; static IDictIteratorImpl * _s_create_iterator( const iter_impl_t& iter_, const void *p_alloc ){ typedef typename allocator_type::template rebind::other impl_alloc_t; IDictIteratorImpl *p = impl_alloc_t(*static_cast(p_alloc)).allocate(1); //throw new(p) DictIteratorImpl( iter_ ); //nothrow return p; } static IDictConstIteratorImpl * _s_create_const_iterator( const const_iter_impl_t& iter_, const void *p_alloc ){ typedef typename allocator_type::template rebind::other impl_alloc_t; IDictConstIteratorImpl *p = impl_alloc_t(*static_cast(p_alloc)).allocate(1); //throw new(p) DictConstIteratorImpl( iter_ ); //nothrow return p; } static IDictIteratorImpl * _s_clone_iterator( const IDictIteratorImpl *p_other, const void *p_alloc ){ typedef typename allocator_type::template rebind::other impl_alloc_t; const DictIteratorImpl *psrc = dynamic_cast(p_other); if ( !psrc ){ throw bsl::BadCastException()<(p_alloc)).allocate(1); //throw new(p) DictIteratorImpl(*psrc); return p; } static IDictConstIteratorImpl * _s_clone_const_iterator( const IDictConstIteratorImpl *p_other, const void *p_alloc ){ typedef typename allocator_type::template rebind::other impl_alloc_t; const DictConstIteratorImpl *psrc = dynamic_cast(p_other); if ( !psrc ){ throw bsl::BadCastException()<(p_alloc)).allocate(1); //throw new(p) DictConstIteratorImpl(*psrc); return p; } static void _s_destroy_iterator( IDictIteratorImpl * p, const void *p_alloc){ typedef typename allocator_type::template rebind::other impl_alloc_t; DictIteratorImpl *_p = dynamic_cast(p); if ( _p ){ _p->~DictIteratorImpl(); impl_alloc_t(*static_cast(p_alloc)).deallocate( _p, 1 ); } } static void _s_destroy_const_iterator( IDictConstIteratorImpl * p, const void *p_alloc ){ typedef typename allocator_type::template rebind::other impl_alloc_t; DictConstIteratorImpl *_p = dynamic_cast(p); if ( _p ){ _p->~DictConstIteratorImpl(); impl_alloc_t(*static_cast(p_alloc)).deallocate( _p, 1 ); } } implement_t _dict; allocator_type _alloc; //TODO£ºÎªÁ˼òµ¥Ö±¹Û£¬Ã»ÓÐ×öEBOÓÅ»¯£¬ÒÔºó¿ÉÒÔ¼ÓÉÏ bsl::ResourcePool& _rp; }; template inline bool MagicBasicDict::DictIteratorImpl::equal_to( const IDictIteratorImpl& other ) const { const DictIteratorImpl *p = dynamic_cast(&other); return p != NULL && _iter == p->_iter; } template inline bool MagicBasicDict::DictIteratorImpl::equal_to( const IDictConstIteratorImpl& other ) const { const DictConstIteratorImpl *p = dynamic_cast(&other); return p != NULL && p->_iter == _iter; } template inline bool MagicBasicDict::DictConstIteratorImpl::equal_to( const IDictIteratorImpl& other ) const { const DictIteratorImpl *p = dynamic_cast(&other); return p != NULL && _iter == p->_iter; } template inline bool MagicBasicDict::DictConstIteratorImpl::equal_to( const IDictConstIteratorImpl& other ) const { const DictConstIteratorImpl *p = dynamic_cast(&other); return p != NULL && _iter == p->_iter; } /** * @brief ÐÞÕûÒ»ÏÂstd::mapµÄ½Ó¿Ú£¬Ìṩһ¸ö½ÓÊÜallocatorµÄ¹¹Ô캯Êý * * µäÐ͵Äadapterģʽ * ¸Ãadapter»¹ÄÜʹÆäÔËÐÐʱÃû×ÖûÓÐÕâôÏÅÈË:-P * */ templateclass Alloc> class __MagicStdMapAdapter: public std::map, Alloc > >{ public: typedef std::map, Alloc > > base_type; typedef typename base_type::allocator_type allocator_type; typedef typename base_type::iterator iterator; typedef typename base_type::const_iterator const_iterator; /** * @brief ĬÈϹ¹Ô캯Êý * * @see * @author chenxm * @date 2009/04/08 11:22:53 **/ __MagicStdMapAdapter() :base_type(){} /** * @brief ʹÓÃallocator³õʼ»¯µÄ¹¹Ô캯Êý * * @param [in] alloc_ : const allocator_type& * @return explicit * @retval * @see * @author chenxm * @date 2009/04/08 11:23:05 **/ explicit __MagicStdMapAdapter( const allocator_type& alloc_ ) :base_type(std::less(), alloc_ ){} /** * @brief ʹÓÃinit_capacityÓëallocator³õʼ»¯µÄ¹¹Ô캯Êý * * ¶ÔÓÚstd::map£¬init_capacityûÓÐÒâÒ壬ֱ½ÓºöÂÔ * @param [in] init_capacity : size_t * @param [in] alloc_ : const allocator_type& * @return explicit * @retval * @see * @author chenxm * @date 2009/04/08 12:02:53 **/ explicit __MagicStdMapAdapter( size_t /*init_capacity*/, const allocator_type& alloc_ ) :base_type(std::less(), alloc_ ){} //inherit everything else }; /** * @brief ÐÞÕûÒ»ÏÂ__gnu_cxx::hash_mapµÄ½Ó¿Ú£¬Ìṩһ¸ö½ÓÊÜallocatorµÄ¹¹Ô캯Êý * * µäÐ͵Äadapterģʽ * ¸Ãadapter»¹ÄÜʹÆäÔËÐÐʱÃû×ÖûÓÐÕâôÏÅÈË:-P * */ templateclass Alloc> #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 class __MagicGnuHashMapAdapter: public std::tr1::unordered_map< IVar::string_type, bsl::var::MagicRef, ::__gnu_cxx::hash, std::equal_to, Alloc > { #elif __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 class __MagicGnuHashMapAdapter: public std::unordered_map< IVar::string_type, bsl::var::MagicRef, __gnu_cxx::hash, std::equal_to, Alloc > { #else class __MagicGnuHashMapAdapter: public __gnu_cxx::hash_map< IVar::string_type, bsl::var::MagicRef, ::__gnu_cxx::hash, std::equal_to, Alloc > { #endif public: #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 typedef std::tr1::unordered_map< IVar::string_type, bsl::var::MagicRef, ::__gnu_cxx::hash, std::equal_to, Alloc > base_type; #elif __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 typedef std::unordered_map< IVar::string_type, bsl::var::MagicRef, __gnu_cxx::hash, std::equal_to, Alloc > base_type; #else typedef __gnu_cxx::hash_map< IVar::string_type, bsl::var::MagicRef, ::__gnu_cxx::hash, std::equal_to, Alloc > base_type; #endif typedef typename base_type::allocator_type allocator_type; typedef typename base_type::iterator iterator; typedef typename base_type::const_iterator const_iterator; /** * @brief ĬÈϹ¹Ô캯Êý * * @see * @author chenxm * @date 2009/04/08 11:22:15 **/ __MagicGnuHashMapAdapter() :base_type(){} /** * @brief ʹÓÃallocator³õʼ»¯µÄ¹¹Ô캯Êý * * 100ÊÇ__gnu_cxx::hash_mapʹÓõÄĬÈÏÈÝÁ¿Öµ * @param [in] alloc_ : const allocator_type& * @return explicit * @retval * @see * @author chenxm * @date 2009/04/08 11:22:27 **/ explicit __MagicGnuHashMapAdapter( const allocator_type& alloc_ ) :base_type(100, typename base_type::hasher(), typename base_type::key_equal(), alloc_ ){} /** * @brief ʹÓÃinit_capacityÓëallocator³õʼ»¯µÄ¹¹Ô캯Êý * * @param [in] init_capacity : size_t * @param [in] alloc_ : const allocator_type& * @return explicit * @retval * @see * @author chenxm * @date 2009/04/08 11:58:52 **/ explicit __MagicGnuHashMapAdapter( size_t init_capacity, const allocator_type& alloc_ ) :base_type(init_capacity, typename base_type::hasher(), typename base_type::key_equal(), alloc_ ){} //inherit everything else }; }} //namespace bsl::var #endif //__BSL_VAR_DICT_H__ /* vim: set ts=4 sw=4 sts=4 tw=100 */