/*************************************************************************** * * Copyright (c) 2008 Baidu.com, Inc. All Rights Reserved * $Id: MagicArray.h,v 1.2 2010/04/28 12:45:33 scmpf Exp $ * **************************************************************************/ /** * @file MagicBasicArray.h * @author chenxm(chenxiaoming@baidu.com) * @date 2008/09/24 01:36:18 * @version $Revision: 1.2 $ * @brief * **/ #ifndef __BSL_VAR_MAGIC_ARRAY_H__ #define __BSL_VAR_MAGIC_ARRAY_H__ #include #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" namespace bsl{ namespace var{ //typedefs template class MagicBasicArray; typedef MagicBasicArray > MagicArray; template class MagicBasicArray: public IVar{ public: typedef IVar::string_type string_type; typedef IVar::field_type field_type; typedef allocator_t allocator_type; typedef ArrayIterator array_iterator; typedef ArrayConstIterator array_const_iterator; typedef MagicRef reference_type; public: MagicBasicArray(bsl::ResourcePool& rp) :_array(), _rp(rp) {} MagicBasicArray( const MagicBasicArray& other ) :IVar(other), _array(other._array), _rp(other._rp){} MagicBasicArray& operator = ( const MagicBasicArray& other ){ try{ _array = other._array; }catch(bsl::Exception& e){ e<<"{"<<__PRETTY_FUNCTION__<<"("<(var)); }else if ( var.is_array() ){ size_t var_size = var.size(); try{ _array.resize( var_size, reference_type(_rp) ); }catch(bsl::Exception& e){ throw; }catch(std::exception& e){ throw StdException(e)<= _array.size() ){ return bsl::var::Null::null; } return _array[idx]; } virtual IVar& get( size_t idx, IVar& default_value ) { if ( idx >= _array.size() ){ return default_value; } return _array[idx]; } virtual const IVar& get( size_t idx ) const { if ( idx >= _array.size() ){ return bsl::var::Null::null; } return _array[idx]; } virtual const IVar& get( size_t idx, const IVar& default_value ) const { if ( idx >= _array.size() ){ return default_value; } return _array[idx]; } virtual void set( size_t idx, IVar& value ){ if ( idx >= _array.size() ){ try{ _array.resize(idx + 1, reference_type(_rp) ); }catch(bsl::Exception& e){ throw; }catch(std::exception& e){ throw StdException(e)<= _array.size() || _array[idx].is_null() ){ return false; }else{ _array[idx] = Null::null; return true; } } virtual array_const_iterator array_begin() const { return array_const_iterator( _s_create_const_iterator( &_array, 0 ), _s_clone_const_iterator, _s_destroy_const_iterator ); } virtual array_iterator array_begin() { return array_iterator( _s_create_iterator( &_array, 0 ), _s_clone_iterator, _s_destroy_iterator ); } virtual array_const_iterator array_end() const { return array_const_iterator( _s_create_const_iterator( &_array, _array.size() ), _s_clone_const_iterator, _s_destroy_const_iterator ); } virtual array_iterator array_end() { return array_iterator( _s_create_iterator( &_array, _array.size() ), _s_clone_iterator, _s_destroy_iterator ); } virtual const IVar& operator []( int idx ) const { return this->get( idx >= 0 ? size_t(idx) : size_t(_array.size() + idx) ); } virtual IVar& operator []( int idx ){ if ( idx >= int(_array.size()) ){ try{ _array.resize( idx + 1, reference_type(_rp) ); }catch(bsl::Exception& e){ throw; }catch(std::exception& e){ throw StdException(e)<get( idx >= 0 ? size_t(idx) : size_t(_array.size() + idx) ); } //methods for dict #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( const field_type& name ) { throw bsl::InvalidOperationException()< array_type; class ArrayIteratorImpl; class ArrayConstIteratorImpl; class ArrayIteratorImpl: public IArrayIteratorImpl{ friend class ArrayConstIteratorImpl; public: ArrayIteratorImpl( array_type* p_array, size_t offset ) :_p_array(p_array), _offset(offset){} virtual ~ArrayIteratorImpl() { //pass } virtual size_t key() const { return _offset; } virtual IVar& value() const { return (*_p_array)[_offset]; } virtual void iterate(){ ++ _offset; } virtual void assign( const IArrayIteratorImpl& other ) { const ArrayIteratorImpl *p = dynamic_cast(&other); if ( !p ){ throw bsl::BadCastException()<_p_array; _offset = p->_offset; } virtual bool equal_to( const IArrayIteratorImpl& other ) const; virtual bool equal_to( const IArrayConstIteratorImpl& other ) const; private: array_type *_p_array; size_t _offset; }; class ArrayConstIteratorImpl: public IArrayConstIteratorImpl{ friend class ArrayIteratorImpl; public: ArrayConstIteratorImpl( const array_type* p_array, size_t offset ) :_p_array(p_array), _offset(offset){} virtual ~ArrayConstIteratorImpl() { //pass } virtual size_t key() const { return _offset; } virtual const IVar& value() const { return (*_p_array)[_offset]; } virtual void iterate(){ ++ _offset; } virtual void assign( const IArrayIteratorImpl& other ) { const ArrayIteratorImpl *p = dynamic_cast(&other); if ( !p ){ throw bsl::BadCastException()<_p_array; _offset = p->_offset; } virtual void assign( const IArrayConstIteratorImpl& other ) { const ArrayConstIteratorImpl *p = dynamic_cast(&other); if ( !p ){ throw bsl::BadCastException()<_p_array; _offset = p->_offset; } virtual bool equal_to( const IArrayConstIteratorImpl& other ) const; virtual bool equal_to( const IArrayIteratorImpl& other ) const; private: const array_type * _p_array; size_t _offset; }; static IArrayIteratorImpl * _s_create_iterator( array_type* p_array, size_t offset){ typedef typename allocator_t::template rebind::other impl_alloc_t; IArrayIteratorImpl *p = impl_alloc_t().allocate(1); //throw new(p) ArrayIteratorImpl(p_array, offset ); //nothrow return p; } static IArrayConstIteratorImpl * _s_create_const_iterator( const array_type* p_array, size_t offset){ typedef typename allocator_t::template rebind::other impl_alloc_t; IArrayConstIteratorImpl *p = impl_alloc_t().allocate(1); //throw new(p) ArrayConstIteratorImpl(p_array, offset ); //nothrow return p; } static IArrayIteratorImpl * _s_clone_iterator( const IArrayIteratorImpl *p_other ){ typedef typename allocator_t::template rebind::other impl_alloc_t; const ArrayIteratorImpl *psrc = dynamic_cast(p_other); if ( !psrc ){ throw bsl::BadCastException()<::other impl_alloc_t; const ArrayConstIteratorImpl *psrc = dynamic_cast(p_other); if ( !psrc ){ throw bsl::BadCastException()<::other impl_alloc_t; ArrayIteratorImpl *_p = dynamic_cast(p); if ( _p ){ _p->~ArrayIteratorImpl(); impl_alloc_t().deallocate( _p, 1 ); } } static void _s_destroy_const_iterator( IArrayConstIteratorImpl * p){ typedef typename allocator_t::template rebind::other impl_alloc_t; ArrayConstIteratorImpl *_p = dynamic_cast(p); if ( _p ){ _p->~ArrayConstIteratorImpl(); impl_alloc_t().deallocate( _p, 1 ); } } array_type _array; bsl::ResourcePool& _rp; }; template inline bool MagicBasicArray::ArrayIteratorImpl::equal_to( const IArrayIteratorImpl& other ) const { const ArrayIteratorImpl *p = dynamic_cast(&other); return p != NULL && _p_array == p->_p_array && _offset == p->_offset; } template inline bool MagicBasicArray::ArrayIteratorImpl::equal_to( const IArrayConstIteratorImpl& other ) const { const ArrayConstIteratorImpl *p = dynamic_cast(&other); return p != NULL && _p_array == p->_p_array && _offset == p->_offset; } template inline bool MagicBasicArray::ArrayConstIteratorImpl::equal_to( const IArrayIteratorImpl& other ) const { const ArrayIteratorImpl *p = dynamic_cast(&other); return p != NULL && _p_array == p->_p_array && _offset == p->_offset; } template inline bool MagicBasicArray::ArrayConstIteratorImpl::equal_to( const IArrayConstIteratorImpl& other ) const { const ArrayConstIteratorImpl *p = dynamic_cast(&other); return p != NULL && _p_array == p->_p_array && _offset == p->_offset; } }} //namespace bsl::var #endif //__BSL_VAR_MAGIC_ARRAY_H__ /* vim: set ts=4 sw=4 sts=4 tw=100 */