OSDN Git Service

fix for gcc-4.5 on cygwin
[meshio/meshio.git] / src / linereader.h
1 #ifndef LINEREADER_H
2 #define LINEREADER_H
3
4 #include "text.h"
5
6 namespace meshio 
7 {
8   struct IsCRLF
9   {
10     bool operator()(char byte)const
11     {
12       switch(byte)
13       {
14         case '\n':
15         case '\r': // fall through
16           return true;
17
18         default:
19           return false;
20       }
21     }
22   };
23
24   struct IsWhiteSpace
25   {
26     bool operator()(char byte)const
27     {
28       switch(byte)
29       {
30         case ' ':
31         case '\t': // fall through
32           return true;
33
34         default:
35           return false;
36       }
37     }
38   };
39
40   struct IsEmpty
41   {
42     bool operator()(cstr line)const
43     {
44       return line.empty();
45     }
46   };
47
48   template<class DELIMITER=IsCRLF, 
49     class TRIM=IsWhiteSpace,
50     class LINESKIP=IsEmpty>
51       class LineReader
52       {
53         binary::IReader &reader_;
54         unsigned int lineCount_;
55         std::vector<char> buf_;
56         bool isEnd_;
57
58       public:
59         LineReader(binary::IReader &reader)
60           : reader_(reader), lineCount_(0), isEnd_(false)
61         {
62         }
63
64         cstr getLine()
65         {
66           while(!isEnd_){
67             fill_();
68             cstr line;
69             if(!buf_.empty()){
70               line=trim_();
71             }
72             if(LINESKIP()(line)){
73               continue;
74             }
75             ++lineCount_;
76             return line;
77           }
78           return cstr();
79         }
80
81         unsigned int getLineCount()const
82         {
83           return lineCount_;
84         }
85
86         bool isEnd()const
87         {
88           return isEnd_;
89         }
90
91       private:
92         void fill_()
93         {
94           buf_.clear();
95           // skip delimeter
96           while(char byte=reader_.getChar()){
97             if(DELIMITER()(byte)){
98               continue;
99             }
100             buf_.push_back(byte);
101             break;
102           }
103           while(char byte=reader_.getChar()){
104             if(DELIMITER()(byte)){
105               break;
106             }
107             buf_.push_back(byte);
108           }
109           if(buf_.empty()){
110             isEnd_=true;
111             return;
112           }
113         }
114
115         cstr trim_()
116         {
117           if(buf_.empty()){
118             return cstr();
119           }
120
121           size_t front=0;
122           while(true){
123             if(front>=buf_.size()){
124               return cstr();
125             }
126             if(!TRIM()(buf_[front])){
127               break;
128             }
129             ++front;
130           }
131
132           size_t back=buf_.size()-1;
133           for(; back>=0; --back){
134             if(!TRIM()(buf_[back])){
135               break;
136             }
137           }
138           assert(front<=back);
139           return cstr(&buf_[0]+front, &buf_[0]+back+1);
140         }
141       };
142
143   template<class DELIMITER=IsWhiteSpace>
144     class LineSplitter
145     {
146       cstr line_;
147
148     public:
149       LineSplitter(cstr line)
150         : line_(line)
151       {
152       }
153
154       cstr get()
155       {
156         const char* head=0;
157         const char* tail=0;
158         const char *current=line_.begin();
159         for(; current!=line_.end();){
160           for(; current!=line_.end(); ++current){
161             if(!DELIMITER()(*current)){
162               head=current;
163               break;
164             }
165           }
166           if(head){
167             for(; current!=line_.end(); ++current){
168               if(DELIMITER()(*current)){
169                 break;
170               }
171             }
172             tail=current;
173           }
174           if(tail){
175             break;
176           }
177         }
178         if(!tail){
179           return cstr();
180         }
181         line_=cstr(tail+1, line_.end());
182         return cstr(head, tail);
183       }
184
185       int getInt()
186       {
187         return atoi(get().begin());
188       }
189
190       float getFloat()
191       {
192         return static_cast<float>(atof(get().begin()));
193       }
194
195       Vector2 getVector2()
196       {
197         float x=getFloat();
198         float y=getFloat();
199         return Vector2(x, y);
200       }
201
202       Vector3 getVector3()
203       {
204         float x=getFloat();
205         float y=getFloat();
206         float z=getFloat();
207         return Vector3(x, y, z);
208       }
209
210       Vector4 getVector4()
211       {
212         float x=getFloat();
213         float y=getFloat();
214         float z=getFloat();
215         float w=getFloat();
216         return Vector4(x, y, z, w);
217       }
218
219       fRGBA getFloatRGBA()
220       {
221         float r=getFloat();
222         float g=getFloat();
223         float b=getFloat();
224         float a=getFloat();
225         return fRGBA(r, g, b, a);
226       }
227
228       bRGBA getByteRGBA()
229       {
230         int r=getInt();
231         int g=getInt();
232         int b=getInt();
233         int a=getInt();
234         return bRGBA(r, g, b, a);
235       }
236
237       cstr getQuated()
238       {
239         const char *begin=line_.begin();
240         for(; begin!=line_.end(); ++begin){
241           if(*begin=='"'){
242             break;
243           }
244         }
245         begin++;
246         assert(begin<=line_.end());
247
248         const char *c=begin+1;
249         for(; c!=line_.end(); ++c){
250           if(*c=='"'){
251             break;
252           }
253         }
254
255         cstr token=cstr(begin, c);
256
257         // advance
258         line_=cstr(c+1, line_.end());
259
260         return token;
261       }
262     };
263 }
264
265 #endif