source: cfg_itronx+oil_gcc/toppers/text.hpp@ 165

Last change on this file since 165 was 54, checked in by ertl-ishikawa, 12 years ago

cfg+oil対応コンフィギュレータを追加

File size: 24.4 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2005-2008 by TAKAGI Nobuhisa
6 *
7 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 */
37
38/*!
39 * \file toppers/text.hpp
40 * \brief テキストデータ管理に関する宣言定義
41 *
42 * このファイルで定義されるクラス
43 * \code
44 * class basic_text< Container, CharT, Traits, Allocator >;
45 * \endcode
46 */
47#ifndef TOPPERS_TEXT_HPP_
48#define TOPPERS_TEXT_HPP_
49
50#include <algorithm>
51#include <iterator>
52#include <vector>
53#include <numeric>
54#include "toppers/text_line.hpp"
55#include "toppers/misc.hpp"
56#include <boost/utility.hpp>
57#include <boost/iterator/iterator_facade.hpp>
58#include <boost/format.hpp>
59
60namespace toppers
61{
62
63 /*!
64 * \class basic_text text.hpp "toppers/text.hpp"
65 * \brief テキストデータ管理テンプレートクラス
66 *
67 * ファイルから読み込んだテキストデータの管理を行うためのクラスです。
68 * このクラスでは、テキストデータを単なる文字列としてではなく、入力元の
69 * ファイル名と行番号を付加した形で管理します。
70 *
71 * \note このクラスはテキスト編集の用途を想定したものではありません。
72 */
73 template
74 <
75 template < typename, class > class Container,
76 typename CharT,
77 class Traits = std::char_traits< CharT >,
78 class Allocator = std::allocator< CharT >
79 >
80 class basic_text
81 {
82 public:
83 typedef basic_text< Container, CharT, Traits, Allocator > self_t;
84 typedef std::basic_string< CharT, Traits, Allocator > string_type;
85 typedef ::toppers::text_line line_type;
86 typedef basic_line_buf< CharT, Traits, Allocator > line_buf;
87
88 // 以下は一般的なコンテナとの互換のための型定義
89 ////////////////////////////////////////////////////////////////////////////////
90 typedef CharT value_type;
91 typedef Container< line_buf, std::allocator< line_buf > > container;
92 typedef value_type& reference;
93 typedef value_type const& const_reference;
94 typedef value_type* pointer;
95 typedef value_type const* const_pointer;
96 typedef Allocator allocator_type;
97 typedef typename Allocator::difference_type difference_type;
98 typedef typename Allocator::size_type size_type;
99
100 /*!
101 * \class const_iterator text.hpp "toppers/text.hpp"
102 * \brief toppers::basic_text のイテレータ
103 */
104 class const_iterator : public boost::iterator_facade< const_iterator, CharT, boost::random_access_traversal_tag, CharT const& >
105 {
106 friend class boost::iterator_core_access;
107 public:
108 typedef boost::iterator_facade< const_iterator, CharT, boost::random_access_traversal_tag, CharT const& > base_t;
109 typedef typename container::const_iterator row_iterator;
110 typedef typename base_t::value_type value_type;
111 typedef typename base_t::reference reference;
112 typedef typename base_t::pointer pointer;
113 typedef typename base_t::difference_type difference_type;
114
115 const_iterator() : row_(), col_( 0 ) {}
116 const_iterator( row_iterator row, size_type col = 0 ) : row_( row ), col_( col ) {}
117 line_type const& line() const { return row_->line; }
118 row_iterator const& get_row() const { return row_; }
119 size_type get_col() const { return col_; }
120 protected:
121 reference dereference() const { return row_->buf[col_]; }
122 bool equal( const_iterator const& rhs ) const { return row_ == rhs.row_ && col_ == rhs.col_; }
123 void increment() { if ( ++col_ == row_->buf.size() ) { col_ = 0; ++row_; } }
124 void decrement() { if ( col_ == 0 ) col_ = ( --row_ )->buf.size(); --col_; }
125 void advance( difference_type n )
126 {
127 typename container::const_iterator row = row_;
128 difference_type col = static_cast< difference_type >( col_ );
129 if ( n >= 0 )
130 {
131 while ( static_cast< size_type>( col + n ) > row->buf.size() )
132 {
133 n -= row->buf.size() - col;
134 ++row;
135 col = 0;
136 }
137 col += n;
138 if ( col == row->buf.size() )
139 {
140 col = 0;
141 ++row;
142 }
143 }
144 else // n < 0
145 {
146 while ( col + n < -1 )
147 {
148 n += col;
149 --row;
150 col = row->buf.size() - 1;
151 }
152 col += n;
153 if ( col == -1 )
154 {
155 --row;
156 col = row->buf.size() - 1;
157 }
158 }
159 row_ = row;
160 col_ = col;
161 }
162 difference_type distance_to( const_iterator const& rhs ) const
163 {
164 difference_type n;
165 typename container::const_iterator row = row_;
166 if ( rhs.row_ < row_ )
167 {
168 n = -static_cast< difference_type >( col_ + ( rhs.row_->buf.size() - rhs.col_ ) );
169 while ( --row != rhs.row_ )
170 {
171 n -= row->buf.size();
172 }
173 }
174 else if ( row_ < rhs.row_ )
175 {
176 n = col_ + rhs.col_;
177 while ( ++row != rhs.row_ )
178 {
179 n += row->buf.size();
180 }
181 }
182 else
183 {
184 n = static_cast< difference_type >( rhs.col_ ) - static_cast< difference_type >( col_ );
185 }
186 return n;
187 }
188 private:
189 typename container::const_iterator row_;
190 size_type col_;
191 };
192
193 /*!
194 * \class iterator text.hpp "toppers/text.hpp"
195 * \brief toppers::basic_text のイテレータ
196 */
197 class iterator : public const_iterator
198 {
199 public:
200 typedef typename container::iterator row_iterator;
201 typedef typename const_iterator::value_type value_type;
202 typedef typename const_iterator::reference reference;
203 typedef typename const_iterator::pointer pointer;
204 typedef typename const_iterator::difference_type difference_type;
205
206 iterator() {}
207 explicit iterator( row_iterator row, size_type col = 0 ) : const_iterator( row, col ) {}
208 value_type& operator*() const { return const_cast< value_type& >( const_iterator::dereference() ); }
209 iterator& operator++() { const_iterator::increment(); return *this; }
210 iterator operator++( int ) { iterator t( *this ); const_iterator::increment(); return t; }
211 iterator& operator--() { const_iterator::decrement(); return *this; }
212 iterator operator--( int ) { iterator t( *this ); const_iterator::decrement(); return t; }
213 };
214
215 typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
216 typedef std::reverse_iterator< iterator > reverse_iterator;
217
218 public:
219 /*!
220 * \brief デフォルトコンストラクタ
221 */
222 basic_text() {}
223
224 /*!
225 * \brief コンストラクタ
226 * \param first 初期化に用いるデータ列の先頭
227 * \param last 初期化に用いるデータ列の終端+1
228 */
229 basic_text( const_iterator const& first, const_iterator const& last )
230 {
231 if ( first != last )
232 {
233 init( first, last );
234 }
235 }
236
237 /*!
238 * \brief コンストラクタ
239 * \param first 初期化に用いるデータ列の先頭
240 * \param last 初期化に用いるデータ列の終端+1
241 * \note ファイル名は"unknown"になります。
242 */
243 template < class InputIterator >
244 basic_text( InputIterator first, InputIterator last )
245 {
246 if ( first != last )
247 {
248 init( first, last, append_directive );
249 }
250 }
251
252 /*!
253 * \brief コンストラクタ
254 * \param first 初期化に用いるデータ列の先頭
255 * \param last 初期化に用いるデータ列の終端+1
256 * \param directive 1行をコンテナに格納するための処理
257 * \note ファイル名は"unknown"になります。
258 *
259 * directive は void directive( container& cont, line_buf& buf )の形式を
260 * とる関数へのポインタまたはファンクタであることを想定しています。
261 * cont は内部でデータの格納に使用するコンテナ、 buf は1行分の文字
262 * 列とファイル名・行番号を格納したバッファです。
263 */
264 template < class InputIterator, class Directive >
265 basic_text( InputIterator first, InputIterator last, Directive directive )
266 {
267 if ( first != last )
268 {
269 init( first, last, directive );
270 }
271 }
272
273 /*!
274 * \brief コンストラクタ
275 * \param istr 初期化に用いる入力ストリーム
276 * \note ファイル名は"unknown"になります。
277 */
278 basic_text( std::basic_istream< CharT, Traits >& istr )
279 {
280 init( istr, append_directive );
281 }
282
283 /*!
284 * \brief コンストラクタ
285 * \param istr 初期化に用いる入力ストリーム
286 * \param directive 1行をコンテナに格納するための処理
287 * \note ファイル名は"unknown"になります。
288 *
289 * directive は void directive( container& cont, line_buf& buf )の形式を
290 * とる関数へのポインタまたはファンクタであることを想定しています。
291 * cont は内部でデータの格納に使用するコンテナ、 buf は1行分の文字
292 * 列とファイル名・行番号を格納したバッファです。
293 */
294 template < class Directive >
295 basic_text( std::basic_istream< CharT, Traits >& istr, Directive directive )
296 {
297 init( istr, directive );
298 }
299
300 /*!
301 * \brief 先頭位置の取得
302 * \return 先頭文字へのイテレータを返す
303 */
304 const_iterator begin() const
305 {
306 return const_iterator( container_.begin() );
307 }
308
309 /*!
310 * \brief 先頭位置の取得
311 * \return 先頭文字へのイテレータを返す
312 */
313 iterator begin()
314 {
315 return iterator( container_.begin() );
316 }
317
318 /*!
319 * \brief 行数の取得
320 * \param pos 先頭文字からのオフセット
321 * \return posで指定されたオフセットから行数を求め,イテレータを返す
322 */
323 const_iterator line_at(size_type pos) const
324 {
325 // modified by takuya
326 //typedef text::container::const_iterator const_row_iterator;
327 typedef typename container::const_iterator const_row_iterator;
328 const_iterator first( container_.begin() ), last( container_.end() );
329 int count = 0 , buf_size , i;
330 size_type sum = 0;
331
332 while((sum < pos) && (first != last))
333 {
334 const_row_iterator current( first.get_row() );
335 buf_size = current->buf.size();
336 sum += buf_size;
337 i = 0;
338 while(i < buf_size)
339 {
340 i++;
341 first++;
342 }
343 count += 1;
344 }
345
346 if(first < last)
347 {
348 first -= buf_size;
349 return const_iterator(first);
350 }
351 else
352 {
353 return const_iterator( --last );
354 }
355 }
356 /*!
357 * \brief 終端位置+1の取得
358 * \return 終端文字の次要素へのイテレータを返す
359 */
360 const_iterator end() const
361 {
362 return const_iterator( container_.end() );
363 }
364
365 /*!
366 * \brief 終端位置+1の取得
367 * \return 終端文字の次要素へのイテレータを返す
368 */
369 iterator end()
370 {
371 return iterator( container_.end() );
372 }
373
374 /*!
375 * \brief 逆順先頭位置の取得
376 * \return 逆順先頭文字への逆イテレータを返す
377 */
378 const_reverse_iterator rbegin() const
379 {
380 string_type const* pbuf = &container_.back().buf;
381 return const_reverse_iterator( container_.rbegin() + pbuf->empty() ? 0 : pbuf->size()-1 );
382 }
383
384 /*!
385 * \brief 逆順先頭位置の取得
386 * \return 逆順先頭文字への逆イテレータを返す
387 */
388 reverse_iterator rbegin()
389 {
390 string_type* pbuf = &container_.back().buf;
391 return reverse_iterator( container_.rbegin() + pbuf->empty() ? 0 : pbuf->size()-1 );
392 }
393
394 /*!
395 * \brief 逆順終端位置+1の取得
396 * \return 逆順終端文字の次要素への逆イテレータを返す
397 */
398 const_reverse_iterator rend() const
399 {
400 return const_reverse_iterator( container_.rend() );
401 }
402
403 /*!
404 * \brief 逆順終端位置+1の取得
405 * \return 逆順終端文字の次要素への逆イテレータを返す
406 */
407 reverse_iterator rend()
408 {
409 return reverse_iterator( container_.rend() );
410 }
411
412 /*!
413 * \brief 先頭文字の参照
414 * \return 先頭文字への参照を返す
415 */
416 const_reference front() const
417 {
418 return container_.front().buf[0];
419 }
420
421 /*!
422 * \brief 先頭文字の参照
423 * \return 先頭文字への参照を返す
424 */
425 reference front()
426 {
427 return container_.front().buf[0];
428 }
429
430 /*!
431 * \brief 終端文字の参照
432 * \return 終端文字への参照を返す
433 */
434 const_reference back() const
435 {
436 string_type const* pbuf = &container_.back().buf;
437 return pbuf->at( pbuf->size()-1 );
438 }
439
440 /*!
441 * \brief 終端文字の参照
442 * \return 終端文字への参照を返す
443 */
444 reference back()
445 {
446 string_type* pbuf = &container_.back().buf;
447 return pbuf->at( pbuf->size()-1 );
448 }
449
450 /*!
451 * \brief 指定位置の文字の参照
452 * \return 指定位置の文字への参照を返す
453 */
454 const_reference at( size_type pos ) const
455 {
456 return container_.front().buf[pos];
457 }
458
459 /*!
460 * \brief 指定位置の文字の参照
461 * \return 指定位置の文字への参照を返す
462 */
463 reference at( size_type pos )
464 {
465 return container_.front().buf[pos];
466 }
467
468 /*!
469 * \brief 指定範囲のテキストデータを追加
470 * \param first 追加に用いるデータ列の先頭
471 * \param last 追加に用いるデータ列の終端+1
472 */
473 void append( const_iterator const& first, const_iterator const& last )
474 {
475 if ( first != last )
476 {
477 self_t t( *this );
478 t.init( first, last );
479 swap( t );
480 }
481 }
482
483 /*!
484 * \brief 指定範囲のテキストデータを追加
485 * \param first 追加に用いるデータ列の先頭
486 * \param last 追加に用いるデータ列の終端+1
487 * \note ファイル名と行番号は追加先の終端のものを継続します。
488 * 追加先にデータがない場合は"unknown"になります。
489 */
490 template < class InputIterator >
491 void append( InputIterator first, InputIterator last )
492 {
493 append( first, last, append_directive );
494 }
495
496 /*!
497 * \brief 指定範囲のテキストデータを追加
498 * \param first 追加に用いるデータ列の先頭
499 * \param last 追加に用いるデータ列の終端+1
500 * \param directive 1行をコンテナに格納するための処理
501 * \note ファイル名と行番号は追加先の終端のものを継続します。
502 * 追加先にデータがない場合は"unknown"になります。
503 *
504 * directive は void directive( container& cont, line_buf& buf )の形式を
505 * とる関数へのポインタまたはファンクタであることを想定しています。
506 * cont は内部でデータの格納に使用するコンテナ、 buf は1行分の文字
507 * 列とファイル名・行番号を格納したバッファです。
508 */
509 template < class InputIterator, class Directive >
510 void append( InputIterator first, InputIterator last, Directive directive )
511 {
512 if ( first != last )
513 {
514 self_t t( *this );
515 t.init( first, last, directive );
516 swap( t );
517 }
518 }
519
520 /*!
521 * \brief 指定範囲のテキストデータを追加
522 * \param istr 追加に用いる入力ストリーム
523 * \note ファイル名と行番号は追加先の終端のものを継続します。
524 * 追加先にデータがない場合は"unknown"になります。
525 */
526 void append( std::basic_istream< CharT, Traits >& istr )
527 {
528 append( istr, append_directive );
529 }
530
531 /*!
532 * \brief 指定範囲のテキストデータを追加
533 * \param istr 追加に用いる入力ストリーム
534 * \param directive 1行をコンテナに格納するための処理
535 * \note ファイル名と行番号は追加先の終端のものを継続します。
536 * 追加先にデータがない場合は"unknown"になります。
537 *
538 * directive は void directive( container& cont, line_buf& buf )の形式を
539 * とる関数へのポインタまたはファンクタであることを想定しています。
540 * cont は内部でデータの格納に使用するコンテナ、 buf は1行分の文字
541 * 列とファイル名・行番号を格納したバッファです。
542 */
543 template < class Directive >
544 void append( std::basic_istream< CharT, Traits >& istr, Directive directive )
545 {
546 self_t t( *this );
547 t.init( istr, directive );
548 swap( t );
549 }
550
551 /*!
552 * \brief 指定範囲のテキストデータを代入
553 * \param first 代入に用いるデータ列の先頭
554 * \param last 代入に用いるデータ列の終端+1
555 */
556 void assign( const_iterator const& first, const_iterator const& last )
557 {
558 self_t t( first, last );
559 swap( t );
560 }
561
562 /*!
563 * \brief 指定範囲のテキストデータを代入
564 * \param first 代入に用いるデータ列の先頭
565 * \param last 代入に用いるデータ列の終端+1
566 * \note ファイル名は"unknown"になります。
567 */
568 template < class InputIterator >
569 void assign( InputIterator first, InputIterator last )
570 {
571 self_t t( first, last, append_directive );
572 swap( t );
573 }
574
575 /*!
576 * \brief 指定範囲のテキストデータを代入
577 * \param first 代入に用いるデータ列の先頭
578 * \param last 代入に用いるデータ列の終端+1
579 * \param directive 1行をコンテナに格納するための処理
580 * \note ファイル名は"unknown"になります。
581 *
582 * directive は void directive( container& cont, line_buf& buf )の形式を
583 * とる関数へのポインタまたはファンクタであることを想定しています。
584 * cont は内部でデータの格納に使用するコンテナ、 buf は1行分の文字
585 * 列とファイル名・行番号を格納したバッファです。
586 */
587 template < class InputIterator, class Directive >
588 void assign( InputIterator first, InputIterator last, Directive directive )
589 {
590 self_t t( first, last, directive );
591 swap( t );
592 }
593
594 /*!
595 * \brief 指定範囲のテキストデータを代入
596 * \param istr 代入に用いる入力ストリーム
597 * \note ファイル名と行番号は代入先の終端のものを継続します。
598 * 追加先にデータがない場合は"unknown"になります。
599 */
600 void assign( std::basic_istream< CharT, Traits >& istr )
601 {
602 self_t t( istr, append_directive );
603 swap( t );
604 }
605
606 /*!
607 * \brief 指定範囲のテキストデータを代入
608 * \param istr 代入に用いる入力ストリーム
609 * \param directive 1行をコンテナに格納するための処理
610 * \note ファイル名と行番号は代入先の終端のものを継続します。
611 * 追加先にデータがない場合は"unknown"になります。
612 *
613 * directive は void directive( container& cont, line_buf& buf )の形式を
614 * とる関数へのポインタまたはファンクタであることを想定しています。
615 * cont は内部でデータの格納に使用するコンテナ、 buf は1行分の文字
616 * 列とファイル名・行番号を格納したバッファです。
617 */
618 template < class Directive >
619 void assign( std::basic_istream< CharT, Traits >& istr, Directive directive )
620 {
621 self_t t( istr, directive );
622 swap( t );
623 }
624
625 /*!
626 * \brief 終端に文字を追加
627 * \param value 追加する文字
628 */
629 void push_back( value_type value )
630 {
631 if ( container_.empty() || container_.back().line.file != line_.file )
632 {
633 line_buf buf( initial_line(), string_type( 1, value ) );
634 container_.push_back( buf );
635 }
636 else
637 {
638 string_type const* pbuf = &container_.back().buf;
639 if ( pbuf->at( pbuf->size()-1 ) == widen( '\n' ) )
640 {
641 ++line_.line;
642 line_buf buf( initial_line(), string_type( 1, value ) );
643 container_.push_back( buf );
644 }
645 else
646 {
647 container_.back().buf += value;
648 }
649 }
650 }
651
652 /*!
653 * \brief 終端から文字を削除
654 */
655 void pop_back()
656 {
657 if ( container_.empty() )
658 {
659 container_.pop_back();
660 }
661 else
662 {
663 string_type const* pbuf = &container_.back().buf;
664 pbuf->resize( pbuf->size()-1 );
665 if ( container_.back().buf.empty() )
666 {
667 container_.pop_back();
668 }
669 }
670 }
671
672 /*!
673 * \brief コンテナが空かどうかの判別
674 * \return 空の場合は true を返す
675 */
676 bool empty() const
677 {
678 return container_.empty();
679 }
680
681 /*!
682 * \brief コンテナのサイズ
683 * \return コンテナに含まれている文字数を返す
684 */
685 size_type size() const
686 {
687 return std::accumulate( container_.begin(), container_.end(), size_type( 0 ), add_line_size );
688 }
689
690 /*!
691 * \brief コンテナの交換
692 * \param other 交換対象となるコンテナ
693 */
694 void swap( self_t& other )
695 {
696 container_.swap( other.container_ );
697 line_.swap( other.line_ );
698 }
699
700 /*!
701 * \brief コンテナのクリア
702 */
703 void clear()
704 {
705 container_.clear();
706 line_.file.clear();
707 line_.line = 0;
708 }
709
710 void set_line( std::string const& file, long line )
711 {
712 line_.file = file;
713 line_.line = line;
714 }
715
716 line_type get_line() const
717 {
718 return line_;
719 }
720 private:
721 //! 同種のコンテナを入力元とする初期化処理
722 void init( const_iterator const& first, const_iterator const& last )
723 {
724 line_buf buf( *first.get_row() );
725 if ( first.get_col() > 0 )
726 {
727 buf.buf = buf.buf.substr( first.get_col() );
728 }
729 container_.push_back( buf );
730 std::copy( boost::next( first ).get_row(), last.get_row(), std::back_inserter( container_ ) );
731 buf = *last.get_row();
732 buf.buf = buf.buf.substr( 0, last.get_col() );
733 container_.push_back( buf );
734 line_ = buf.line;
735 }
736
737 //! 異種のコンテナを入力元とする初期化処理
738 template < class InputIterator, class Directive >
739 void init( InputIterator first, InputIterator last, Directive directive )
740 {
741 line_buf buf( initial_line() );
742 value_type const nl = widen( '\n' );
743 for ( InputIterator iter = first; iter != last; ++iter )
744 {
745 value_type ch = *iter;
746 buf.buf += ch;
747 if ( ch == nl )
748 {
749 directive( container_, buf );
750 line_ = buf.line;
751 }
752 }
753 if ( !buf.buf.empty() )
754 {
755 container_.push_back( buf );
756 }
757 line_ = buf.line;
758 }
759
760 //! 入力ストリームを入力元とする初期化処理
761 template < class Directive >
762 void init( std::basic_istream< CharT, Traits >& istr, Directive directive )
763 {
764 line_buf buf( initial_line() );
765 value_type const nl = widen( '\n' );
766 while ( istr )
767 {
768 value_type ch;
769 istr.get( ch );
770 buf.buf += ch;
771 if ( ch == nl )
772 {
773 directive( container_, buf );
774 line_ = buf.line;
775 }
776 }
777 if ( !buf.buf.empty() )
778 {
779 container_.push_back( buf );
780 }
781 line_ = buf.line;
782 }
783
784 //! ファイル名・行番号の初期情報の取得
785 line_type const initial_line() const
786 {
787 if ( line_.line > 0 )
788 {
789 return line_;
790 }
791 if ( container_.empty() )
792 {
793 return line_type( "unknown", 1 );
794 }
795 return container_.back().line;
796 }
797
798 //! シングルバイト文字から別形式の文字型への変換
799 static value_type widen( char ch )
800 {
801 return ::toppers::widen< value_type >( ch );
802 }
803
804 //! size 関数内で使用する累算処理
805 static size_type add_line_size( size_type value, line_buf const& buf )
806 {
807 return value + buf.buf.size();
808 }
809
810 //! Directive のデフォルト処理
811 static void append_directive( container& cont, line_buf& buf )
812 {
813 cont.push_back( buf );
814 ++buf.line.line;
815 buf.buf.clear();
816 }
817 private:
818 container container_;
819 line_type line_;
820 };
821
822 typedef basic_text< std::vector, char > text;
823
824 inline text_line const& get_text_line( text::const_iterator iter )
825 {
826 return iter.line();
827 }
828
829 inline text_line const& get_text_line( text::iterator iter )
830 {
831 return iter.line();
832 }
833
834}
835
836#endif // ! TOPPERS_TEXT_HPP_
Note: See TracBrowser for help on using the repository browser.