OSDN Git Service

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