OSDN Git Service

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