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

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

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

File size: 7.3 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2007-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/csv.hpp
40 * \brief CSVファイル入出力に関する宣言定義
41 */
42#ifndef TOPPERS_CSV_HPP_
43#define TOPPERS_CSV_HPP_
44
45#include <stdexcept>
46#include <ostream>
47#include <iterator>
48#include <string>
49#include <vector>
50#include <algorithm>
51#include <boost/utility.hpp>
52#include "toppers/misc.hpp"
53
54namespace toppers
55{
56
57 class csv_error : public std::runtime_error
58 {
59 public:
60 explicit csv_error( long line )
61 : std::runtime_error( "CSV parse error" ), line_( line )
62 {
63 }
64 long line() const
65 {
66 return line_;
67 }
68 private:
69 long line_;
70 };
71
72 /*!
73 * \class basic_csv csv.hpp "toppers/csv.hpp"
74 * \brief CSV ファイルの解析クラス
75 */
76 template < typename CharT, class Traits = std::char_traits< CharT > >
77 class basic_csv
78 {
79 public:
80 typedef std::basic_string< CharT, Traits > string_type;
81 typedef typename std::vector< std::vector< string_type > >::const_iterator const_iterator;
82 typedef typename std::vector< std::vector< string_type > >::const_reference const_reference;
83 typedef typename std::vector< std::vector< string_type > >::value_type value_type;
84 typedef typename std::vector< std::vector< string_type > >::size_type size_type;
85
86 basic_csv();
87 template < class InputIterator >
88 basic_csv( InputIterator first, InputIterator last )
89 {
90 read( first, last );
91 }
92
93 template < class InputIterator >
94 void read( InputIterator first, InputIterator last )
95 {
96 const CharT dquo = widen< CharT >( '\"' );
97 const CharT comma = widen< CharT >( ',' );
98 const CharT lf = widen< CharT >( '\n' );
99 enum
100 {
101 none,
102 non_escaped,
103 escape_opened,
104 escape_closed
105 } state = none;
106 std::vector< std::vector< string_type > > records;
107 std::vector< string_type > record;
108 string_type field;
109 long line = 1;
110
111 record.reserve( 16 );
112 field.reserve( 255 );
113
114 while ( first != last )
115 {
116 CharT ch = *first;
117 if ( ch == dquo )
118 {
119 switch ( state )
120 {
121 case none:
122 state = escape_opened;
123 break;
124 case escape_opened:
125 ++first;
126 ch = *first;
127 if ( ch == dquo ) // "" だったので、" を追加
128 {
129 field.push_back( dquo );
130 }
131 else // 閉じ "
132 {
133 state = escape_closed;
134 }
135 continue; // ++first をこれ以上実行させない
136 default:
137 throw csv_error( line );
138 break;
139 }
140 }
141 else // ch != dquo
142 {
143 if ( state == escape_opened )
144 {
145 field.push_back( ch );
146 }
147 else
148 {
149 if ( ch == comma || ch == lf )
150 {
151 record.push_back( field );
152 field.clear();
153 state = none;
154 if ( ch == lf ) // 改行(RFC4180 では厳密には CR-LF なければならないが、とりあえず '\n' とする)
155 {
156 records.push_back( record );
157 record.clear();
158 ++line;
159 }
160 }
161 else
162 {
163 field.push_back( ch );
164// CharT const* debug_string = field.c_str();
165 }
166 }
167 }
168 ++first;
169 }
170 records_.swap( records );
171 }
172 template < class OutputIterator >
173 void write( OutputIterator result ) const
174 {
175 const CharT dquo = widen< CharT >( '\"' );
176 const CharT comma = widen< CharT >( ',' );
177 const CharT lf = widen< CharT >( '\n' );
178
179 for ( typename std::vector< std::vector< string_type > >::const_iterator r_iter( records_.begin() ), r_last( records_.end() );
180 r_iter != r_last;
181 ++r_iter )
182 {
183 for ( typename std::vector< string_type >::const_iterator f_iter( r_iter->begin() ), f_last( r_iter->end() );
184 f_iter != f_last;
185 ++f_iter )
186 {
187 std::string field;
188 bool need_escape = false;
189
190 for ( typename string_type::const_iterator s_iter( f_iter->begin() ), s_last( f_iter->end() );
191 s_iter != s_last;
192 ++s_iter )
193 {
194 CharT ch = *s_iter;
195 if ( ch == dquo )
196 {
197 field.push_back( dquo );
198 need_escape = true;
199 }
200 else if ( ch == comma || ch == lf )
201 {
202 need_escape = true;
203 }
204 field.push_back( ch );
205 }
206
207 if ( need_escape )
208 {
209 field = dquo + field + dquo;
210 }
211 result = std::copy( field.begin(), field.end(), result );
212 if ( boost::next( f_iter ) != f_last )
213 {
214 *result++ = comma;
215 }
216 }
217 *result++ = lf;
218 }
219 }
220
221 const_iterator begin() const
222 {
223 return records_.begin();
224 }
225 const_iterator end() const
226 {
227 return records_.end();
228 }
229 const_reference at( size_type pos ) const
230 {
231 return records_.at( pos );
232 }
233 const_reference operator[]( size_type pos ) const
234 {
235 return records_[ pos ];
236 }
237 bool empty() const
238 {
239 return records_.empty();
240 }
241 size_type size() const
242 {
243 return records_.size();
244 }
245 void swap( basic_csv& other )
246 {
247 records_.swap( other.records_ );
248 }
249 private:
250 std::vector< std::vector< string_type > > records_;
251 };
252
253 typedef basic_csv< char > csv;
254 typedef basic_csv< wchar_t > wcsv;
255
256}
257
258#endif // TOPPERS_CSV_HPP_
Note: See TracBrowser for help on using the repository browser.