OSDN Git Service

be8ba4f12586d96a2db3879dffdf3f8b1dc8c801
[meshio/meshio.git] / include / text.h
1 #ifndef MESH_IO_TEXT_H_INCLUDED
2 #define MESH_IO_TEXT_H_INCLUDED
3
4 #include "binary.h"
5 #include "la.h"
6 #include "color.h"
7 #include <string>
8 #include <stdlib.h>
9
10 namespace meshio {
11 namespace text {
12
13 /**
14  * \8eQ\8fÆ\83I\83\93\83\8a\81[\82Ì\8aÈ\88Õ\95\8e\9a\97ñ\83N\83\89\83X
15  */
16 class cstr
17 {
18         const char *begin_;
19         const char *end_;
20
21 public:
22         cstr()
23                 : begin_(0), end_(0)
24                 {}
25
26         cstr(const char *begin, const char *end)
27                 : begin_(begin), end_(end)
28                 { }
29
30         bool operator==(const char *rhs)const
31         {
32                 const char *l=begin_;
33                 for(const char *r=rhs; *r; ++r, ++l){
34                         if(l==end_){
35                                 return false;
36                         }
37                         if(*l!=*r){
38                                 return false;
39                         }
40                 }
41                 return l==end_;
42         }
43
44         bool operator!=(const char *rhs)const
45         {
46                 return !(*this==rhs);
47         }
48
49         bool include(char c)const
50         {
51                 for(const char *l=begin_; l!=end_; ++l){
52                         if(*l==c){
53                                 return true;
54                         }
55                 }
56                 return false;
57         }
58
59         bool startswith(const char *rhs)
60         {
61                 const char *r=rhs;
62                 for(const char *l=begin_; l!=end_ && *r!='\0'; ++l, ++r){
63                         if(*l!=*r){
64                                 return false;
65                         }
66                 }
67                 return true;
68         }
69
70         bool empty()const
71         {
72                 return begin_==end_;
73         }
74
75         std::string str()const{ return std::string(begin_, end_); }
76         const char* begin()const{ return begin_; }
77         const char* end()const{ return end_; }
78         std::pair<const char*, const char*> range()const{ 
79                 return std::make_pair(begin_, end_); 
80         }
81
82         template<typename IsTrim>
83                 cstr &trim(IsTrim isTrim){
84                         while(begin_!=end_ && isTrim(*begin_)){
85                                 begin_++;
86                         }
87                         while(end_!=begin_ && isTrim(end_[-1])){
88                                 end_--;
89                         }
90                         return *this;
91                 }
92 };
93 inline std::ostream &operator<<(std::ostream &os, const cstr &rhs)
94 {
95         return os << rhs.str();
96 }
97
98 struct IsCRLF
99 {
100         bool operator()(char byte)const
101         {
102                 switch(byte)
103                 {
104                 case '\n':
105                 case '\r': // fall through
106                         return true;
107
108                 default:
109                         return false;
110                 }
111         }
112 };
113
114 struct IsWhiteSpace
115 {
116         bool operator()(char byte)const
117         {
118                 switch(byte)
119                 {
120                 case ' ':
121                 case '\t': // fall through
122                         return true;
123
124                 default:
125                         return false;
126                 }
127         }
128 };
129
130 struct IsEmpty
131 {
132         bool operator()(cstr line)const
133         {
134                 return line.empty();
135         }
136 };
137
138 template<class DELIMITER=IsCRLF, 
139         class TRIM=IsSpace,
140         class LINESKIP=IsEmptyLine>
141         class LineReader
142 {
143         binary::IReader &reader_;
144         unsigned int lineCount_;
145         std::vector<char> buf_;
146         bool isEnd_;
147
148 public:
149         LineReader(binary::IReader &reader)
150                 : reader_(reader), lineCount_(0), isEnd_(false)
151                 {
152                 }
153
154         cstr getLine()
155         {
156                 while(!isEnd_){
157                         fill_();
158                         cstr line;
159                         if(!buf_.empty()){
160                                 line=trim_();
161                         }
162                         if(LINESKIP()(line)){
163                                 continue;
164                         }
165                         ++lineCount_;
166                         return line;
167                 }
168                 return cstr();
169         }
170
171         unsigned int getLineCount()const
172         {
173                 return lineCount_;
174         }
175
176         bool isEnd()const
177         {
178                 return isEnd_;
179         }
180
181 private:
182         void fill_()
183         {
184                 buf_.clear();
185                 // skip delimeter
186                 while(char byte=reader_.getChar()){
187                         if(DELIMITER()(byte)){
188                                 continue;
189                         }
190                         buf_.push_back(byte);
191                         break;
192                 }
193                 while(char byte=reader_.getChar()){
194                         if(DELIMITER()(byte)){
195                                 break;
196                         }
197                         buf_.push_back(byte);
198                 }
199                 if(buf_.empty()){
200                         isEnd_=true;
201                         return;
202                 }
203         }
204         
205         cstr trim_()
206         {
207                 if(buf_.empty()){
208                         return cstr();
209                 }
210
211                 size_t front=0;
212                 while(true){
213                         if(front>=buf_.size()){
214                                 return cstr();
215                         }
216                         if(!TRIM()(buf_[front])){
217                                 break;
218                         }
219                         ++front;
220                 }
221
222                 size_t back=buf_.size()-1;
223                 for(; back>=0; --back){
224                         if(!TRIM()(buf_[back])){
225                                 break;
226                         }
227                 }
228                 assert(front<=back);
229                 return cstr(&buf_[0]+front, &buf_[0]+back+1);
230         }
231 };
232
233 template<class DELIMITER=IsSpace>
234 class LineSplitter
235 {
236         cstr line_;
237
238 public:
239         LineSplitter(cstr line)
240                 : line_(line)
241                 {
242                 }
243
244         cstr get()
245         {
246                 const char* head=0;
247                 const char* tail=0;
248                 const char *current=line_.begin();
249                 for(; current!=line_.end();){
250                         for(; current!=line_.end(); ++current){
251                                 if(!DELIMITER()(*current)){
252                                         head=current;
253                                         break;
254                                 }
255                         }
256                         if(head){
257                                 for(; current!=line_.end(); ++current){
258                                         if(DELIMITER()(*current)){
259                                                 break;
260                                         }
261                                 }
262                                 tail=current;
263                         }
264                         if(tail){
265                                 break;
266                         }
267                 }
268                 if(!tail){
269                         return cstr();
270                 }
271                 line_=cstr(tail+1, line_.end());
272                 return cstr(head, tail);
273         }
274
275         int getInt()
276         {
277                 return atoi(get().begin());
278         }
279
280         float getFloat()
281         {
282                 return static_cast<float>(atof(get().begin()));
283         }
284
285         la::Vector2 getVector2()
286         {
287                 float x=getFloat();
288                 float y=getFloat();
289                 return la::Vector2(x, y);
290         }
291
292         la::Vector3 getVector3()
293         {
294                 float x=getFloat();
295                 float y=getFloat();
296                 float z=getFloat();
297                 return la::Vector3(x, y, z);
298         }
299
300         la::Vector4 getVector4()
301         {
302                 float x=getFloat();
303                 float y=getFloat();
304                 float z=getFloat();
305                 float w=getFloat();
306                 return la::Vector4(x, y, z, w);
307         }
308
309         color::fRGBA getFloatRGBA()
310         {
311                 float r=getFloat();
312                 float g=getFloat();
313                 float b=getFloat();
314                 float a=getFloat();
315                 return color::fRGBA(r, g, b, a);
316         }
317
318         color::bRGBA getByteRGBA()
319         {
320                 int r=getInt();
321                 int g=getInt();
322                 int b=getInt();
323                 int a=getInt();
324                 return color::bRGBA(r, g, b, a);
325         }
326
327         cstr getQuated()
328         {
329                 const char *begin=line_.begin();
330                 for(; begin!=line_.end(); ++begin){
331                         if(*begin=='"'){
332                                 break;
333                         }
334                 }
335                 begin++;
336                 assert(begin<=line_.end());
337
338                 const char *c=begin+1;
339                 for(; c!=line_.end(); ++c){
340                         if(*c=='"'){
341                                 break;
342                         }
343                 }
344
345                 cstr token=cstr(begin, c);
346
347                 // advance
348                 line_=cstr(c+1, line_.end());
349
350                 return token;
351         }
352 };
353
354 inline void copyStringAndFillZero(char *dst, const std::string &src)
355 {
356         size_t i=0;
357         for(; i<src.size(); ++i)
358         {
359                 dst[i]=src[i];
360                 if(src[i]=='\0'){
361                         break;
362                 }
363         }
364         for(; i<src.size(); ++i)
365         {
366                 dst[i]='\0';
367         }
368 }
369
370 } // namespace text
371 } // namespace meshio
372 #endif // MESH_IO_TEXT_H_INCLUDED