kicad/plugins/3d/vrml/wrlproc.cpp

2040 lines
54 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <iostream>
#include <sstream>
#include <wx/string.h>
#include <wx/log.h>
#include "wrlproc.h"
#include <wx_filename.h>
#define GETLINE \
do \
{ \
try \
{ \
char* cp = m_file->ReadLine(); \
\
if( nullptr == cp ) \
{ \
m_eof = true; \
m_buf.clear(); \
} \
else \
{ \
m_buf = cp; \
m_bufpos = 0; \
} \
\
m_fileline = m_file->LineNumber(); \
} \
catch( ... ) \
{ \
m_error = " * [INFO] input line too long"; \
m_eof = true; \
m_buf.clear(); \
} \
} while( 0 )
WRLPROC::WRLPROC( LINE_READER* aLineReader )
{
m_fileVersion = WRLVERSION::VRML_INVALID;
m_eof = false;
m_fileline = 0;
m_bufpos = 0;
m_file = aLineReader;
if( nullptr == aLineReader )
{
m_eof = true;
return;
}
m_error.clear();
wxString tname = m_file->GetSource();
m_filename = tname.ToUTF8();
wxFileName fn( tname );
if( fn.IsRelative() )
fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
m_filedir = fn.GetPathWithSep().ToUTF8();
m_buf.clear();
GETLINE;
if( m_eof )
return;
if( m_buf.compare( 0, 16, "#VRML V1.0 ascii" ) == 0 )
{
m_fileVersion = WRLVERSION::VRML_V1;
// nothing < 0x20, and no:
// single or double quote
// backslash
// curly brace
// plus
// period
m_badchars = "\"'\\{}+.";
return;
}
if( m_buf.compare( 0, 15, "#VRML V2.0 utf8" ) == 0 )
{
m_fileVersion = WRLVERSION::VRML_V2;
// nothing < 0x20, and no:
// single or double quotes
// sharp (#)
// plus
// minus
// comma
// period
// square brackets []
// curly braces {}
// backslash
// NOTE: badchars should include '-' but due to my bad model naming scheme
// in the VRML model generator, I have allowed '-'. Other VRML parsers seem to
// accept '-'. FreeCAD produces names with '+' in them so '+' has been allowed
// as well; '+' is not even valid for VRML1.
//m_badchars = "'\"#,.+-[]\\{}";
m_badchars = "'\"#,.[]\\{}";
return;
}
m_buf.clear();
m_fileVersion = WRLVERSION::VRML_INVALID;
m_eof = true;
m_error = "not a valid VRML file: '";
m_error.append( m_filename );
m_error.append( 1, '\'' );
m_badchars.clear();
}
WRLPROC::~WRLPROC()
{
}
bool WRLPROC::getRawLine( void )
{
m_error.clear();
if( !m_file )
{
m_error = "no open file";
return false;
}
if( m_bufpos >= m_buf.size() )
m_buf.clear();
if( !m_buf.empty() )
return true;
if( m_eof )
return false;
GETLINE;
if( m_eof && m_buf.empty() )
return false;
// strip the EOL characters
while( !m_buf.empty() && ( *m_buf.rbegin() == '\r' || *m_buf.rbegin() == '\n' ) )
m_buf.erase( --m_buf.end() );
if( WRLVERSION::VRML_V1 == m_fileVersion && !m_buf.empty() )
{
std::string::iterator sS = m_buf.begin();
std::string::iterator eS = m_buf.end();
while( sS != eS )
{
if( ( ( *sS ) & 0x80 ) )
{
m_error = " non-ASCII character sequence in VRML1 file";
return false;
}
++sS;
}
}
return true;
}
bool WRLPROC::EatSpace( void )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
if( m_bufpos >= m_buf.size() )
m_buf.clear();
RETRY:
while( m_buf.empty() && !m_eof )
getRawLine();
// buffer may be empty if we have reached EOF or encountered IO errors
if( m_buf.empty() )
return false;
// eliminate leading white space (including control characters and comments)
while( m_bufpos < m_buf.size() )
{
if( m_buf[m_bufpos] > 0x20 )
break;
++m_bufpos;
}
if( m_bufpos == m_buf.size() || '#' == m_buf[m_bufpos] )
{
// lines consisting entirely of white space are not unusual
m_buf.clear();
goto RETRY;
}
return true;
}
WRLVERSION WRLPROC::GetVRMLType( void )
{
return m_fileVersion;
}
const char* WRLPROC::GetParentDir( void )
{
if( m_filedir.empty() )
return nullptr;
return m_filedir.c_str();
}
bool WRLPROC::ReadGlob( std::string& aGlob )
{
aGlob.clear();
if( !m_file )
{
m_error = "no open file";
return false;
}
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
size_t ssize = m_buf.size();
while( m_bufpos < ssize && m_buf[m_bufpos] > 0x20 )
{
if( ',' == m_buf[m_bufpos] )
{
// the comma is a special instance of blank space
++m_bufpos;
return true;
}
if( '{' == m_buf[m_bufpos] || '}' == m_buf[m_bufpos]
|| '[' == m_buf[m_bufpos] || ']' == m_buf[m_bufpos] )
return true;
aGlob.append( 1, m_buf[m_bufpos++] );
}
return true;
}
bool WRLPROC::ReadName( std::string& aName )
{
aName.clear();
if( !m_file )
{
m_error = "no open file";
return false;
}
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
size_t ssize = m_buf.size();
while( m_bufpos < ssize && m_buf[m_bufpos] > 0x20 )
{
if( '[' == m_buf[m_bufpos] || '{' == m_buf[m_bufpos]
|| ']' == m_buf[m_bufpos] || '}' == m_buf[m_bufpos]
|| '.' == m_buf[m_bufpos] || '#' == m_buf[m_bufpos]
|| ',' == m_buf[m_bufpos] )
{
if( !aName.empty() )
{
return true;
}
else
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << m_fileline << ", column " << m_bufpos;
ostr << " -- invalid name";
m_error = ostr.str();
return false;
}
}
if( m_badchars.find( m_buf[m_bufpos] ) != std::string::npos )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << m_fileline << ", column " << m_bufpos;
ostr << " -- invalid character in name";
m_error = ostr.str();
return false;
}
if( aName.empty() && m_buf[m_bufpos] >= '0' && m_buf[m_bufpos] <= '9' )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << m_fileline << ", column " << m_bufpos;
ostr << " -- name must not start with a digit";
m_error = ostr.str();
return false;
}
aName.append( 1, m_buf[m_bufpos++] );
}
return true;
}
bool WRLPROC::DiscardNode( void )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( '{' != m_buf[m_bufpos] )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] expecting character '{' at line " << m_fileline;
ostr << ", column " << m_bufpos;
m_error = ostr.str();
wxLogTrace( traceVrmlPlugin, "%s\n", m_error.c_str() );
return false;
}
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
++m_bufpos;
size_t lvl = 1;
std::string tmp;
while( lvl > 0 )
{
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
// comments must be skipped
if( '#' == m_buf[m_bufpos] )
{
m_bufpos = 0;
m_buf.clear();
continue;
}
if( '{' == m_buf[m_bufpos] )
{
++m_bufpos;
++lvl;
continue;
}
if( '}' == m_buf[m_bufpos] )
{
++m_bufpos;
--lvl;
continue;
}
// note: if we have a ']' we must skip it and test the next non-blank character;
// this ensures that we don't miss a '}' in cases where the braces are not
// separated by space. if we had proceeded to ReadGlob() we could have had a problem.
if( ']' == m_buf[m_bufpos] || '[' == m_buf[m_bufpos] )
{
++m_bufpos;
continue;
}
// strings are handled as a special case since they may contain
// control characters and braces
if( '"' == m_buf[m_bufpos] )
{
if( !ReadString( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
}
// everything at this point can be read and discarded via ReadGlob()
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
}
return true;
}
bool WRLPROC::DiscardList( void )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( '[' != m_buf[m_bufpos] )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] expecting character '[' at line " << m_fileline;
ostr << ", column " << m_bufpos;
m_error = ostr.str();
return false;
}
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
++m_bufpos;
size_t lvl = 1;
std::string tmp;
while( lvl > 0 )
{
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
// comments must be skipped
if( '#' == m_buf[m_bufpos] )
{
m_bufpos = 0;
m_buf.clear();
continue;
}
if( '[' == m_buf[m_bufpos] )
{
++m_bufpos;
++lvl;
continue;
}
if( ']' == m_buf[m_bufpos] )
{
++m_bufpos;
--lvl;
continue;
}
// note: if we have a '}' we must skip it and test the next non-blank character;
// this ensures that we don't miss a ']' in cases where the braces are not
// separated by space. if we had proceeded to ReadGlob() we could have had a problem.
if( '}' == m_buf[m_bufpos] || '{' == m_buf[m_bufpos] )
{
++m_bufpos;
continue;
}
// strings are handled as a special case since they may contain
// control characters and braces
if( '"' == m_buf[m_bufpos] )
{
if( !ReadString( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
}
// everything at this point can be read and discarded via ReadGlob()
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
}
return false;
}
bool WRLPROC::ReadString( std::string& aSFString )
{
// In VRML1 a string may be unquoted provided there are no space characters
// In VRML2 all strings must be quoted
aSFString.clear();
if( !m_file )
{
m_error = "no open file";
return false;
}
// remember the line number in case of errors
size_t ifline = m_fileline;
while( true )
{
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << "invalid VRML file; expecting string at line " << ifline <<
" but found nothing";
m_error = ostr.str();
return false;
}
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( WRLVERSION::VRML_V2 == m_fileVersion && '"' != m_buf[m_bufpos] )
{
m_error = "invalid VRML2 file (string not quoted)";
return false;
}
ifline = m_fileline;
if( '"' != m_buf[m_bufpos] )
{
if( !ReadGlob( aSFString ) )
{
std::ostringstream ostr;
ostr << "invalid VRML1 file at lines " << ifline << "--" << m_fileline;
if( !m_error.empty() )
ostr << " : " << m_error;
m_error = ostr.str();
return false;
}
return true;
}
bool isesc = false; // true if an escape character was found
while( true )
{
++m_bufpos;
if( m_bufpos >= m_buf.size() )
{
aSFString.append( 1, '\n' );
if( !getRawLine() )
{
std::ostringstream ostr;
ostr << "invalid VRML1 file at lines " << ifline << "--" << m_fileline;
ostr << "; could not find end of string\n";
m_error = ostr.str();
return false;
}
}
if( '\\' == m_buf[m_bufpos] )
{
if( isesc )
{
aSFString.append( 1, '\n' );
isesc = false;
}
else
{
isesc = true;
}
continue;
}
else if( '"' == m_buf[m_bufpos] )
{
if( isesc )
aSFString.append( 1, '"' );
else
break;
}
else
{
aSFString.append( 1, m_buf[m_bufpos] );
}
// ensure that the backslash escape cannot extend beyond the first character
isesc = false;
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadSFBool( bool& aSFBool )
{
if( !EatSpace() )
return false;
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
std::string tmp;
if( !ReadGlob( tmp ) )
return false;
if( !tmp.compare( "0" ) )
{
aSFBool = false;
}
else if( !tmp.compare( "1" ) )
{
aSFBool = true;
}
else if( !tmp.compare( "TRUE" ) )
{
aSFBool = true;
}
else if( !tmp.compare( "FALSE" ) )
{
aSFBool = false;
}
else
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] expected one of 0, 1, TRUE, FALSE but got '" << tmp << "'\n";
m_error = ostr.str();
return false;
}
return true;
}
bool WRLPROC::ReadSFColor( WRLVEC3F& aSFColor )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !ReadSFVec3f( aSFColor ) )
return false;
if( aSFColor.x < 0.0 || aSFColor.x > 1.0 || aSFColor.y < 0.0 || aSFColor.y > 1.0
|| aSFColor.z < 0.0 || aSFColor.z > 1.0 )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] invalid RGB value in color triplet";
m_error = ostr.str();
return false;
}
return true;
}
bool WRLPROC::ReadSFFloat( float& aSFFloat )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
aSFFloat = 0.0;
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
std::string tmp;
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
std::istringstream istr;
istr.str( tmp );
istr >> aSFFloat;
if( istr.fail() || !istr.eof() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] invalid character in SFFloat";
m_error = ostr.str();
return false;
}
return true;
}
bool WRLPROC::ReadSFInt( int& aSFInt32 )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
aSFInt32 = 0;
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
std::string tmp;
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline<< ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( std::string::npos != tmp.find( "0x" ) )
{
// Rules: "0x" + "0-9, A-F" - VRML is case sensitive but in
// this instance we do no enforce case.
std::stringstream sstr;
sstr << std::hex << tmp;
sstr >> aSFInt32;
return true;
}
std::istringstream istr;
istr.str( tmp );
istr >> aSFInt32;
if( istr.fail() || !istr.eof() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] invalid character in SFInt";
m_error = ostr.str();
return false;
}
return true;
}
bool WRLPROC::ReadSFRotation( WRLROTATION& aSFRotation )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
aSFRotation.x = 0.0;
aSFRotation.y = 0.0;
aSFRotation.z = 1.0;
aSFRotation.w = 0.0;
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
std::string tmp;
float trot[4];
for( int i = 0; i < 4; ++i )
{
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
std::istringstream istr;
istr.str( tmp );
istr >> trot[i];
if( istr.fail() || !istr.eof() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] invalid character in space delimited quartet";
m_error = ostr.str();
return false;
}
}
aSFRotation.x = trot[0];
aSFRotation.y = trot[1];
aSFRotation.z = trot[2];
aSFRotation.w = trot[3];
return true;
}
bool WRLPROC::ReadSFVec2f( WRLVEC2F& aSFVec2f )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
aSFVec2f.x = 0.0;
aSFVec2f.y = 0.0;
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
std::string tmp;
float tcol[2];
for( int i = 0; i < 2; ++i )
{
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
std::istringstream istr;
istr.str( tmp );
istr >> tcol[i];
if( istr.fail() || !istr.eof() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] invalid character in space delimited pair";
m_error = ostr.str();
return false;
}
}
aSFVec2f.x = tcol[0];
aSFVec2f.y = tcol[1];
return true;
}
bool WRLPROC::ReadSFVec3f( WRLVEC3F& aSFVec3f )
{
if( !m_file )
{
m_error = "no open file";
return false;
}
aSFVec3f.x = 0.0;
aSFVec3f.y = 0.0;
aSFVec3f.z = 0.0;
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
std::string tmp;
float tcol[3];
for( int i = 0; i < 3; ++i )
{
if( !ReadGlob( tmp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
// ignore any commas
if( !EatSpace() )
return false;
if( ',' == m_buf[m_bufpos] )
Pop();
std::istringstream istr;
istr.str( tmp );
istr >> tcol[i];
if( istr.fail() || !istr.eof() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] invalid character in space delimited triplet";
m_error = ostr.str();
return false;
}
}
aSFVec3f.x = tcol[0];
aSFVec3f.y = tcol[1];
aSFVec3f.z = tcol[2];
return true;
}
bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString )
{
aMFString.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
std::string lstr;
if( m_buf[m_bufpos] != '[' )
{
if( !ReadString( lstr ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( m_bufpos >= m_buf.size() && !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFString.push_back( lstr );
return true;
}
++m_bufpos;
while( true )
{
if( !ReadString( lstr ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFString.push_back( lstr );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] problems encountered while reading list";
m_error = ostr.str();
return false;
}
if( ']' == m_buf[m_bufpos] )
break;
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor )
{
aMFColor.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
WRLVEC3F lcolor;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( m_buf[m_bufpos] != '[' )
{
if( !ReadSFColor( lcolor ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFColor.push_back( lcolor );
return true;
}
++m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( !ReadSFColor( lcolor ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
aMFColor.push_back( lcolor );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ']' == m_buf[m_bufpos] )
break;
if( ',' == m_buf[m_bufpos] )
Pop();
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat )
{
aMFFloat.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
float temp;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( m_buf[m_bufpos] != '[' )
{
if( !ReadSFFloat( temp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFFloat.push_back( temp );
return true;
}
++m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( !ReadSFFloat( temp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
aMFFloat.push_back( temp );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ']' == m_buf[m_bufpos] )
break;
if( ',' == m_buf[m_bufpos] )
Pop();
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 )
{
aMFInt32.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
int temp;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( m_buf[m_bufpos] != '[' )
{
if( !ReadSFInt( temp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFInt32.push_back( temp );
return true;
}
++m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( !ReadSFInt( temp ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
aMFInt32.push_back( temp );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ']' == m_buf[m_bufpos] )
break;
if( ',' == m_buf[m_bufpos] )
Pop();
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation )
{
aMFRotation.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
WRLROTATION lrot;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( m_buf[m_bufpos] != '[' )
{
if( !ReadSFRotation( lrot ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFRotation.push_back( lrot );
return true;
}
++m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( !ReadSFRotation( lrot ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
aMFRotation.push_back( lrot );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ']' == m_buf[m_bufpos] )
break;
if( ',' == m_buf[m_bufpos] )
Pop();
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f )
{
aMFVec2f.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
WRLVEC2F lvec2f;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( m_buf[m_bufpos] != '[' )
{
if( !ReadSFVec2f( lvec2f ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFVec2f.push_back( lvec2f );
return true;
}
++m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( !ReadSFVec2f( lvec2f ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
aMFVec2f.push_back( lvec2f );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ']' == m_buf[m_bufpos] )
break;
if( ',' == m_buf[m_bufpos] )
Pop();
}
++m_bufpos;
return true;
}
bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f )
{
aMFVec3f.clear();
size_t fileline = m_fileline;
size_t linepos = m_bufpos;
if( !m_file )
{
m_error = "no open file";
return false;
}
WRLVEC3F lvec3f;
while( true )
{
if( !EatSpace() )
return false;
// if the text is the start of a comment block, clear the buffer and loop
if( '#' == m_buf[m_bufpos] )
m_buf.clear();
else
break;
}
if( m_buf[m_bufpos] != '[' )
{
if( !ReadSFVec3f( lvec3f ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( ',' == m_buf[m_bufpos] )
Pop();
aMFVec3f.push_back( lvec3f );
return true;
}
++m_bufpos;
while( true )
{
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( !ReadSFVec3f( lvec3f ) )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] " << m_error;
m_error = ostr.str();
return false;
}
aMFVec3f.push_back( lvec3f );
if( !EatSpace() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_bufpos << "\n";
ostr << " * [INFO] could not check characters after the string";
m_error = ostr.str();
return false;
}
if( !EatSpace() )
return false;
if( ']' == m_buf[m_bufpos] )
break;
if( ',' == m_buf[m_bufpos] )
Pop();
}
++m_bufpos;
return true;
}
bool WRLPROC::eof( void )
{
return m_eof;
}
std::string WRLPROC::GetError( void )
{
return m_error;
}
bool WRLPROC::GetFilePosData( size_t& line, size_t& column )
{
if( !m_file )
{
line = 0;
column = 0;
return false;
}
line = m_fileline;
column = m_bufpos;
return true;
}
std::string WRLPROC::GetFilePosition() const
{
std::ostringstream retv;
if( !m_file )
retv << "no file loaded to provide file position information";
else
retv << "at line " << m_fileline << ", column " << m_bufpos;
return retv.str();
}
std::string WRLPROC::GetFileName( void )
{
if( !m_file )
{
m_error = "no open file";
return "";
}
return std::string( m_file->GetSource().ToUTF8() );
}
char WRLPROC::Peek( void )
{
if( !m_file )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [BUG] no open file";
m_error = ostr.str();
return '\0';
}
if( !EatSpace() )
{
if( m_error.empty() )
{
std::ostringstream ostr;
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed to read data from file\n";
m_error = ostr.str();
}
return '\0';
}
return m_buf[m_bufpos];
}
void WRLPROC::Pop( void )
{
if( m_bufpos < m_buf.size() )
++m_bufpos;
}