text.hpp

説明を見る。
00001 /*
00002  *  TOPPERS/FDMP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Function Distributed Multiprocessor Kernel
00005  *
00006  *  Copyright (C) 2005 by Takagi Nobuhisa
00007  * 
00008  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
00009  *  によって公表されている GNU General Public License の Version 2 に記
00010  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00011  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00012  *  利用と呼ぶ)することを無償で許諾する.
00013  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00014  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00015  *      スコード中に含まれていること.
00016  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00017  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00018  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00019  *      の無保証規定を掲載すること.
00020  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00021  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00022  *      と.
00023  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00024  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00025  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00026  *        報告すること.
00027  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00028  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00029  * 
00030  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00031  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00032  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00033  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00034  * 
00035  */
00036 
00046 #ifndef TOPPERS_TEXT_HPP_
00047 #define TOPPERS_TEXT_HPP_
00048 
00049 #include "toppers/text_line.hpp"
00050 #include "toppers/misc.hpp"
00051 #include <iterator>
00052 #include <vector>
00053 #include <boost/iterator/iterator_facade.hpp>
00054 #include <boost/format.hpp>
00055 
00056 namespace toppers
00057 {
00058 
00069   template
00070   <
00071     template <typename, class> class Container,
00072     typename CharT,
00073     class Traits = std::char_traits<CharT>,
00074     class Allocator = std::allocator<CharT>
00075   >
00076   class basic_text
00077   {
00078   public:
00079     typedef basic_text<Container, CharT, Traits, Allocator> self_t;
00080     typedef std::basic_string<CharT, Traits, Allocator> string_type;
00081     typedef ::toppers::text_line line_type;
00082     typedef basic_line_buf<CharT, Traits, Allocator> line_buf;
00083 
00084     //  以下は一般的なコンテナとの互換のための型定義
00086     typedef CharT value_type;
00087     typedef Container<line_buf, std::allocator<line_buf> > container;
00088     typedef value_type& reference;
00089     typedef const value_type& const_reference;
00090     typedef value_type* pointer;
00091     typedef const value_type* const_pointer;
00092     typedef Allocator allocator_type;
00093     typedef typename Allocator::difference_type difference_type;
00094     typedef typename Allocator::size_type size_type;
00095 
00100     class const_iterator : public boost::iterator_facade<const_iterator, CharT, boost::random_access_traversal_tag, const CharT&>
00101     {
00102       friend class boost::iterator_core_access;
00103     public:
00104       typedef boost::iterator_facade<const_iterator, CharT, boost::random_access_traversal_tag, const CharT&> base_t;
00105       typedef typename container::const_iterator row_iterator;
00106       typedef typename base_t::value_type value_type;
00107       typedef typename base_t::reference reference;
00108       typedef typename base_t::pointer pointer;
00109       typedef typename base_t::difference_type difference_type;
00110 
00111       const_iterator() : row_(), col_( 0 ) {}
00112       const_iterator( row_iterator row, size_type col ) : row_( row ), col_( col ) {}
00113       const line_type& line() const { return row_->line_; }
00114       const row_iterator& get_row() const { return row_; }
00115       size_type get_col() const { return col_; }
00116     protected:
00117       reference dereference() const { return row_->buf_[col_]; }
00118       bool equal( const const_iterator& rhs ) const { return row_ == rhs.row_ && col_ == rhs.col_; }
00119       void increment() { if ( ++col_ == row_->buf_.size() ) { col_ = 0; ++row_; } }
00120       void decrement() { if ( col_ == 0 ) col_ = ( --row_ )->buf_.size(); --col_; }
00121       void advance( difference_type n )
00122       {
00123         typename container::const_iterator row = row_;
00124         size_type col = col_;
00125         while ( col + n > row->buf_.size() )
00126         {
00127           n -= row->buf_.size() - col;
00128           ++row;
00129           col = 0;
00130         }
00131         col += n;
00132         if ( col == row->buf_.size() )
00133         {
00134           col = 0;
00135           ++row;
00136         }
00137         row_ = row;
00138         col_ = col;
00139       }
00140       difference_type distance_to( const const_iterator& rhs ) const
00141       {
00142         difference_type n;
00143         typename container::const_iterator row = row_;
00144         if ( rhs.row_ < row_ )
00145         {
00146           n = -static_cast<difference_type>( col_ + ( rhs.row_->buf_.size() - rhs.col_ ) );
00147           while ( --row != rhs.row_ )
00148           {
00149             n -= row->buf_.size();
00150           }
00151         }
00152         else if ( row_ < rhs.row_ )
00153         {
00154           n = col_ + rhs.col_;
00155           while ( ++row != rhs.row_ )
00156           {
00157             n += row->buf_.size();
00158           }
00159         }
00160         else
00161         {
00162           n = static_cast<difference_type>( rhs.col_ ) - static_cast<difference_type>( col_ );
00163         }
00164         return n;
00165       }
00166     private:
00167       typename container::const_iterator row_;
00168       size_type col_;
00169     };
00170 
00175     class iterator : public const_iterator
00176     {
00177     public:
00178       typedef typename container::iterator row_iterator;
00179       typedef typename const_iterator::value_type value_type;
00180       typedef typename const_iterator::reference reference;
00181       typedef typename const_iterator::pointer pointer;
00182       typedef typename const_iterator::difference_type difference_type;
00183 
00184       iterator() {}
00185       explicit iterator( row_iterator row, size_type col = 0 ) : const_iterator( row, col ) {}
00186       value_type& operator*() const { return const_cast<value_type&>( dereference() ); }
00187       iterator& operator++() { increment(); return *this; }
00188       iterator operator++( int ) { iterator t( *this ); increment(); return t; }
00189       iterator& operator--() { decrement(); return *this; }
00190       iterator operator--( int ) { iterator t( *this ); decrement(); return t; }
00191     };
00192 
00193     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00194     typedef std::reverse_iterator<iterator> reverse_iterator;
00195 
00196   public:
00200     basic_text() {}
00201 
00207     basic_text( const const_iterator& first, const const_iterator& last )
00208     {
00209       if ( first != last )
00210       {
00211         init( first, last );
00212       }
00213     }
00214 
00221     template <class ForwardIterator>
00222     basic_text( ForwardIterator first, ForwardIterator last )
00223     {
00224       if ( first != last )
00225       {
00226         init( first, last, append_directive );
00227       }
00228     }
00229 
00242     template <class ForwardIterator, class Directive>
00243     basic_text( ForwardIterator first, ForwardIterator last, Directive directive )
00244     {
00245       if ( first != last )
00246       {
00247         init( first, last, directive );
00248       }
00249     }
00250 
00256     basic_text( std::basic_istream<CharT, Traits>& istr )
00257     {
00258       if ( first != last )
00259       {
00260         init( istr, append_directive );
00261       }
00262     }
00263 
00275     template <class Directive>
00276     basic_text( std::basic_istream<CharT, Traits>& istr, Directive directive )
00277     {
00278       init( istr, directive );
00279     }
00280 
00285     const_iterator begin() const
00286     {
00287       return const_iterator( container_.begin() );
00288     }
00289 
00294     iterator begin()
00295     {
00296       return iterator( container_.begin() );
00297     }
00298 
00303     const_iterator end() const
00304     {
00305       return const_iterator( container_.end() );
00306     }
00307 
00312     iterator end()
00313     {
00314       return iterator( container_.end() );
00315     }
00316 
00321     const_iterator rbegin() const
00322     {
00323       const string_type* pbuf = &container_.back().buf_;
00324       return const_reverse_iterator( container_.rbegin(), pbuf->empty() ? 0 : pbuf->size()-1 );
00325     }
00326 
00331     iterator rbegin()
00332     {
00333       string_type* pbuf = &container_.back().buf_;
00334       return reverse_iterator( container_.rbegin(), pbuf->empty() ? 0 : pbuf->size()-1 );
00335     }
00336 
00341     const_iterator rend() const
00342     {
00343       return const_reverse_iterator( container_.rend(), container_.back().buf_.size()-1 );
00344     }
00345 
00350     iterator rend()
00351     {
00352       return reverse_iterator( container_.rend() );
00353     }
00354 
00359     const_reference front() const
00360     {
00361       return container_.front().buf_[0];
00362     }
00363 
00368     reference front()
00369     {
00370       return container_.front().buf_[0];
00371     }
00372 
00377     const_reference back() const
00378     {
00379       const string_type* pbuf = &container_.back().buf_;
00380       return pbuf_->at( pbuf_->size()-1 );
00381     }
00382 
00387     reference back()
00388     {
00389       string_type* pbuf = &container_.back().buf_;
00390       return pbuf_->at( pbuf_->size()-1 );
00391     }
00392 
00397     const_reference at( size_type pos ) const
00398     {
00399       return container_.front().buf_[pos];
00400     }
00401 
00406     reference at( size_type pos )
00407     {
00408       return container_.front().buf_[pos];
00409     }
00410 
00416     void append( const const_iterator& first, const const_iterator& last )
00417     {
00418       if ( first != last )
00419       {
00420         self_t t( *this );
00421         t.init( first, last );
00422         swap( t );
00423       }
00424     }
00425 
00433     template <class ForwardIterator>
00434     void append( ForwardIterator first, ForwardIterator last )
00435     {
00436       append( first, last, append_directive );
00437     }
00438 
00452     template <class ForwardIterator, class Directive>
00453     void append( ForwardIterator first, ForwardIterator last, Directive directive )
00454     {
00455       if ( first != last )
00456       {
00457         self_t t( *this );
00458         t.init( first, last, directive );
00459         swap( t );
00460       }
00461     }
00462 
00469     void append( std::basic_istream<CharT, Traits>& istr )
00470     {
00471       append( istr, append_directive );
00472     }
00473 
00486     template <class Directive>
00487     void append( std::basic_istream<CharT, Traits>& istr, Directive directive )
00488     {
00489       self_t t( *this );
00490       t.init( istr, directive );
00491       swap( t );
00492     }
00493 
00499     void assign( const const_iterator& first, const const_iterator& last )
00500     {
00501       self_t t( first, last );
00502       swap( t );
00503     }
00504 
00511     template <class ForwardIterator>
00512     void assign( ForwardIterator first, ForwardIterator last )
00513     {
00514       self_t t( first, last, append_directive );
00515       swap( t );
00516     }
00517 
00530     template <class ForwardIterator, class Directive>
00531     void assign( ForwardIterator first, ForwardIterator last, Directive directive )
00532     {
00533       self_t t( first, last, directive );
00534       swap( t );
00535     }
00536 
00543     void assign( std::basic_istream<CharT, Traits>& istr )
00544     {
00545       self_t t( istr, append_directive );
00546       swap( t );
00547     }
00548 
00561     template <class Directive>
00562     void assign( std::basic_istream<CharT, Traits>& istr, Directive directive )
00563     {
00564       self_t t( istr, directive );
00565       swap( t );
00566     }
00567 
00572     void push_back( value_type value )
00573     {
00574       if ( container_.empty() )
00575       {
00576         line_buf buf( initial_line(), string_type( 1, value ) );
00577         container_.push_back( buf );
00578       }
00579       else
00580       {
00581         const string_type* pbuf = &container_.back().buf_;
00582         if ( pbuf_->at( pbuf_->size()-1 ) == widen( '\n' ) )
00583         {
00584           line_buf buf( initial_line(), string_type( 1, value ) );
00585           ++buf.line_.line_;
00586           container_.push_back( buf );
00587         }
00588         else
00589         {
00590           container_.back().buf_ += value;
00591         }
00592       }
00593     }
00594 
00598     void pop_back()
00599     {
00600       if ( container_.empty() )
00601       {
00602         container_.pop_back();
00603       }
00604       else
00605       {
00606         const string_type* pbuf = &container_.back().buf_;
00607         pbuf->resize( pbuf->size()-1 );
00608         if ( container_.back().buf_.empty() )
00609         {
00610           container_.pop_back();
00611         }
00612       }
00613     }
00614 
00619     bool empty() const
00620     {
00621       return container_.empty();
00622     }
00623 
00628     size_type size() const
00629     {
00630       return std::accumulate( container_.begin(), container_.end(), size_type( 0 ), add_line_size );
00631     }
00632 
00637     void swap( self_t& other )
00638     {
00639       container_.swap( other.container_ );
00640       line_.swap( other.line_ );
00641     }
00642 
00646     void clear()
00647     {
00648       container_.clear();
00649     }
00650   private:
00652     void init( const const_iterator& first, const const_iterator& last )
00653     {
00654       line_buf buf( *first.get_row() );
00655       if ( first.get_col() > 0 )
00656       {
00657         buf.buf_ = buf.buf_.substr( first.get_col() );
00658       }
00659       container_.push_back( buf );
00660       ++first;
00661       container_.append( first.get_row(), last.get_row() );
00662       buf = *last.get_row();
00663       buf.buf_ = buf.buf_.substr( 0, last.get_col() );
00664       container_.push_back( buf );
00665     }
00666 
00668     template <class ForwardIterator, class Directive>
00669     void init( ForwardIterator first, ForwardIterator last, Directive directive )
00670     {
00671       line_buf buf( initial_line() );
00672       const value_type nl = widen( '\n' );
00673       for ( ForwardIterator iter = first; iter != last; ++iter )
00674       {
00675         value_type ch = *iter;
00676         buf.buf_ += ch;
00677         if ( ch == nl )
00678         {
00679           directive( container_, buf );
00680           line_ = buf.line_;
00681         }
00682       }
00683       if ( !buf.buf_.empty() )
00684       {
00685         container_.push_back( buf );
00686       }
00687     }
00688 
00690     template <class Directive>
00691     void init( std::basic_istream<CharT, Traits>& istr, Directive directive )
00692     {
00693       line_buf buf( initial_line() );
00694       const value_type nl = widen( '\n' );
00695       while ( istr )
00696       {
00697         value_type ch;
00698         istr.get( ch );
00699         buf.buf_ += ch;
00700         if ( ch == nl )
00701         {
00702           directive( container_, buf );
00703           line_ = buf.line_;
00704         }
00705       }
00706       if ( !buf.buf_.empty() )
00707       {
00708         container_.push_back( buf );
00709       }
00710     }
00711 
00713     const line_type initial_line() const
00714     {
00715       if ( line_.line_ > 0 )
00716       {
00717         return line_;
00718       }
00719       if ( container_.empty() )
00720       {
00721         return line_type( "unknown", 1 );
00722       }
00723       return container_.back().line_;
00724     }
00725 
00727     static value_type widen( char ch )
00728     {
00729       return ::toppers::widen<value_type>( ch );
00730     }
00731 
00733     static size_type add_line_size( size_type value, const line_buf& buf )
00734     {
00735       return value + buf.buf_.size();
00736     }
00737 
00739     static void append_directive( container& cont, line_buf& buf )
00740     {
00741       cont.push_back( buf );
00742       ++buf.line_.line_;
00743       buf.buf_.clear();
00744     }
00745   private:
00746     container container_;
00747     line_type line_;
00748   };
00749 
00750   typedef basic_text<std::vector, char> text;
00751 
00752   inline const text_line& get_text_line( text::const_iterator iter )
00753   {
00754     return iter.line();
00755   }
00756 
00757   inline const text_line& get_text_line( text::iterator iter )
00758   {
00759     return iter.line();
00760   }
00761 
00762 }
00763 
00764 #endif  // ! TOPPERS_TEXT_HPP_

Copyright © 2006 by TAKAGI Nobuhisa.
このページは Wed Apr 12 16:31:57 2006 に Doxygen によって生成されました。