KiCad PCB EDA Suite
wrlproc.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <iostream>
26 #include <sstream>
27 #include <wx/filename.h>
28 #include <wx/string.h>
29 #include <wx/log.h>
30 #include "wrlproc.h"
31 
32 #define GETLINE \
33  do \
34  { \
35  try \
36  { \
37  char* cp = m_file->ReadLine(); \
38  \
39  if( nullptr == cp ) \
40  { \
41  m_eof = true; \
42  m_buf.clear(); \
43  } \
44  else \
45  { \
46  m_buf = cp; \
47  m_bufpos = 0; \
48  } \
49  \
50  m_fileline = m_file->LineNumber(); \
51  } \
52  catch( ... ) \
53  { \
54  m_error = " * [INFO] input line too long"; \
55  m_eof = true; \
56  m_buf.clear(); \
57  } \
58  } while( 0 )
59 
60 
62 {
64  m_eof = false;
65  m_fileline = 0;
66  m_bufpos = 0;
67  m_file = aLineReader;
68 
69  if( nullptr == aLineReader )
70  {
71  m_eof = true;
72  return;
73  }
74 
75  m_error.clear();
76  wxString tname = m_file->GetSource();
77  m_filename = tname.ToUTF8();
78  wxFileName fn( tname );
79 
80  if( fn.IsRelative() )
81  fn.Normalize();
82 
83  m_filedir = fn.GetPathWithSep().ToUTF8();
84 
85  m_buf.clear();
86  GETLINE;
87 
88  if( m_eof )
89  return;
90 
91  if( m_buf.compare( 0, 16, "#VRML V1.0 ascii" ) == 0 )
92  {
94  // nothing < 0x20, and no:
95  // single or double quote
96  // backslash
97  // curly brace
98  // plus
99  // period
100  m_badchars = "\"'\\{}+.";
101  return;
102  }
103 
104  if( m_buf.compare( 0, 15, "#VRML V2.0 utf8" ) == 0 )
105  {
107  // nothing < 0x20, and no:
108  // single or double quotes
109  // sharp (#)
110  // plus
111  // minus
112  // comma
113  // period
114  // square brackets []
115  // curly braces {}
116  // backslash
117  // NOTE: badchars should include '-' but due to my bad model naming scheme
118  // in the VRML model generator, I have allowed '-'. Other VRML parsers seem to
119  // accept '-'. FreeCAD produces names with '+' in them so '+' has been allowed
120  // as well; '+' is not even valid for VRML1.
121  //m_badchars = "'\"#,.+-[]\\{}";
122  m_badchars = "'\"#,.[]\\{}";
123  return;
124  }
125 
126  m_buf.clear();
128  m_eof = true;
129 
130  m_error = "not a valid VRML file: '";
131  m_error.append( m_filename );
132  m_error.append( 1, '\'' );
133  m_badchars.clear();
134 }
135 
136 
138 {
139 }
140 
141 
143 {
144  m_error.clear();
145 
146  if( !m_file )
147  {
148  m_error = "no open file";
149  return false;
150  }
151 
152  if( m_bufpos >= m_buf.size() )
153  m_buf.clear();
154 
155  if( !m_buf.empty() )
156  return true;
157 
158  if( m_eof )
159  return false;
160 
161  GETLINE;
162 
163  if( m_eof && m_buf.empty() )
164  return false;
165 
166  // strip the EOL characters
167  while( !m_buf.empty() && ( *m_buf.rbegin() == '\r' || *m_buf.rbegin() == '\n' ) )
168  m_buf.erase( --m_buf.end() );
169 
170  if( WRLVERSION::VRML_V1 == m_fileVersion && !m_buf.empty() )
171  {
172  std::string::iterator sS = m_buf.begin();
173  std::string::iterator eS = m_buf.end();
174 
175  while( sS != eS )
176  {
177  if( ( ( *sS ) & 0x80 ) )
178  {
179  m_error = " non-ASCII character sequence in VRML1 file";
180  return false;
181  }
182 
183  ++sS;
184  }
185  }
186 
187  return true;
188 }
189 
190 
191 bool WRLPROC::EatSpace( void )
192 {
193  if( !m_file )
194  {
195  m_error = "no open file";
196  return false;
197  }
198 
199  if( m_bufpos >= m_buf.size() )
200  m_buf.clear();
201 
202 RETRY:
203  while( m_buf.empty() && !m_eof )
204  getRawLine();
205 
206  // buffer may be empty if we have reached EOF or encountered IO errors
207  if( m_buf.empty() )
208  return false;
209 
210  // eliminate leading white space (including control characters and comments)
211  while( m_bufpos < m_buf.size() )
212  {
213  if( m_buf[m_bufpos] > 0x20 )
214  break;
215 
216  ++m_bufpos;
217  }
218 
219  if( m_bufpos == m_buf.size() || '#' == m_buf[m_bufpos] )
220  {
221  // lines consisting entirely of white space are not unusual
222  m_buf.clear();
223  goto RETRY;
224  }
225 
226  return true;
227 }
228 
229 
231 {
232  return m_fileVersion;
233 }
234 
235 
236 const char* WRLPROC::GetParentDir( void )
237 {
238  if( m_filedir.empty() )
239  return nullptr;
240 
241  return m_filedir.c_str();
242 }
243 
244 
245 bool WRLPROC::ReadGlob( std::string& aGlob )
246 {
247  aGlob.clear();
248 
249  if( !m_file )
250  {
251  m_error = "no open file";
252  return false;
253  }
254 
255  while( true )
256  {
257  if( !EatSpace() )
258  return false;
259 
260  // if the text is the start of a comment block, clear the buffer and loop
261  if( '#' == m_buf[m_bufpos] )
262  m_buf.clear();
263  else
264  break;
265  }
266 
267  size_t ssize = m_buf.size();
268 
269  while( m_bufpos < ssize && m_buf[m_bufpos] > 0x20 )
270  {
271  if( ',' == m_buf[m_bufpos] )
272  {
273  // the comma is a special instance of blank space
274  ++m_bufpos;
275  return true;
276  }
277 
278  if( '{' == m_buf[m_bufpos] || '}' == m_buf[m_bufpos]
279  || '[' == m_buf[m_bufpos] || ']' == m_buf[m_bufpos] )
280  return true;
281 
282  aGlob.append( 1, m_buf[m_bufpos++] );
283  }
284 
285  return true;
286 }
287 
288 
289 bool WRLPROC::ReadName( std::string& aName )
290 {
291  aName.clear();
292 
293  if( !m_file )
294  {
295  m_error = "no open file";
296  return false;
297  }
298 
299  while( true )
300  {
301  if( !EatSpace() )
302  return false;
303 
304  // if the text is the start of a comment block, clear the buffer and loop
305  if( '#' == m_buf[m_bufpos] )
306  m_buf.clear();
307  else
308  break;
309  }
310 
311  size_t ssize = m_buf.size();
312 
313  while( m_bufpos < ssize && m_buf[m_bufpos] > 0x20 )
314  {
315  if( '[' == m_buf[m_bufpos] || '{' == m_buf[m_bufpos]
316  || ']' == m_buf[m_bufpos] || '}' == m_buf[m_bufpos]
317  || '.' == m_buf[m_bufpos] || '#' == m_buf[m_bufpos]
318  || ',' == m_buf[m_bufpos] )
319  {
320  if( !aName.empty() )
321  {
322  return true;
323  }
324  else
325  {
326  std::ostringstream ostr;
327  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
328  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
329  ostr << " * [INFO] line " << m_fileline << ", column " << m_bufpos;
330  ostr << " -- invalid name";
331  m_error = ostr.str();
332 
333  return false;
334  }
335  }
336 
337  if( m_badchars.find( m_buf[m_bufpos] ) != std::string::npos )
338  {
339  std::ostringstream ostr;
340  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
341  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
342  ostr << " * [INFO] line " << m_fileline << ", column " << m_bufpos;
343  ostr << " -- invalid character in name";
344  m_error = ostr.str();
345 
346  return false;
347  }
348 
349  if( aName.empty() && m_buf[m_bufpos] >= '0' && m_buf[m_bufpos] <= '9' )
350  {
351  std::ostringstream ostr;
352  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
353  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
354  ostr << " * [INFO] line " << m_fileline << ", column " << m_bufpos;
355  ostr << " -- name must not start with a digit";
356  m_error = ostr.str();
357 
358  return false;
359  }
360 
361  aName.append( 1, m_buf[m_bufpos++] );
362  }
363 
364  return true;
365 }
366 
367 
369 {
370  if( !m_file )
371  {
372  m_error = "no open file";
373  return false;
374  }
375 
376  if( !EatSpace() )
377  {
378  std::ostringstream ostr;
379  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
380  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
381  ostr << " * [INFO] " << m_error;
382  m_error = ostr.str();
383 
384  return false;
385  }
386 
387  if( '{' != m_buf[m_bufpos] )
388  {
389  std::ostringstream ostr;
390  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
391  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
392  ostr << " * [INFO] expecting character '{' at line " << m_fileline;
393  ostr << ", column " << m_bufpos;
394  m_error = ostr.str();
395 
396  wxLogTrace( traceVrmlPlugin, "%s\n", m_error.c_str() );
397 
398  return false;
399  }
400 
401  size_t fileline = m_fileline;
402  size_t linepos = m_bufpos;
403 
404  ++m_bufpos;
405  size_t lvl = 1;
406  std::string tmp;
407 
408  while( lvl > 0 )
409  {
410  if( !EatSpace() )
411  {
412  std::ostringstream ostr;
413  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
414  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
415  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
416  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
417  ostr << " * [INFO] " << m_error;
418  m_error = ostr.str();
419 
420  return false;
421  }
422 
423  // comments must be skipped
424  if( '#' == m_buf[m_bufpos] )
425  {
426  m_bufpos = 0;
427  m_buf.clear();
428  continue;
429  }
430 
431  if( '{' == m_buf[m_bufpos] )
432  {
433  ++m_bufpos;
434  ++lvl;
435  continue;
436  }
437 
438  if( '}' == m_buf[m_bufpos] )
439  {
440  ++m_bufpos;
441  --lvl;
442  continue;
443  }
444 
445  // note: if we have a ']' we must skip it and test the next non-blank character;
446  // this ensures that we don't miss a '}' in cases where the braces are not
447  // separated by space. if we had proceeded to ReadGlob() we could have had a problem.
448  if( ']' == m_buf[m_bufpos] || '[' == m_buf[m_bufpos] )
449  {
450  ++m_bufpos;
451  continue;
452  }
453 
454  // strings are handled as a special case since they may contain
455  // control characters and braces
456  if( '"' == m_buf[m_bufpos] )
457  {
458  if( !ReadString( tmp ) )
459  {
460  std::ostringstream ostr;
461  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
462  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
463  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
464  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
465  ostr << " * [INFO] " << m_error;
466  m_error = ostr.str();
467 
468  return false;
469  }
470  }
471 
472  // everything at this point can be read and discarded via ReadGlob()
473  if( !ReadGlob( tmp ) )
474  {
475  std::ostringstream ostr;
476  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
477  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
478  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
479  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
480  ostr << " * [INFO] " << m_error;
481  m_error = ostr.str();
482 
483  return false;
484  }
485  }
486 
487  return true;
488 }
489 
490 
492 {
493  if( !m_file )
494  {
495  m_error = "no open file";
496  return false;
497  }
498 
499  if( !EatSpace() )
500  {
501  std::ostringstream ostr;
502  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
503  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
504  ostr << " * [INFO] " << m_error;
505  m_error = ostr.str();
506 
507  return false;
508  }
509 
510  if( '[' != m_buf[m_bufpos] )
511  {
512  std::ostringstream ostr;
513  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
514  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
515  ostr << " * [INFO] expecting character '[' at line " << m_fileline;
516  ostr << ", column " << m_bufpos;
517  m_error = ostr.str();
518 
519  return false;
520  }
521 
522  size_t fileline = m_fileline;
523  size_t linepos = m_bufpos;
524 
525  ++m_bufpos;
526  size_t lvl = 1;
527  std::string tmp;
528 
529  while( lvl > 0 )
530  {
531  if( !EatSpace() )
532  {
533  std::ostringstream ostr;
534  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
535  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
536  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
537  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
538  ostr << " * [INFO] " << m_error;
539  m_error = ostr.str();
540 
541  return false;
542  }
543 
544  // comments must be skipped
545  if( '#' == m_buf[m_bufpos] )
546  {
547  m_bufpos = 0;
548  m_buf.clear();
549  continue;
550  }
551 
552  if( '[' == m_buf[m_bufpos] )
553  {
554  ++m_bufpos;
555  ++lvl;
556  continue;
557  }
558 
559  if( ']' == m_buf[m_bufpos] )
560  {
561  ++m_bufpos;
562  --lvl;
563  continue;
564  }
565 
566  // note: if we have a '}' we must skip it and test the next non-blank character;
567  // this ensures that we don't miss a ']' in cases where the braces are not
568  // separated by space. if we had proceeded to ReadGlob() we could have had a problem.
569  if( '}' == m_buf[m_bufpos] || '{' == m_buf[m_bufpos] )
570  {
571  ++m_bufpos;
572  continue;
573  }
574 
575  // strings are handled as a special case since they may contain
576  // control characters and braces
577  if( '"' == m_buf[m_bufpos] )
578  {
579  if( !ReadString( tmp ) )
580  {
581  std::ostringstream ostr;
582  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
583  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
584  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
585  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
586  ostr << " * [INFO] " << m_error;
587  m_error = ostr.str();
588 
589  return false;
590  }
591  }
592 
593  // everything at this point can be read and discarded via ReadGlob()
594  if( !ReadGlob( tmp ) )
595  {
596  std::ostringstream ostr;
597  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
598  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
599  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
600  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
601  ostr << " * [INFO] " << m_error;
602  m_error = ostr.str();
603 
604  return false;
605  }
606  }
607 
608  return false;
609 }
610 
611 
612 bool WRLPROC::ReadString( std::string& aSFString )
613 {
614  // In VRML1 a string may be unquoted provided there are no space characters
615  // In VRML2 all strings must be quoted
616  aSFString.clear();
617 
618  if( !m_file )
619  {
620  m_error = "no open file";
621  return false;
622  }
623 
624  // remember the line number in case of errors
625  size_t ifline = m_fileline;
626 
627  while( true )
628  {
629  if( !EatSpace() )
630  {
631  std::ostringstream ostr;
632  ostr << "invalid VRML file; expecting string at line " << ifline <<
633  " but found nothing";
634  m_error = ostr.str();
635 
636  return false;
637  }
638 
639  // if the text is the start of a comment block, clear the buffer and loop
640  if( '#' == m_buf[m_bufpos] )
641  m_buf.clear();
642  else
643  break;
644  }
645 
646  if( WRLVERSION::VRML_V2 == m_fileVersion && '"' != m_buf[m_bufpos] )
647  {
648  m_error = "invalid VRML2 file (string not quoted)";
649  return false;
650  }
651 
652  ifline = m_fileline;
653 
654  if( '"' != m_buf[m_bufpos] )
655  {
656  if( !ReadGlob( aSFString ) )
657  {
658  std::ostringstream ostr;
659  ostr << "invalid VRML1 file at lines " << ifline << "--" << m_fileline;
660 
661  if( !m_error.empty() )
662  ostr << " : " << m_error;
663 
664  m_error = ostr.str();
665 
666  return false;
667  }
668 
669  return true;
670  }
671 
672  bool isesc = false; // true if an escape character was found
673 
674  while( true )
675  {
676  ++m_bufpos;
677 
678  if( m_bufpos >= m_buf.size() )
679  {
680  aSFString.append( 1, '\n' );
681 
682  if( !getRawLine() )
683  {
684  std::ostringstream ostr;
685  ostr << "invalid VRML1 file at lines " << ifline << "--" << m_fileline;
686  ostr << "; could not find end of string\n";
687  m_error = ostr.str();
688 
689  return false;
690  }
691  }
692 
693  if( '\\' == m_buf[m_bufpos] )
694  {
695  if( isesc )
696  {
697  aSFString.append( 1, '\n' );
698  isesc = false;
699  }
700  else
701  {
702  isesc = true;
703  }
704 
705  continue;
706  }
707  else if( '"' == m_buf[m_bufpos] )
708  {
709  if( isesc )
710  aSFString.append( 1, '"' );
711  else
712  break;
713  }
714  else
715  {
716  aSFString.append( 1, m_buf[m_bufpos] );
717  }
718 
719  // ensure that the backslash escape cannot extend beyond the first character
720  isesc = false;
721  }
722 
723  ++m_bufpos;
724 
725  return true;
726 }
727 
728 
729 bool WRLPROC::ReadSFBool( bool& aSFBool )
730 {
731  if( !EatSpace() )
732  return false;
733 
734  size_t fileline = m_fileline;
735  size_t linepos = m_bufpos;
736  std::string tmp;
737 
738  if( !ReadGlob( tmp ) )
739  return false;
740 
741  if( !tmp.compare( "0" ) )
742  {
743  aSFBool = false;
744  }
745  else if( !tmp.compare( "1" ) )
746  {
747  aSFBool = true;
748  }
749  else if( !tmp.compare( "TRUE" ) )
750  {
751  aSFBool = true;
752  }
753  else if( !tmp.compare( "FALSE" ) )
754  {
755  aSFBool = false;
756  }
757  else
758  {
759  std::ostringstream ostr;
760  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
761  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
762  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
763  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
764  ostr << " * [INFO] expected one of 0, 1, TRUE, FALSE but got '" << tmp << "'\n";
765  m_error = ostr.str();
766 
767  return false;
768  }
769 
770  return true;
771 }
772 
773 
775 {
776  if( !m_file )
777  {
778  m_error = "no open file";
779  return false;
780  }
781 
782  size_t fileline = m_fileline;
783  size_t linepos = m_bufpos;
784 
785  if( !ReadSFVec3f( aSFColor ) )
786  return false;
787 
788  if( aSFColor.x < 0.0 || aSFColor.x > 1.0 || aSFColor.y < 0.0 || aSFColor.y > 1.0
789  || aSFColor.z < 0.0 || aSFColor.z > 1.0 )
790  {
791  std::ostringstream ostr;
792  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
793  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
794  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
795  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
796  ostr << " * [INFO] invalid RGB value in color triplet";
797  m_error = ostr.str();
798 
799  return false;
800  }
801 
802  return true;
803 }
804 
805 
806 bool WRLPROC::ReadSFFloat( float& aSFFloat )
807 {
808  if( !m_file )
809  {
810  m_error = "no open file";
811  return false;
812  }
813 
814  aSFFloat = 0.0;
815 
816  size_t fileline = m_fileline;
817  size_t linepos = m_bufpos;
818 
819  while( true )
820  {
821  if( !EatSpace() )
822  return false;
823 
824  // if the text is the start of a comment block, clear the buffer and loop
825  if( '#' == m_buf[m_bufpos] )
826  m_buf.clear();
827  else
828  break;
829  }
830 
831  std::string tmp;
832 
833  if( !ReadGlob( tmp ) )
834  {
835  std::ostringstream ostr;
836  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
837  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
838  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
839  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
840  ostr << " * [INFO] " << m_error;
841  m_error = ostr.str();
842 
843  return false;
844  }
845 
846  std::istringstream istr;
847  istr.str( tmp );
848  istr >> aSFFloat;
849 
850  if( istr.fail() || !istr.eof() )
851  {
852  std::ostringstream ostr;
853  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
854  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
855  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
856  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
857  ostr << " * [INFO] invalid character in SFFloat";
858  m_error = ostr.str();
859 
860  return false;
861  }
862 
863  return true;
864 }
865 
866 
867 bool WRLPROC::ReadSFInt( int& aSFInt32 )
868 {
869  if( !m_file )
870  {
871  m_error = "no open file";
872  return false;
873  }
874 
875  aSFInt32 = 0;
876  size_t fileline = m_fileline;
877  size_t linepos = m_bufpos;
878 
879  while( true )
880  {
881  if( !EatSpace() )
882  return false;
883 
884  // if the text is the start of a comment block, clear the buffer and loop
885  if( '#' == m_buf[m_bufpos] )
886  m_buf.clear();
887  else
888  break;
889  }
890 
891  std::string tmp;
892 
893  if( !ReadGlob( tmp ) )
894  {
895  std::ostringstream ostr;
896  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
897  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
898  ostr << " * [INFO] line " << fileline<< ", char " << linepos << " -- ";
899  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
900  ostr << " * [INFO] " << m_error;
901  m_error = ostr.str();
902 
903  return false;
904  }
905 
906  if( std::string::npos != tmp.find( "0x" ) )
907  {
908  // Rules: "0x" + "0-9, A-F" - VRML is case sensitive but in
909  // this instance we do no enforce case.
910  std::stringstream sstr;
911  sstr << std::hex << tmp;
912  sstr >> aSFInt32;
913  return true;
914  }
915 
916  std::istringstream istr;
917  istr.str( tmp );
918  istr >> aSFInt32;
919 
920  if( istr.fail() || !istr.eof() )
921  {
922  std::ostringstream ostr;
923  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
924  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
925  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
926  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
927  ostr << " * [INFO] invalid character in SFInt";
928  m_error = ostr.str();
929 
930  return false;
931  }
932 
933  return true;
934 }
935 
936 
938 {
939  if( !m_file )
940  {
941  m_error = "no open file";
942  return false;
943  }
944 
945  aSFRotation.x = 0.0;
946  aSFRotation.y = 0.0;
947  aSFRotation.z = 1.0;
948  aSFRotation.w = 0.0;
949 
950  size_t fileline = m_fileline;
951  size_t linepos = m_bufpos;
952 
953  while( true )
954  {
955  if( !EatSpace() )
956  return false;
957 
958  // if the text is the start of a comment block, clear the buffer and loop
959  if( '#' == m_buf[m_bufpos] )
960  m_buf.clear();
961  else
962  break;
963  }
964 
965  std::string tmp;
966  float trot[4];
967 
968  for( int i = 0; i < 4; ++i )
969  {
970  if( !ReadGlob( tmp ) )
971  {
972  std::ostringstream ostr;
973  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
974  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
975  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
976  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
977  ostr << " * [INFO] " << m_error;
978  m_error = ostr.str();
979 
980  return false;
981  }
982 
983  std::istringstream istr;
984  istr.str( tmp );
985  istr >> trot[i];
986 
987  if( istr.fail() || !istr.eof() )
988  {
989  std::ostringstream ostr;
990  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
991  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
992  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
993  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
994  ostr << " * [INFO] invalid character in space delimited quartet";
995  m_error = ostr.str();
996 
997  return false;
998  }
999 
1000  }
1001 
1002  aSFRotation.x = trot[0];
1003  aSFRotation.y = trot[1];
1004  aSFRotation.z = trot[2];
1005  aSFRotation.w = trot[3];
1006 
1007  return true;
1008 }
1009 
1010 
1012 {
1013  if( !m_file )
1014  {
1015  m_error = "no open file";
1016  return false;
1017  }
1018 
1019  aSFVec2f.x = 0.0;
1020  aSFVec2f.y = 0.0;
1021 
1022  size_t fileline = m_fileline;
1023  size_t linepos = m_bufpos;
1024 
1025  while( true )
1026  {
1027  if( !EatSpace() )
1028  return false;
1029 
1030  // if the text is the start of a comment block, clear the buffer and loop
1031  if( '#' == m_buf[m_bufpos] )
1032  m_buf.clear();
1033  else
1034  break;
1035  }
1036 
1037  std::string tmp;
1038 
1039  float tcol[2];
1040 
1041  for( int i = 0; i < 2; ++i )
1042  {
1043  if( !ReadGlob( tmp ) )
1044  {
1045  std::ostringstream ostr;
1046  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1047  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1048  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1049  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1050  ostr << " * [INFO] " << m_error;
1051  m_error = ostr.str();
1052 
1053  return false;
1054  }
1055 
1056  std::istringstream istr;
1057  istr.str( tmp );
1058  istr >> tcol[i];
1059 
1060  if( istr.fail() || !istr.eof() )
1061  {
1062  std::ostringstream ostr;
1063  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1064  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1065  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1066  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1067  ostr << " * [INFO] invalid character in space delimited pair";
1068  m_error = ostr.str();
1069 
1070  return false;
1071  }
1072 
1073  }
1074 
1075  aSFVec2f.x = tcol[0];
1076  aSFVec2f.y = tcol[1];
1077 
1078  return true;
1079 }
1080 
1081 
1083 {
1084  if( !m_file )
1085  {
1086  m_error = "no open file";
1087  return false;
1088  }
1089 
1090  aSFVec3f.x = 0.0;
1091  aSFVec3f.y = 0.0;
1092  aSFVec3f.z = 0.0;
1093 
1094  size_t fileline = m_fileline;
1095  size_t linepos = m_bufpos;
1096 
1097  while( true )
1098  {
1099  if( !EatSpace() )
1100  return false;
1101 
1102  // if the text is the start of a comment block, clear the buffer and loop
1103  if( '#' == m_buf[m_bufpos] )
1104  m_buf.clear();
1105  else
1106  break;
1107  }
1108 
1109  std::string tmp;
1110 
1111  float tcol[3];
1112 
1113  for( int i = 0; i < 3; ++i )
1114  {
1115  if( !ReadGlob( tmp ) )
1116  {
1117  std::ostringstream ostr;
1118  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1119  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1120  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1121  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1122  ostr << " * [INFO] " << m_error;
1123  m_error = ostr.str();
1124 
1125  return false;
1126  }
1127 
1128  // ignore any commas
1129  if( !EatSpace() )
1130  return false;
1131 
1132  if( ',' == m_buf[m_bufpos] )
1133  Pop();
1134 
1135  std::istringstream istr;
1136  istr.str( tmp );
1137  istr >> tcol[i];
1138 
1139  if( istr.fail() || !istr.eof() )
1140  {
1141  std::ostringstream ostr;
1142  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1143  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1144  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1145  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1146  ostr << " * [INFO] invalid character in space delimited triplet";
1147  m_error = ostr.str();
1148 
1149  return false;
1150  }
1151 
1152  }
1153 
1154  aSFVec3f.x = tcol[0];
1155  aSFVec3f.y = tcol[1];
1156  aSFVec3f.z = tcol[2];
1157 
1158  return true;
1159 }
1160 
1161 
1162 bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString )
1163 {
1164  aMFString.clear();
1165  size_t fileline = m_fileline;
1166  size_t linepos = m_bufpos;
1167 
1168  if( !m_file )
1169  {
1170  m_error = "no open file";
1171  return false;
1172  }
1173 
1174  while( true )
1175  {
1176  if( !EatSpace() )
1177  return false;
1178 
1179  // if the text is the start of a comment block, clear the buffer and loop
1180  if( '#' == m_buf[m_bufpos] )
1181  m_buf.clear();
1182  else
1183  break;
1184  }
1185 
1186  std::string lstr;
1187 
1188  if( m_buf[m_bufpos] != '[' )
1189  {
1190  if( !ReadString( lstr ) )
1191  {
1192  std::ostringstream ostr;
1193  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1194  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1195  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1196  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1197  ostr << " * [INFO] " << m_error;
1198  m_error = ostr.str();
1199 
1200  return false;
1201  }
1202 
1203  if( m_bufpos >= m_buf.size() && !EatSpace() )
1204  {
1205  std::ostringstream ostr;
1206  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1207  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1208  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1209  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1210  ostr << " * [INFO] could not check characters after the string";
1211  m_error = ostr.str();
1212 
1213  return false;
1214  }
1215 
1216  if( ',' == m_buf[m_bufpos] )
1217  Pop();
1218 
1219  aMFString.push_back( lstr );
1220  return true;
1221  }
1222 
1223  ++m_bufpos;
1224 
1225  while( true )
1226  {
1227  if( !ReadString( lstr ) )
1228  {
1229  std::ostringstream ostr;
1230  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1231  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1232  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1233  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1234  ostr << " * [INFO] " << m_error;
1235  m_error = ostr.str();
1236 
1237  return false;
1238  }
1239 
1240  if( !EatSpace() )
1241  {
1242  std::ostringstream ostr;
1243  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1244  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1245  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1246  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1247  ostr << " * [INFO] could not check characters after the string";
1248  m_error = ostr.str();
1249 
1250  return false;
1251  }
1252 
1253  if( ',' == m_buf[m_bufpos] )
1254  Pop();
1255 
1256  aMFString.push_back( lstr );
1257 
1258  if( !EatSpace() )
1259  {
1260  std::ostringstream ostr;
1261  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1262  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1263  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1264  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1265  ostr << " * [INFO] problems encountered while reading list";
1266  m_error = ostr.str();
1267 
1268  return false;
1269  }
1270 
1271  if( ']' == m_buf[m_bufpos] )
1272  break;
1273 
1274  }
1275 
1276  ++m_bufpos;
1277  return true;
1278 }
1279 
1280 
1281 bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor )
1282 {
1283  aMFColor.clear();
1284  size_t fileline = m_fileline;
1285  size_t linepos = m_bufpos;
1286 
1287  if( !m_file )
1288  {
1289  m_error = "no open file";
1290  return false;
1291  }
1292 
1293  WRLVEC3F lcolor;
1294 
1295  while( true )
1296  {
1297  if( !EatSpace() )
1298  return false;
1299 
1300  // if the text is the start of a comment block, clear the buffer and loop
1301  if( '#' == m_buf[m_bufpos] )
1302  m_buf.clear();
1303  else
1304  break;
1305  }
1306 
1307  if( m_buf[m_bufpos] != '[' )
1308  {
1309  if( !ReadSFColor( lcolor ) )
1310  {
1311  std::ostringstream ostr;
1312  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1313  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1314  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1315  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1316  ostr << " * [INFO] " << m_error;
1317  m_error = ostr.str();
1318 
1319  return false;
1320  }
1321 
1322  if( !EatSpace() )
1323  {
1324  std::ostringstream ostr;
1325  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1326  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1327  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1328  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1329  ostr << " * [INFO] could not check characters after the string";
1330  m_error = ostr.str();
1331 
1332  return false;
1333  }
1334 
1335  if( ',' == m_buf[m_bufpos] )
1336  Pop();
1337 
1338  aMFColor.push_back( lcolor );
1339  return true;
1340  }
1341 
1342  ++m_bufpos;
1343 
1344  while( true )
1345  {
1346  if( !EatSpace() )
1347  return false;
1348 
1349  if( ']' == m_buf[m_bufpos] )
1350  break;
1351 
1352  if( !ReadSFColor( lcolor ) )
1353  {
1354  std::ostringstream ostr;
1355  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1356  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1357  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1358  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1359  ostr << " * [INFO] " << m_error;
1360  m_error = ostr.str();
1361 
1362  return false;
1363  }
1364 
1365  aMFColor.push_back( lcolor );
1366 
1367  if( !EatSpace() )
1368  {
1369  std::ostringstream ostr;
1370  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1371  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1372  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1373  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1374  ostr << " * [INFO] could not check characters after the string";
1375  m_error = ostr.str();
1376 
1377  return false;
1378  }
1379 
1380  if( ']' == m_buf[m_bufpos] )
1381  break;
1382 
1383  if( ',' == m_buf[m_bufpos] )
1384  Pop();
1385 
1386  }
1387 
1388  ++m_bufpos;
1389  return true;
1390 }
1391 
1392 
1393 bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat )
1394 {
1395  aMFFloat.clear();
1396  size_t fileline = m_fileline;
1397  size_t linepos = m_bufpos;
1398 
1399  if( !m_file )
1400  {
1401  m_error = "no open file";
1402  return false;
1403  }
1404 
1405  float temp;
1406 
1407  while( true )
1408  {
1409  if( !EatSpace() )
1410  return false;
1411 
1412  // if the text is the start of a comment block, clear the buffer and loop
1413  if( '#' == m_buf[m_bufpos] )
1414  m_buf.clear();
1415  else
1416  break;
1417  }
1418 
1419  if( m_buf[m_bufpos] != '[' )
1420  {
1421  if( !ReadSFFloat( temp ) )
1422  {
1423  std::ostringstream ostr;
1424  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1425  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1426  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1427  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1428  ostr << " * [INFO] " << m_error;
1429  m_error = ostr.str();
1430 
1431  return false;
1432  }
1433 
1434  if( !EatSpace() )
1435  {
1436  std::ostringstream ostr;
1437  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1438  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1439  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1440  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1441  ostr << " * [INFO] could not check characters after the string";
1442  m_error = ostr.str();
1443 
1444  return false;
1445  }
1446 
1447  if( ',' == m_buf[m_bufpos] )
1448  Pop();
1449 
1450  aMFFloat.push_back( temp );
1451  return true;
1452  }
1453 
1454  ++m_bufpos;
1455 
1456  while( true )
1457  {
1458  if( !EatSpace() )
1459  return false;
1460 
1461  if( ']' == m_buf[m_bufpos] )
1462  break;
1463 
1464  if( !ReadSFFloat( temp ) )
1465  {
1466  std::ostringstream ostr;
1467  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1468  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1469  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1470  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1471  ostr << " * [INFO] " << m_error;
1472  m_error = ostr.str();
1473 
1474  return false;
1475  }
1476 
1477  aMFFloat.push_back( temp );
1478 
1479  if( !EatSpace() )
1480  {
1481  std::ostringstream ostr;
1482  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1483  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1484  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1485  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1486  ostr << " * [INFO] could not check characters after the string";
1487  m_error = ostr.str();
1488 
1489  return false;
1490  }
1491 
1492  if( ']' == m_buf[m_bufpos] )
1493  break;
1494 
1495  if( ',' == m_buf[m_bufpos] )
1496  Pop();
1497  }
1498 
1499  ++m_bufpos;
1500  return true;
1501 }
1502 
1503 
1504 bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 )
1505 {
1506  aMFInt32.clear();
1507  size_t fileline = m_fileline;
1508  size_t linepos = m_bufpos;
1509 
1510  if( !m_file )
1511  {
1512  m_error = "no open file";
1513  return false;
1514  }
1515 
1516  int temp;
1517 
1518  while( true )
1519  {
1520  if( !EatSpace() )
1521  return false;
1522 
1523  // if the text is the start of a comment block, clear the buffer and loop
1524  if( '#' == m_buf[m_bufpos] )
1525  m_buf.clear();
1526  else
1527  break;
1528  }
1529 
1530  if( m_buf[m_bufpos] != '[' )
1531  {
1532  if( !ReadSFInt( temp ) )
1533  {
1534  std::ostringstream ostr;
1535  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1536  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1537  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1538  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1539  ostr << " * [INFO] " << m_error;
1540  m_error = ostr.str();
1541 
1542  return false;
1543  }
1544 
1545  if( !EatSpace() )
1546  {
1547  std::ostringstream ostr;
1548  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1549  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1550  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1551  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1552  ostr << " * [INFO] could not check characters after the string";
1553  m_error = ostr.str();
1554 
1555  return false;
1556  }
1557 
1558  if( ',' == m_buf[m_bufpos] )
1559  Pop();
1560 
1561  aMFInt32.push_back( temp );
1562  return true;
1563  }
1564 
1565  ++m_bufpos;
1566 
1567  while( true )
1568  {
1569  if( !EatSpace() )
1570  return false;
1571 
1572  if( ']' == m_buf[m_bufpos] )
1573  break;
1574 
1575  if( !ReadSFInt( temp ) )
1576  {
1577  std::ostringstream ostr;
1578  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1579  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1580  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1581  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1582  ostr << " * [INFO] " << m_error;
1583  m_error = ostr.str();
1584 
1585  return false;
1586  }
1587 
1588  aMFInt32.push_back( temp );
1589 
1590  if( !EatSpace() )
1591  {
1592  std::ostringstream ostr;
1593  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1594  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1595  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1596  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1597  ostr << " * [INFO] could not check characters after the string";
1598  m_error = ostr.str();
1599 
1600  return false;
1601  }
1602 
1603  if( ']' == m_buf[m_bufpos] )
1604  break;
1605 
1606  if( ',' == m_buf[m_bufpos] )
1607  Pop();
1608 
1609  }
1610 
1611  ++m_bufpos;
1612  return true;
1613 }
1614 
1615 
1616 bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation )
1617 {
1618  aMFRotation.clear();
1619  size_t fileline = m_fileline;
1620  size_t linepos = m_bufpos;
1621 
1622  if( !m_file )
1623  {
1624  m_error = "no open file";
1625  return false;
1626  }
1627 
1628  WRLROTATION lrot;
1629 
1630  while( true )
1631  {
1632  if( !EatSpace() )
1633  return false;
1634 
1635  // if the text is the start of a comment block, clear the buffer and loop
1636  if( '#' == m_buf[m_bufpos] )
1637  m_buf.clear();
1638  else
1639  break;
1640  }
1641 
1642  if( m_buf[m_bufpos] != '[' )
1643  {
1644  if( !ReadSFRotation( lrot ) )
1645  {
1646  std::ostringstream ostr;
1647  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1648  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1649  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1650  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1651  ostr << " * [INFO] " << m_error;
1652  m_error = ostr.str();
1653 
1654  return false;
1655  }
1656 
1657  if( !EatSpace() )
1658  {
1659  std::ostringstream ostr;
1660  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1661  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1662  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1663  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1664  ostr << " * [INFO] could not check characters after the string";
1665  m_error = ostr.str();
1666 
1667  return false;
1668  }
1669 
1670  if( ',' == m_buf[m_bufpos] )
1671  Pop();
1672 
1673  aMFRotation.push_back( lrot );
1674  return true;
1675  }
1676 
1677  ++m_bufpos;
1678 
1679  while( true )
1680  {
1681  if( !EatSpace() )
1682  return false;
1683 
1684  if( ']' == m_buf[m_bufpos] )
1685  break;
1686 
1687  if( !ReadSFRotation( lrot ) )
1688  {
1689  std::ostringstream ostr;
1690  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1691  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1692  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1693  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1694  ostr << " * [INFO] " << m_error;
1695  m_error = ostr.str();
1696 
1697  return false;
1698  }
1699 
1700  aMFRotation.push_back( lrot );
1701 
1702  if( !EatSpace() )
1703  {
1704  std::ostringstream ostr;
1705  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1706  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1707  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1708  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1709  ostr << " * [INFO] could not check characters after the string";
1710  m_error = ostr.str();
1711 
1712  return false;
1713  }
1714 
1715  if( ']' == m_buf[m_bufpos] )
1716  break;
1717 
1718  if( ',' == m_buf[m_bufpos] )
1719  Pop();
1720 
1721  }
1722 
1723  ++m_bufpos;
1724  return true;
1725 }
1726 
1727 
1728 bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f )
1729 {
1730  aMFVec2f.clear();
1731  size_t fileline = m_fileline;
1732  size_t linepos = m_bufpos;
1733 
1734  if( !m_file )
1735  {
1736  m_error = "no open file";
1737  return false;
1738  }
1739 
1740  WRLVEC2F lvec2f;
1741 
1742  while( true )
1743  {
1744  if( !EatSpace() )
1745  return false;
1746 
1747  // if the text is the start of a comment block, clear the buffer and loop
1748  if( '#' == m_buf[m_bufpos] )
1749  m_buf.clear();
1750  else
1751  break;
1752  }
1753 
1754  if( m_buf[m_bufpos] != '[' )
1755  {
1756  if( !ReadSFVec2f( lvec2f ) )
1757  {
1758  std::ostringstream ostr;
1759  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1760  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1761  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1762  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1763  ostr << " * [INFO] " << m_error;
1764  m_error = ostr.str();
1765 
1766  return false;
1767  }
1768 
1769  if( !EatSpace() )
1770  {
1771  std::ostringstream ostr;
1772  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1773  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1774  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1775  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1776  ostr << " * [INFO] could not check characters after the string";
1777  m_error = ostr.str();
1778 
1779  return false;
1780  }
1781 
1782  if( ',' == m_buf[m_bufpos] )
1783  Pop();
1784 
1785  aMFVec2f.push_back( lvec2f );
1786  return true;
1787  }
1788 
1789  ++m_bufpos;
1790 
1791  while( true )
1792  {
1793  if( !EatSpace() )
1794  return false;
1795 
1796  if( ']' == m_buf[m_bufpos] )
1797  break;
1798 
1799  if( !ReadSFVec2f( lvec2f ) )
1800  {
1801  std::ostringstream ostr;
1802  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1803  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1804  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1805  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1806  ostr << " * [INFO] " << m_error;
1807  m_error = ostr.str();
1808 
1809  return false;
1810  }
1811 
1812  aMFVec2f.push_back( lvec2f );
1813 
1814  if( !EatSpace() )
1815  {
1816  std::ostringstream ostr;
1817  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1818  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1819  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1820  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1821  ostr << " * [INFO] could not check characters after the string";
1822  m_error = ostr.str();
1823 
1824  return false;
1825  }
1826 
1827  if( ']' == m_buf[m_bufpos] )
1828  break;
1829 
1830  if( ',' == m_buf[m_bufpos] )
1831  Pop();
1832  }
1833 
1834  ++m_bufpos;
1835  return true;
1836 }
1837 
1838 
1839 bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f )
1840 {
1841  aMFVec3f.clear();
1842  size_t fileline = m_fileline;
1843  size_t linepos = m_bufpos;
1844 
1845  if( !m_file )
1846  {
1847  m_error = "no open file";
1848  return false;
1849  }
1850 
1851  WRLVEC3F lvec3f;
1852 
1853  while( true )
1854  {
1855  if( !EatSpace() )
1856  return false;
1857 
1858  // if the text is the start of a comment block, clear the buffer and loop
1859  if( '#' == m_buf[m_bufpos] )
1860  m_buf.clear();
1861  else
1862  break;
1863  }
1864 
1865  if( m_buf[m_bufpos] != '[' )
1866  {
1867  if( !ReadSFVec3f( lvec3f ) )
1868  {
1869  std::ostringstream ostr;
1870  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1871  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1872  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1873  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1874  ostr << " * [INFO] " << m_error;
1875  m_error = ostr.str();
1876 
1877  return false;
1878  }
1879 
1880  if( !EatSpace() )
1881  {
1882  std::ostringstream ostr;
1883  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1884  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1885  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1886  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1887  ostr << " * [INFO] could not check characters after the string";
1888  m_error = ostr.str();
1889 
1890  return false;
1891  }
1892 
1893  if( ',' == m_buf[m_bufpos] )
1894  Pop();
1895 
1896  aMFVec3f.push_back( lvec3f );
1897  return true;
1898  }
1899 
1900  ++m_bufpos;
1901 
1902  while( true )
1903  {
1904  if( !EatSpace() )
1905  return false;
1906 
1907  if( ']' == m_buf[m_bufpos] )
1908  break;
1909 
1910  if( !ReadSFVec3f( lvec3f ) )
1911  {
1912  std::ostringstream ostr;
1913  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1914  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1915  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1916  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1917  ostr << " * [INFO] " << m_error;
1918  m_error = ostr.str();
1919 
1920  return false;
1921  }
1922 
1923  aMFVec3f.push_back( lvec3f );
1924 
1925  if( !EatSpace() )
1926  {
1927  std::ostringstream ostr;
1928  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
1929  ostr << " * [INFO] failed on file '" << m_filename << "'\n";
1930  ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
1931  ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
1932  ostr << " * [INFO] could not check characters after the string";
1933  m_error = ostr.str();
1934 
1935  return false;
1936  }
1937 
1938  if( !EatSpace() )
1939  return false;
1940 
1941  if( ']' == m_buf[m_bufpos] )
1942  break;
1943 
1944  if( ',' == m_buf[m_bufpos] )
1945  Pop();
1946 
1947  }
1948 
1949  ++m_bufpos;
1950  return true;
1951 }
1952 
1953 
1954 bool WRLPROC::eof( void )
1955 {
1956  return m_eof;
1957 }
1958 
1959 
1960 std::string WRLPROC::GetError( void )
1961 {
1962  return m_error;
1963 }
1964 
1965 
1966 bool WRLPROC::GetFilePosData( size_t& line, size_t& column )
1967 {
1968  if( !m_file )
1969  {
1970  line = 0;
1971  column = 0;
1972  return false;
1973  }
1974 
1975  line = m_fileline;
1976  column = m_bufpos;
1977 
1978  return true;
1979 }
1980 
1981 
1982 std::string WRLPROC::GetFilePosition() const
1983 {
1984  std::ostringstream retv;
1985 
1986  if( !m_file )
1987  retv << "no file loaded to provide file position information";
1988  else
1989  retv << "at line " << m_fileline << ", column " << m_bufpos;
1990 
1991  return retv.str();
1992 }
1993 
1994 
1995 std::string WRLPROC::GetFileName( void )
1996 {
1997  if( !m_file )
1998  {
1999  m_error = "no open file";
2000  return "";
2001  }
2002 
2003  return std::string( m_file->GetSource().ToUTF8() );
2004 }
2005 
2006 
2007 char WRLPROC::Peek( void )
2008 {
2009  if( !m_file )
2010  {
2011  std::ostringstream ostr;
2012  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
2013  ostr << " * [BUG] no open file";
2014  m_error = ostr.str();
2015  return '\0';
2016  }
2017 
2018  if( !EatSpace() )
2019  {
2020  if( m_error.empty() )
2021  {
2022  std::ostringstream ostr;
2023  ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
2024  ostr << " * [INFO] failed to read data from file\n";
2025  m_error = ostr.str();
2026  }
2027 
2028  return '\0';
2029  }
2030 
2031  return m_buf[m_bufpos];
2032 }
2033 
2034 
2035 void WRLPROC::Pop( void )
2036 {
2037  if( m_bufpos < m_buf.size() )
2038  ++m_bufpos;
2039 }
bool ReadMFFloat(std::vector< float > &aMFFloat)
Definition: wrlproc.cpp:1393
bool ReadMFVec3f(std::vector< WRLVEC3F > &aMFVec3f)
Definition: wrlproc.cpp:1839
defines the basic input class for VRML
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Definition: richio.h:80
bool ReadSFRotation(WRLROTATION &aSFRotation)
Definition: wrlproc.cpp:937
void Pop(void)
Definition: wrlproc.cpp:2035
glm::vec3 WRLVEC3F
Definition: wrltypes.h:188
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
Definition: richio.h:109
WRLVERSION
Definition: wrltypes.h:43
bool GetFilePosData(size_t &line, size_t &column)
Definition: wrlproc.cpp:1966
bool ReadSFVec3f(WRLVEC3F &aSFVec3f)
Definition: wrlproc.cpp:1082
WRLVERSION GetVRMLType(void)
Definition: wrlproc.cpp:230
unsigned int m_bufpos
Definition: wrlproc.h:112
std::string m_filedir
Definition: wrlproc.h:118
bool ReadMFInt(std::vector< int > &aMFInt32)
Definition: wrlproc.cpp:1504
glm::vec2 WRLVEC2F
Definition: wrltypes.h:187
glm::vec4 WRLROTATION
Definition: wrltypes.h:189
bool ReadMFVec2f(std::vector< WRLVEC2F > &aMFVec2f)
Definition: wrlproc.cpp:1728
bool ReadGlob(std::string &aGlob)
Definition: wrlproc.cpp:245
~WRLPROC()
Definition: wrlproc.cpp:137
LINE_READER * m_file
Definition: wrlproc.h:108
bool ReadMFColor(std::vector< WRLVEC3F > &aMFColor)
Definition: wrlproc.cpp:1281
unsigned int m_fileline
Definition: wrlproc.h:111
std::string m_badchars
Definition: wrlproc.h:116
std::string m_error
Definition: wrlproc.h:115
bool DiscardNode(void)
Definition: wrlproc.cpp:368
std::string m_buf
Definition: wrlproc.h:109
std::string GetFilePosition() const
Definition: wrlproc.cpp:1982
bool ReadSFFloat(float &aSFFloat)
Definition: wrlproc.cpp:806
std::string m_filename
Definition: wrlproc.h:117
bool ReadSFColor(WRLVEC3F &aSFColor)
Definition: wrlproc.cpp:774
bool ReadSFBool(bool &aSFBool)
Definition: wrlproc.cpp:729
bool m_eof
Definition: wrlproc.h:110
bool ReadString(std::string &aSFString)
Definition: wrlproc.cpp:612
char Peek(void)
Definition: wrlproc.cpp:2007
const char * GetParentDir(void)
Definition: wrlproc.cpp:236
std::string GetFileName(void)
Definition: wrlproc.cpp:1995
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition: vrml.cpp:63
WRLPROC(LINE_READER *aLineReader)
Definition: wrlproc.cpp:61
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:289
bool ReadSFInt(int &aSFInt32)
Definition: wrlproc.cpp:867
bool ReadMFRotation(std::vector< WRLROTATION > &aMFRotation)
Definition: wrlproc.cpp:1616
std::string GetError(void)
Definition: wrlproc.cpp:1960
bool DiscardList(void)
Definition: wrlproc.cpp:491
bool eof(void)
Definition: wrlproc.cpp:1954
bool ReadSFVec2f(WRLVEC2F &aSFVec2f)
Definition: wrlproc.cpp:1011
#define GETLINE
Definition: wrlproc.cpp:32
bool EatSpace(void)
Definition: wrlproc.cpp:191
bool getRawLine(void)
Definition: wrlproc.cpp:142
bool ReadMFString(std::vector< std::string > &aMFString)
Definition: wrlproc.cpp:1162
WRLVERSION m_fileVersion
Definition: wrlproc.h:114