2040 lines
54 KiB
C++
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;
|
|
}
|