From e13dade5179ab328648de5dcd546cb65a46ad0c7 Mon Sep 17 00:00:00 2001 From: Cirilo Bernardo Date: Sun, 20 Dec 2015 18:59:26 +1100 Subject: [PATCH] Added beginnings of VRML parser --- plugins/3d/CMakeLists.txt | 1 + plugins/3d/vrml/CMakeLists.txt | 16 + plugins/3d/vrml/v2/vrml2_base.cpp | 162 +++ plugins/3d/vrml/v2/vrml2_base.h | 83 ++ plugins/3d/vrml/v2/vrml2_helpers.h | 47 + plugins/3d/vrml/v2/vrml2_node.cpp | 255 ++++ plugins/3d/vrml/v2/vrml2_node.h | 154 ++ plugins/3d/vrml/v2/wrlproc.cpp | 2120 ++++++++++++++++++++++++++++ plugins/3d/vrml/v2/wrlproc.h | 104 ++ plugins/3d/vrml/v2/wrltypes.h | 130 ++ plugins/3d/vrml/vrml.cpp | 191 +++ 11 files changed, 3263 insertions(+) create mode 100644 plugins/3d/vrml/CMakeLists.txt create mode 100644 plugins/3d/vrml/v2/vrml2_base.cpp create mode 100644 plugins/3d/vrml/v2/vrml2_base.h create mode 100644 plugins/3d/vrml/v2/vrml2_helpers.h create mode 100644 plugins/3d/vrml/v2/vrml2_node.cpp create mode 100644 plugins/3d/vrml/v2/vrml2_node.h create mode 100644 plugins/3d/vrml/v2/wrlproc.cpp create mode 100644 plugins/3d/vrml/v2/wrlproc.h create mode 100644 plugins/3d/vrml/v2/wrltypes.h create mode 100644 plugins/3d/vrml/vrml.cpp diff --git a/plugins/3d/CMakeLists.txt b/plugins/3d/CMakeLists.txt index 39818bc22a..2564ef093f 100644 --- a/plugins/3d/CMakeLists.txt +++ b/plugins/3d/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory( idf ) +add_subdirectory( vrml ) diff --git a/plugins/3d/vrml/CMakeLists.txt b/plugins/3d/vrml/CMakeLists.txt new file mode 100644 index 0000000000..62956216e4 --- /dev/null +++ b/plugins/3d/vrml/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/v2 ) + +add_library( s3d_plugin_vrml MODULE + vrml.cpp + v2/wrlproc.cpp +# v2/vrml2_node.cpp +# v2/vrml2_base.cpp + ) + +target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} ) + +install( TARGETS + s3d_plugin_vrml + DESTINATION ${KICAD_USER_PLUGIN}/3d + COMPONENT binary + ) diff --git a/plugins/3d/vrml/v2/vrml2_base.cpp b/plugins/3d/vrml/v2/vrml2_base.cpp new file mode 100644 index 0000000000..ee8ec737ee --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_base.cpp @@ -0,0 +1,162 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + +#include "vrml2_base.h" +#include "vrml2_helpers.h" + + +WRL2BASE::WRL2BASE( WRL2NODE* aParent ) : WRL2NODE() +{ + m_Type = V2_BASE; + return; +} + + +WRL2BASE::~WRL2BASE() +{ + std::list< WRL2NODE* >::iterator sC = m_Children.begin(); + std::list< WRL2NODE* >::iterator eC = m_Children.end(); + + while( sC != eC ) + { + (*sC)->SetParent( NULL ); + delete (*sC); + ++sC; + } + + sC.clear(); + return; +} + + +// functions inherited from WRL2NODE +bool WRL2BASE::SetParent( WRL2NODE* aParent ) +{ + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to extract name from virtual base node\n"; + #endif +} + + +WRL2NODE* WRL2BASE::FindNode( const char *aNodeName, const WRL2NODE *aCaller ) +{ + if( NULL == aNodeName || 0 == aNodeName[0] ) + return NULL; + + if( !m_Name.compare( aNodeName ) ) + return this; + + FIND_NODE( aNodeName, m_Children, this ); + + return NULL; +} + + +bool WRL2BASE::AddRefNode( WRL2NODE* aNode ) +{ + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to add reference node to WRL2BASE\n"; + #endif + + return false; +} + + +bool WRL2BASE::AddChildNode( WRL2NODE* aNode ) +{ + if( aNode->GetNodeType() == WRL2_BASE ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to add a base node to another base node\n"; + #endif + return false; + } + + std::list< WRL2NODE* >::iterator sC = m_Children.begin(); + std::list< WRL2NODE* >::iterator eC = m_Children.end(); + + while( sC != eC ) + { + if( *sC == aNode ) + return false; + } + + aNode->SetParent( this ); + m_Children.push_back( aNode ); + + return true; +} + + +const char* WRL2BASE::GetName( void ) +{ + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to extract name from virtual base node\n"; + #endif + return NULL; + return NULL; +} + + +bool WRL2BASE::SetName(const char *aName) +{ + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] attempting to set name on virtual base node\n"; + #endif + return false; +} + + +bool WRL2BASE::Read( WRLPROC& proc ) +{ + if( proc.GetVRMLType() != VRML_V2 ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] no open file or file is not a VRML2 file\n"; + #endif + return false; + } + + std::string glob; + + while( proc.ReadGlob( glob ) ) + { + // XXX - Process node name + + + xxx; + } while( !glob.empty() ); + + + // XXX - + #warning TO BE IMPLEMENTED + return false; +} diff --git a/plugins/3d/vrml/v2/vrml2_base.h b/plugins/3d/vrml/v2/vrml2_base.h new file mode 100644 index 0000000000..11127dff6e --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_base.h @@ -0,0 +1,83 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + */ + +/** + * @file vrmlv2_node.h + * defines the base class for VRML2.0 nodes + */ + +/* + * Notes on deleting unsupported entities: + * 1. PROTO: PROTO ProtoName [parameter list] {body} + * the parameter list will always have '[]'. So the items + * to delete are: String, List, Body + * 2. EXTERNPROTO: EXTERNPROTO extern protoname [] MFstring + * delete: string, string, string, list, list + * 3. Unsupported node types: NodeName (Optional DEF RefName) {body} + * This scheme should also apply to PROTO'd node types. + * 4. ROUTE: ROUTE nodename1.event to nodename2.event + * Delete a String 3 times + * 5. Script: Script { ... } + */ + +#ifndef VRML2_BASE_H +#define VRML2_BASE_H + +#include +#include + +#include "vrml2_node.h" + + +/** + * Class WRL2BASE + * represents the top node of a VRML2 model + */ +class WRL2BASE : public WRL2NODE +{ +protected: + std::list< WRL2NODE* > m_Children; // nodes owned by this node + +public: + + // functions inherited from WRL2NODE + void unlinkChildNode( const WRL2NODE* aNode ); + void unlinkRefNode( const WRL2NODE* aNode ); + +public: + WRL2BASE(); + virtual ~WRL2BASE(); + + // overrides + virtual const char* GetName( void ); + virtual bool SetName(const char *aName); + + // functions inherited from WRL2NODE + bool Read( WRLPROC& proc ); + bool SetParent( WRL2NODE* aParent ); + WRL2NODE* FindNode( const char *aNodeName, const WRL2NODE *aCaller ); + bool AddRefNode( WRL2NODE* aNode ); + bool AddChildNode( WRL2NODE* aNode ); +}; + +#endif // VRML2_BASE_H diff --git a/plugins/3d/vrml/v2/vrml2_helpers.h b/plugins/3d/vrml/v2/vrml2_helpers.h new file mode 100644 index 0000000000..e9bdb632dc --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_helpers.h @@ -0,0 +1,47 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + */ + +/** + * @file vrml2_helpers.h + * helper functions for VRML2 processing + */ + +#ifndef VRML2_HELPERS_H +#define VRML2_HELPERS_H + + +// Function to find a node object given a (non-unique) node name +#define FIND_NODE( aName, aNodeList, aCallingNode ) do { \ + std::vector< aType* >::iterator sLA = aNodeList.begin(); \ + std::vector< aType* >::iterator eLA = aNodeList.end(); \ + WRL2NODE* psg = NULL; \ + while( sLA != eLA ) { \ + if( (WRL2NODE*)*sLA != aCallingNode ) { \ + psg = (WRL2NODE*) (*sLA)->FindNode( aName, this ); \ + if( NULL != psg) \ + return psg; \ + } \ + ++sLA; \ + } } while ( 0 ) + +#endif // VRML2_HELPERS_H diff --git a/plugins/3d/vrml/v2/vrml2_node.cpp b/plugins/3d/vrml/v2/vrml2_node.cpp new file mode 100644 index 0000000000..8a12e2ea2d --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_node.cpp @@ -0,0 +1,255 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include "vrml2_node.h" + + + +static std::set< std::string > badNames; + +typedef std::pair< std::string, WRLNODES > NODEITEM; +typedef std::map< std::string, WRLNODES > NODEMAP; +static NODEMAP nodenames; + + +WRL2NODE::WRL2NODE() +{ + m_Parent = NULL; + m_Type = V2_END; + + if( badNames.empty() ) + { + badNames.insert( "DEF" ); + badNames.insert( "EXTERNPROTO" ); + badNames.insert( "FALSE" ); + badNames.insert( "IS" ); + badNames.insert( "NULL" ); + badNames.insert( "PROTO" ); + badNames.insert( "ROUTE" ); + badNames.insert( "TO" ); + badNames.insert( "TRUE" ); + badNames.insert( "USE" ); + badNames.insert( "eventIn" ); + badNames.insert( "eventOut" ); + badNames.insert( "exposedField" ); + badNames.insert( "field" ); + } + + if( nodenames.empty() ) + { + node_names.insert( NODEITEM( "Anchor", WRL2_ANCHOR ) ); + node_names.insert( NODEITEM( "Appearance", WRL2_APPEARANCE ) ); + node_names.insert( NODEITEM( "Audioclip", WRL2_AUDIOCLIP ); + node_names.insert( NODEITEM( "Background", WRL2_BACKGROUND ) ); + node_names.insert( NODEITEM( "Billboard", WRL2_BILLBOARD ) ); + node_names.insert( NODEITEM( "Box", WRL2_BOX ) ); + node_names.insert( NODEITEM( "Collision", WRL2_COLLISION ) ); + node_names.insert( NODEITEM( "Color", WRL2_COLOR ) ); + node_names.insert( NODEITEM( "ColorInterpolator", WRL2_COLORINTERPOLATOR ) ); + node_names.insert( NODEITEM( "Cone", WRL2_CONE ) ); + node_names.insert( NODEITEM( "Coordinate", WRL2_COORDINATE ) ); + node_names.insert( NODEITEM( "CoordinateInterpolator", WRL2_COORDINATEINTERPOLATOR ) ); + node_names.insert( NODEITEM( "Cylinder", WRL2_CYLINDER ) ); + node_names.insert( NODEITEM( "CylinderSensor", WRL2_CYLINDERSENSOR ) ); + node_names.insert( NODEITEM( "DirectionalLight", WRL2_DIRECTIONALLIGHT ) ); + node_names.insert( NODEITEM( "ElevationGrid", WRL2_ELEVATIONGRID ) ); + node_names.insert( NODEITEM( "Extrusion", WRL2_EXTRUSION ) ); + node_names.insert( NODEITEM( "Fog", WRL2_FOG ) ); + node_names.insert( NODEITEM( "FontStyle", WRL2_FONTSTYLE ) ); + node_names.insert( NODEITEM( "Group", WRL2_GROUP ) ); + node_names.insert( NODEITEM( "ImageTexture", WRL2_IMAGETEXTURE ) ); + node_names.insert( NODEITEM( "IndexedFaceSet", WRL2_INDEXEDFACESET ) ); + node_names.insert( NODEITEM( "IndexedLineSet", WRL2_INDEXEDLINESET ) ); + node_names.insert( NODEITEM( "Inline", WRL2_INLINE ) ); + node_names.insert( NODEITEM( "LOD", WRL2_LOD ) ); + node_names.insert( NODEITEM( "Material", WRL2_MATERIAL ) ); + node_names.insert( NODEITEM( "MovieTexture", WRL2_MOVIETEXTURE ) ); + node_names.insert( NODEITEM( "NavigationInfo", WRL2_NAVIGATIONINFO ) ); + node_names.insert( NODEITEM( "Normal", WRL2_NORMAL ) ); + node_names.insert( NODEITEM( "NormalInterpolator", WRL2_NORMALINTERPOLATOR ) ); + node_names.insert( NODEITEM( "OrientationInterpolator", WRL2_ORIENTATIONINTERPOLATOR ) ); + node_names.insert( NODEITEM( "PixelTexture", WRL2_PIXELTEXTURE ) ); + node_names.insert( NODEITEM( "PlaneSensor", WRL2_PLANESENSOR ) ); + node_names.insert( NODEITEM( "PointLight", WRL2_POINTLIGHT ) ); + node_names.insert( NODEITEM( "PointSet", WRL2_POINTSET ) ); + node_names.insert( NODEITEM( "PositionInterpolator", WRL2_POSITIONINTERPOLATOR ) ); + node_names.insert( NODEITEM( "ProximitySensor", WRL2_PROXIMITYSENSOR ) ); + node_names.insert( NODEITEM( "ScalarInterpolator", WRL2_SCALARINTERPOLATOR ) ); + node_names.insert( NODEITEM( "Script", WRL2_SCRIPT ) ); + node_names.insert( NODEITEM( "Shape", WRL2_SHAPE ) ); + node_names.insert( NODEITEM( "Sound", WRL2_SOUND ) ); + node_names.insert( NODEITEM( "Sphere", WRL2_SPHERE ) ); + node_names.insert( NODEITEM( "SphereSensor", WRL2_SPHERESENSOR ) ); + node_names.insert( NODEITEM( "SpotLight", WRL2_SPOTLIGHT ) ); + node_names.insert( NODEITEM( "Switch", WRL2_SWITCH ) ); + node_names.insert( NODEITEM( "Text", WRL2_TEXT ) ); + node_names.insert( NODEITEM( "TextureCoordinate", WRL2_TEXTURECOORDINATE ) ); + node_names.insert( NODEITEM( "TextureTransform", WRL2_TEXTURETRANSFORM ) ); + node_names.insert( NODEITEM( "TimeSensor", WRL2_TIMESENSOR ) ); + node_names.insert( NODEITEM( "TouchSensor", WRL2_TOUCHSENSOR ) ); + node_names.insert( NODEITEM( "Transform", WRL2_TRANSFORM ) ); + node_names.insert( NODEITEM( "ViewPoint", WRL2_VIEWPOINT ) ); + node_names.insert( NODEITEM( "VisibilitySensor", WRL2_VISIBILITYSENSOR ) ); + node_names.insert( NODEITEM( "WorldInfo", WRL2_WORLDINFO ) ); + } + + return; +} + + +WRL2NODE::~WRL2NODE() +{ + std::list< WRL2NODE* > m_BackPointers; // nodes which hold a reference to this + std::list< WRL2NODE* > m_Children; // nodes owned by this node + std::list< WRL2NODE* > m_References; // nodes not owned but referenced by this node + + if( m_Parent ) + m_Parent->unlinkChildNode( this ); + + std::list< WRL2NODE* >::iterator sBP = m_BackPointers.begin(); + std::list< WRL2NODE* >::iterator eBP = m_BackPointers.end(); + + while( sBP != eBP ) + { + (*sBP)->unlinkRefNode( this ); + ++sBP; + } + + return; +} + + +void WRL2NODE::addNodeRef( WRL2NODE* aNode ) +{ + std::list< WRL2NODE* >::iterator np = + std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode ); + + if( np != m_BackPointers.end() ) + return; + + m_BackPointers.push_back( aNode ); + + return; +} + + +void WRL2NODE::delNodeRef( WRL2NODE* aNode ) +{ + std::list< WRL2NODE* >::iterator np = + std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode ); + + if( np != m_BackPointers.end() ) + { + m_BackPointers.erase( np ); + return; + } + + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] delNodeRef() did not find its target\n"; + #endif + + return; +} + + +WRL2TYPES WRL2NODE::GetNodeType( void ) const +{ + return m_Type; +} + + +WRL2NODE* WRL2NODE::GetParent( void ) +{ + return m_Parent; +} + + +const char* WRL2NODE::GetName( void ) +{ + return m_Name; +} + + +bool WRL2NODE::SetName(const char *aName) +{ + if( NULL == aName || '\0' == aName[0] ) + { + m_Name.clear(); + return true; + } + + std::set< std::string >::iterator item = badNames.find( aName ); + + if( item != badNames.end() ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] invalid node name '" << *item << "' (matches restricted word)\n"; + #endif + return false; + } + + + if( isdigit( aName[0] ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] invalid node name '" << *item << "' (begins with digit)\n"; + #endif + return false; + } + + std::string tmpstr( aName ); + #define BAD_CHARS1 "\"\'#+,-.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F" + #define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + + if( std::string::npos != tmpstr.find_first_of( BAD_CHARS1 ) + || std::string::npos != tmpstr.find_first_of( BAD_CHARS2 ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] invalid node name '" << *item; + std::cerr<< "' (contains invalid character)\n"; + #endif + return false; + } + + m_Name = aName; + + return true; +} + + +const char* WRL2NODE::GetNodeTypeName( WRL::V2TYPES aNodeType ) const +{ + if( aNodeType < WRL2_BEGIN || aNodeType >= WRL2_END ) + return NULL; + + return nodenames[aNodeType]->first.c_str(); +} diff --git a/plugins/3d/vrml/v2/vrml2_node.h b/plugins/3d/vrml/v2/vrml2_node.h new file mode 100644 index 0000000000..29395ff110 --- /dev/null +++ b/plugins/3d/vrml/v2/vrml2_node.h @@ -0,0 +1,154 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + */ + +/** + * @file vrmlv2_node.h + * defines the base class for VRML2.0 nodes + */ + +/* + * Notes on deleting unsupported entities: + * 1. PROTO: PROTO ProtoName [parameter list] {body} + * the parameter list will always have '[]'. So the items + * to delete are: String, List, Body + * 2. EXTERNPROTO: EXTERNPROTO extern protoname [] MFstring + * delete: string, string, string, list, list + * 3. Unsupported node types: NodeName (Optional DEF RefName) {body} + * This scheme should also apply to PROTO'd node types. + * 4. ROUTE: ROUTE nodename1.event to nodename2.event + * Delete a String 3 times + * 5. Script: Script { ... } + */ + +#ifndef VRML2_NODE_H +#define VRML2_NODE_H + +#include +#include + +#include "wrlproc.h" + + +/** + * Class WRL2NODE + * represents the base class of all VRML2 nodes + */ +class WRL2NODE +{ +protected: + WRL2NODE* m_Parent; // pointer to parent node; may be NULL for top level node + WRL2TYPES m_Type; // type of VRML node + std::string m_Name; // name to use for referencing the node by name + + std::list< WRL2NODE* > m_BackPointers; // nodes which hold a reference to this + +public: + /** + * Function unlinkChild + * removes references to an owned child; it is invoked by the child upon destruction + * to ensure that the parent has no invalid references. + * + * @param aNode is the child which is being deleted + */ + virtual void unlinkChildNode( const WRL2NODE* aNode ) = 0; + + /** + * Function unlinkRef + * removes pointers to a referenced node; it is invoked by the referenced node + * upon destruction to ensure that the referring node has no invalid references. + * + * @param aNode is the node which is being deleted + */ + virtual void unlinkRefNode( const WRL2NODE* aNode ) = 0; + + /** + * Function addNodeRef + * adds a pointer to a node which references, but does not own, this node. + * Such back-pointers are required to ensure that invalidated references + * are removed when a node is deleted + * + * @param aNode is the node holding a reference to this object + */ + void addNodeRef( WRL2NODE* aNode ); + + /** + * Function delNodeRef + * removes a pointer to a node which references, but does not own, this node. + * + * @param aNode is the node holding a reference to this object + */ + void delNodeRef( WRL2NODE* aNode ); + +public: + WRL2NODE(); + virtual ~WRL2NODE(); + + // read data via the given file processor + virtual bool Read( WRLPROC& proc ) = 0; + + /** + * Function GetNodeType + * returns the type of this node instance + */ + WRL2TYPES GetNodeType( void ) const; + + /** + * Function GetParent + * returns a pointer to the parent SGNODE of this object + * or NULL if the object has no parent (ie. top level transform) + */ + WRL2NODE* GetParent( void ); + + /** + * Function SetParent + * sets the parent WRL2NODE of this object. + * + * @param aParent [in] is the desired parent node + * @return true if the operation succeeds; false if + * the given node is not allowed to be a parent to + * the derived object. + */ + virtual bool SetParent( WRL2NODE* aParent ) = 0; + + virtual const char* GetName( void ); + virtual bool SetName(const char *aName); + + const char * GetNodeTypeName( WRL::V2TYPES aNodeType ) const; + + /** + * Function FindNode searches the tree of linked nodes and returns a + * reference to the first node found with the given name. The reference + * is then typically added to another node via AddRefNode(). + * + * @param aNodeName is the name of the node to search for + * @param aCaller is a pointer to the node invoking this function + * @return is a valid node pointer on success, otherwise NULL + */ + virtual WRL2NODE* FindNode( const char *aNodeName, const WRL2NODE *aCaller ) = 0; + + virtual bool AddRefNode( WRL2NODE* aNode ) = 0; + + virtual bool AddChildNode( WRL2NODE* aNode ) = 0; +}; + +#endif // VRML2_NODE_H diff --git a/plugins/3d/vrml/v2/wrlproc.cpp b/plugins/3d/vrml/v2/wrlproc.cpp new file mode 100644 index 0000000000..8e51d43676 --- /dev/null +++ b/plugins/3d/vrml/v2/wrlproc.cpp @@ -0,0 +1,2120 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include "wrlproc.h" + +#define GETLINE do {\ + m_filepos = m_file.tellg(); \ + std::getline( m_file, m_buf ); \ + ++m_fileline; \ + } while( 0 ) + + +WRLPROC::WRLPROC() +{ + m_filepos = 0; + m_fileline = 0; + m_linepos = 0; + m_fileVersion = VRML_INVALID; + + return; +} + + +WRLPROC::~WRLPROC() +{ + Close(); + return; +} + + +bool WRLPROC::Open( const std::string& aFileName ) +{ + if( m_file.is_open() ) + { + m_error = "attempting to open a new file while one is still open"; + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] " << m_error << "\n"; + #endif + return false; + } + + // initialize some internal variables; this is necessary since + // the values may be set differently if there have been previous + // failed calls to Open(). + m_error.clear(); + m_filename = aFileName; + m_filepos = 0; + m_fileline = 0; + m_linepos = 0; + m_file.open( aFileName.c_str() ); + + if( !m_file.is_open() ) + { + m_error = "could not open file '"; + m_error.append( aFileName ); + m_error.append( 1, '\'' ); + return false; + } + + m_buf.clear(); + GETLINE; + m_linepos = 0; + m_buf = m_buf.substr( 0, 16 ); + + if( m_buf.find( "#VRML V1.0 ascii" ) == 0 ) + { + m_fileVersion = VRML_V1; + // nothing < 0x20, and no: + // single or double quote + // backslash + // curly brace + // plus + // period + m_badchars = "\"'\\{}+."; + return true; + } + + if( m_buf.find( "#VRML V2.0 utf8" ) == 0 ) + { + m_fileVersion = VRML_V2; + // nothing < 0x20, and no: + // single or double quotes + // sharp (#) + // plus + // minus + // comma + // period + // square brackets [] + // curly braces {} + // backslash + m_badchars = "'\"#,.+-[]\\{}"; + return true; + } + + m_file.close(); + m_buf.clear(); + m_fileVersion = VRML_INVALID; + m_error = "not a valid VRML file: '"; + m_error.append( aFileName ); + m_error.append( 1, '\'' ); + m_badchars.clear(); + + return false; +} + + +void WRLPROC::Close() +{ + m_file.close(); + m_buf.clear(); + m_filepos = 0; + m_fileline = 0; + m_linepos = 0; + m_fileVersion = VRML_INVALID; + m_filename.clear(); + m_error.clear(); + m_badchars.clear(); + + return; +} + + +bool WRLPROC::getRawLine( void ) +{ + m_error.clear(); + + if( !m_file.is_open() ) + { + m_error = "no open file"; + return false; + } + + if( m_linepos >= m_buf.size() ) + m_buf.clear(); + + if( !m_buf.empty() ) + return true; + + if( m_file.bad() ) + { + m_error = "bad stream"; + return false; + } + + GETLINE; + m_linepos = 0; + + if( m_file.bad() && !m_file.eof() ) + return false; + + if( 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( '\xff' == ((*sS) & 0x80) ) + { + m_error = " non-ASCII character sequence in VRML1 file"; + return false; + } + + ++sS; + } + } + + return true; +} + + +bool WRLPROC::eatSpace( void ) +{ + if( m_linepos >= m_buf.size() ) + m_buf.clear(); + +RETRY: + while( m_buf.empty() && !m_file.bad() ) + 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) + while( m_linepos < m_buf.size() ) + { + if( m_buf[m_linepos] > 0x20 ) + break; + + ++m_linepos; + } + + if( m_linepos == m_buf.size() ) + { + // lines consisting entirely of white space are not unusual + m_buf.clear(); + goto RETRY; + } + + return true; +} + + +WRLVERSION WRLPROC::GetVRMLType( void ) +{ + return m_fileVersion; +} + + +bool WRLPROC::ReadGlob( std::string& aGlob, bool* hasComma ) +{ + aGlob.clear(); + + if( NULL != hasComma ) + *hasComma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + size_t ssize = m_buf.size(); + + while( m_buf[m_linepos] > 0x20 && m_linepos < ssize ) + { + if( ',' == m_buf[m_linepos] ) + { + // the comma is a special instance of blank space + if( NULL != hasComma ) + *hasComma = true; + + ++m_linepos; + + return true; + } + + aGlob.append( 1, m_buf[m_linepos++] ); + } + + return true; +} + + +bool WRLPROC::ReadName( std::string& aName ) +{ + aName.clear(); + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + size_t ssize = m_buf.size(); + + while( m_buf[m_linepos] > 0x20 && m_linepos < ssize ) + { + if( '[' == m_buf[m_linepos] || '{' == m_buf[m_linepos] ) + return true; + + if( m_badchars.find( m_buf[m_linepos] ) != 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_linepos; + ostr << " -- invalid character in name"; + m_error = ostr.str(); + + return false; + } + + aName.append( 1, m_buf[m_linepos++] ); + } + + return true; +} + + +bool WRLPROC::DiscardNode( void ) +{ + 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_linepos] ) + { + std::ostringstream ostr; + ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; + ostr << " * [INFO] failed on file '" << m_filename << "'\n"; + ostr << " * [INFO] expecting character '{' at line " << m_linepos; + ostr << ", column " << m_linepos; + m_error = ostr.str(); + + return false; + } + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + ++m_linepos; + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + // comments must be skipped + if( '#' == m_buf[m_linepos] ) + { + m_linepos = 0; + m_buf.clear(); + continue; + } + + if( '{' == m_buf[m_linepos] ) + { + ++m_linepos; + ++lvl; + continue; + } + + if( '}' == m_buf[m_linepos] ) + { + ++m_linepos; + --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_linepos] ) + { + ++m_linepos; + continue; + } + + // strings are handled as a special case since they may contain + // control characters and braces + if( '"' == m_buf[m_linepos] ) + { + 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_linepos << "\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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + } + + return true; +} + + +bool WRLPROC::DiscardList( void ) +{ + 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_linepos] ) + { + std::ostringstream ostr; + ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n"; + ostr << " * [INFO] failed on file '" << m_filename << "'\n"; + ostr << " * [INFO] expecting character '[' at line " << m_linepos; + ostr << ", column " << m_linepos; + m_error = ostr.str(); + + return false; + } + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + ++m_linepos; + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + // comments must be skipped + if( '#' == m_buf[m_linepos] ) + { + m_linepos = 0; + m_buf.clear(); + continue; + } + + if( '[' == m_buf[m_linepos] ) + { + ++m_linepos; + ++lvl; + continue; + } + + if( ']' == m_buf[m_linepos] ) + { + ++m_linepos; + --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_linepos] ) + { + ++m_linepos; + continue; + } + + // strings are handled as a special case since they may contain + // control characters and braces + if( '"' == m_buf[m_linepos] ) + { + 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_linepos << "\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_linepos << "\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(); + + // 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( VRML_V2 == m_fileVersion && '"' != m_buf[m_linepos] ) + { + m_error = "invalid VRML2 file (string not quoted)"; + return false; + } + + ifline = m_fileline; + + if( '"' != m_buf[m_linepos] ) + { + 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_linepos; + + if( m_linepos >= 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_linepos] ) + { + if( isesc ) + { + aSFString.append( 1, '\n' ); + isesc = false; + } + else + { + isesc = true; + } + + continue; + } + + if( '"' == m_buf[m_linepos] ) + { + if( isesc ) + aSFString.append( 1, '"' ); + else + break; + } + + // ensure that the backslash escape cannot extend beyond the first character + isesc = false; + } + + ++m_linepos; + + return true; +} + + +bool WRLPROC::ReadSFBool( bool& aSFBool ) +{ + if( !eatSpace() ) + return false; + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + 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_linepos << "\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, bool* hasComma ) +{ + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + if( NULL != hasComma ) + *hasComma = false; + + bool lComma = false; + + if( !ReadSFVec3f( aSFColor, &lComma ) ) + 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_linepos << "\n"; + ostr << " * [INFO] invalid RGB value in color triplet"; + m_error = ostr.str(); + + return false; + } + + if( NULL != hasComma ) + *hasComma = lComma; + + return true; +} + + +bool WRLPROC::ReadSFFloat( float& aSFFloat, bool* hasComma ) +{ + if( NULL != hasComma ) + *hasComma = false; + + aSFFloat = 0.0; + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + bool lComma = false; + std::string tmp; + + if( !ReadGlob( tmp, &lComma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + std::istringstream istr; + istr.str( tmp ); + + istr >> aSFFloat; + tmp.clear(); + istr >> tmp; + + if( !tmp.empty() ) + { + 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_linepos << "\n"; + ostr << " * [INFO] invalid character in SFFloat"; + m_error = ostr.str(); + + return false; + } + + if( NULL != hasComma ) + *hasComma = lComma; + + return true; +} + + +bool WRLPROC::ReadSFInt( int& aSFInt32, bool* hasComma ) +{ + if( NULL != hasComma ) + *hasComma = false; + + aSFInt32 = 0; + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + bool lComma = false; + std::string tmp; + + if( !ReadGlob( tmp, &lComma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + std::istringstream istr; + istr.str( tmp ); + + istr >> aSFInt32; + tmp.clear(); + istr >> tmp; + + if( !tmp.empty() ) + { + 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_linepos << "\n"; + ostr << " * [INFO] invalid character in SFInt"; + m_error = ostr.str(); + + return false; + } + + if( NULL != hasComma ) + *hasComma = lComma; + + return true; +} + + +bool WRLPROC::ReadSFRotation( WRLROTATION& aSFRotation, bool* hasComma ) +{ + if( NULL != hasComma ) + *hasComma = 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_linepos; + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + bool lComma = false; + std::string tmp; + + float trot[4]; + + for( int i = 0; i < 4; ++i ) + { + if( !ReadGlob( tmp, &lComma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( lComma && i != 3 ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in space delimited quartet"; + m_error = ostr.str(); + + return false; + } + + std::istringstream istr; + istr.str( tmp ); + + istr >> trot[i]; + tmp.clear(); + istr >> tmp; + + if( !tmp.empty() ) + { + 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_linepos << "\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]; + + if( NULL != hasComma ) + *hasComma = lComma; + + return true; +} + + +bool WRLPROC::ReadSFVec2f( WRLVEC2F& aSFVec2f, bool* hasComma ) +{ + if( NULL != hasComma ) + *hasComma = false; + + aSFVec2f.x = 0.0; + aSFVec2f.y = 0.0; + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + bool lComma = false; + std::string tmp; + + float tcol[2]; + + for( int i = 0; i < 2; ++i ) + { + if( !ReadGlob( tmp, &lComma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( lComma && i != 1 ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in space delimited pair"; + m_error = ostr.str(); + + return false; + } + + std::istringstream istr; + istr.str( tmp ); + + istr >> tcol[i]; + tmp.clear(); + istr >> tmp; + + if( !tmp.empty() ) + { + 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_linepos << "\n"; + ostr << " * [INFO] invalid character in space delimited pair"; + m_error = ostr.str(); + + return false; + } + + } + + aSFVec2f.x = tcol[0]; + aSFVec2f.y = tcol[1]; + + if( NULL != hasComma ) + *hasComma = lComma; + + return true; +} + + +bool WRLPROC::ReadSFVec3f( WRLVEC3F& aSFVec3f, bool* hasComma ) +{ + if( NULL != hasComma ) + *hasComma = false; + + aSFVec3f.x = 0.0; + aSFVec3f.y = 0.0; + aSFVec3f.z = 0.0; + + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + bool lComma = false; + std::string tmp; + + float tcol[3]; + + for( int i = 0; i < 3; ++i ) + { + if( !ReadGlob( tmp, &lComma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( lComma && i != 2 ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in space delimited triplet"; + m_error = ostr.str(); + + return false; + } + + std::istringstream istr; + istr.str( tmp ); + + istr >> tcol[i]; + tmp.clear(); + istr >> tmp; + + if( !tmp.empty() ) + { + 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_linepos << "\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]; + + if( NULL != hasComma ) + *hasComma = lComma; + + return true; +} + + +bool WRLPROC::ReadMFString( std::vector< std::string >& aMFString ) +{ + aMFString.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + 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_linepos] ) + m_buf.clear(); + else + break; + } + + std::string lstr; + + if( m_buf[m_linepos] != '[' ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( m_linepos >= 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFString.push_back( lstr ); + return true; + } + + ++m_linepos; + + 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_linepos << "\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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + ++m_linepos; + + 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_linepos << "\n"; + ostr << " * [INFO] problems encountered while reading list"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + } + + ++m_linepos; + return true; +} + + +bool WRLPROC::ReadMFColor( std::vector< WRLVEC3F >& aMFColor ) +{ + aMFColor.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + WRLVEC3F lcolor; + bool lcomma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( m_buf[m_linepos] != '[' ) + { + if( !ReadSFColor( lcolor, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + if( lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFColor.push_back( lcolor ); + return true; + } + + ++m_linepos; + + while( true ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( !ReadSFColor( lcolor, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + aMFColor.push_back( lcolor ); + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma missing in delimited list"; + m_error = ostr.str(); + + return false; + } + } + + ++m_linepos; + return true; +} + + +bool WRLPROC::ReadMFFloat( std::vector< float >& aMFFloat ) +{ + aMFFloat.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + float temp; + bool lcomma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( m_buf[m_linepos] != '[' ) + { + if( !ReadSFFloat( temp, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + if( lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFFloat.push_back( temp ); + return true; + } + + ++m_linepos; + + while( true ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( !ReadSFFloat( temp, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + aMFFloat.push_back( temp ); + + if( !lcomma ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma missing in delimited list"; + m_error = ostr.str(); + + return false; + } + } + + ++m_linepos; + return true; +} + + +bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 ) +{ + aMFInt32.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + int temp; + bool lcomma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( m_buf[m_linepos] != '[' ) + { + if( !ReadSFInt( temp, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + if( lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFInt32.push_back( temp ); + return true; + } + + ++m_linepos; + + while( true ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( !ReadSFInt( temp, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + aMFInt32.push_back( temp ); + + if( !lcomma ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma missing in delimited list"; + m_error = ostr.str(); + + return false; + } + } + + ++m_linepos; + return true; +} + + +bool WRLPROC::ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ) +{ + aMFRotation.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + WRLROTATION lrot; + bool lcomma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( m_buf[m_linepos] != '[' ) + { + if( !ReadSFRotation( lrot, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + if( lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFRotation.push_back( lrot ); + return true; + } + + ++m_linepos; + + while( true ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( !ReadSFRotation( lrot, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + aMFRotation.push_back( lrot ); + + if( !lcomma ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma missing in delimited list"; + m_error = ostr.str(); + + return false; + } + } + + ++m_linepos; + return true; +} + + +bool WRLPROC::ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ) +{ + aMFVec2f.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + WRLVEC2F lvec2f; + bool lcomma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( m_buf[m_linepos] != '[' ) + { + if( !ReadSFVec2f( lvec2f, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + if( lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFVec2f.push_back( lvec2f ); + return true; + } + + ++m_linepos; + + while( true ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( !ReadSFVec2f( lvec2f, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + aMFVec2f.push_back( lvec2f ); + + if( !lcomma ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma missing in delimited list"; + m_error = ostr.str(); + + return false; + } + } + + ++m_linepos; + return true; +} + + +bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) +{ + aMFVec3f.clear(); + size_t fileline = m_fileline; + size_t linepos = m_linepos; + + WRLVEC3F lvec3f; + bool lcomma = 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_linepos] ) + m_buf.clear(); + else + break; + } + + if( m_buf[m_linepos] != '[' ) + { + if( !ReadSFVec3f( lvec3f, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + if( lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma encountered in undelimited list"; + m_error = ostr.str(); + + return false; + } + + aMFVec3f.push_back( lvec3f ); + return true; + } + + ++m_linepos; + + while( true ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( !ReadSFVec3f( lvec3f, &lcomma ) ) + { + 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_linepos << "\n"; + ostr << " * [INFO] " << m_error; + m_error = ostr.str(); + + return false; + } + + aMFVec3f.push_back( lvec3f ); + + if( !lcomma ) + { + if( !eatSpace() ) + return false; + + if( ']' == m_buf[m_linepos] ) + break; + + if( ',' == m_buf[m_linepos] ) + lcomma = true; + } + + 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_linepos << "\n"; + ostr << " * [INFO] could not check characters after the string"; + m_error = ostr.str(); + + return false; + } + + if( ']' == m_buf[m_linepos] ) + break; + + if( !lcomma ) + { + 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_linepos << "\n"; + ostr << " * [INFO] comma missing in delimited list"; + m_error = ostr.str(); + + return false; + } + } + + ++m_linepos; + return true; +} diff --git a/plugins/3d/vrml/v2/wrlproc.h b/plugins/3d/vrml/v2/wrlproc.h new file mode 100644 index 0000000000..598f59ed19 --- /dev/null +++ b/plugins/3d/vrml/v2/wrlproc.h @@ -0,0 +1,104 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + */ + +/** + * @file wrlproc.h + * defines the basic input class for VRML + */ + + +#ifndef WRLPROC_H +#define WRLPROC_H + +#include +#include +#include + +#include "wrltypes.h" + +class WRLPROC +{ +private: + std::ifstream m_file; + std::string m_filename; // name of the open file + size_t m_filepos; // position in the file + size_t m_fileline; // line being processed + size_t m_linepos; // position within 'buf' + std::string m_buf; // string being parsed + + WRLVERSION m_fileVersion; // VRML file version + std::string m_error; // error message + std::string m_badchars; // characters forbidden in VRML{1|2} names + + // getRawLine reads a single non-blank line and in the case of a VRML1 file + // it checks for invalid characters (bit 8 set). If m_buf is not empty and + // not completely parsed the function returns 'true'. The file position + // parameters are updated as appropriate. + bool getRawLine( void ); + + // eatSpace discards all leading white space from the current m_linepos + // and continues until a non-empty line is found which contains non-blank + // characters + bool eatSpace( void ); + +public: + WRLPROC(); + ~WRLPROC(); + + bool Open( const std::string& aFileName ); + void Close(); + + WRLVERSION GetVRMLType( void ); + + // helper routines + + // read up to the next whitespace or comma + bool ReadGlob( std::string& aGlob, bool* hasComma = NULL ); + // read a VRML name; is similar to ReadGlob except that it enforces + // name checking rules, does not allow a comma at the end, and + // stops when a left brace or bracket is found. + bool ReadName( std::string& aName ); + bool DiscardNode( void ); // discard node data in a matched '{}' set + bool DiscardList( void ); // discard list data in a matched '[]' set + + // single variable readers + bool ReadString( std::string& aSFString ); // read a VRML string + bool ReadSFBool( bool& aSFBool ); + bool ReadSFColor( WRLVEC3F& aSFColor, bool* hasComma = NULL ); + bool ReadSFFloat( float& aSFFloat, bool* hasComma = NULL ); + bool ReadSFInt( int& aSFInt32, bool* hasComma = NULL ); + bool ReadSFRotation( WRLROTATION& aSFRotation, bool* hasComma = NULL ); + bool ReadSFVec2f( WRLVEC2F& aSFVec2f, bool* hasComma = NULL ); + bool ReadSFVec3f( WRLVEC3F& aSFVec3f, bool* hasComma = NULL ); + + // array readers + bool ReadMFString( std::vector< std::string >& aMFString ); + bool ReadMFColor( std::vector< WRLVEC3F >& aMFColor ); + bool ReadMFFloat( std::vector< float >& aMFFloat ); + bool ReadMFInt( std::vector< int >& aMFInt32 ); + bool ReadMFRotation( std::vector< WRLROTATION >& aMFRotation ); + bool ReadMFVec2f( std::vector< WRLVEC2F >& aMFVec2f ); + bool ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ); +}; + +#endif // WRLPROC_H diff --git a/plugins/3d/vrml/v2/wrltypes.h b/plugins/3d/vrml/v2/wrltypes.h new file mode 100644 index 0000000000..138dade77e --- /dev/null +++ b/plugins/3d/vrml/v2/wrltypes.h @@ -0,0 +1,130 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + */ + +/** + * @file wrltypes.h + * declares some compound types used for VRML + */ + + +#ifndef WRLTYPES_H +#define WRLTYPES_H + + +// version of the VRML file being parsed +enum WRLVERSION +{ + VRML_INVALID = 0, // not a valid VRML file + VRML_V1, + VRML_V2 +}; + + +// VRML Node Types +// These are used to look up node names and to quickly +// determine what routine to invoke to read a section of +// a file. +enum WRLNODES +{ + WRL2_BASE = 0, // not really a VRML node but we need a top level virtual node + WRL2_BEGIN, + WRL2_ANCHOR = WRL2_BEGIN, + WRL2_APPEARANCE, + WRL2_AUDIOCLIP, + WRL2_BACKGROUND, + WRL2_BILLBOARD, + WRL2_BOX, + WRL2_COLLISION, + WRL2_COLOR, + WRL2_COLORINTERPOLATOR, + WRL2_CONE, + WRL2_COORDINATE, + WRL2_COORDINATEINTERPOLATOR, + WRL2_CYLINDER, + WRL2_CYLINDERSENSOR, + WRL2_DIRECTIONALLIGHT, + WRL2_ELEVATIONGRID, + WRL2_EXTRUSION, + WRL2_FOG, + WRL2_FONTSTYLE, + WRL2_GROUP, + WRL2_IMAGETEXTURE, + WRL2_INDEXEDFACESET, + WRL2_INDEXEDLINESET, + WRL2_INLINE, + WRL2_LOD, + WRL2_MATERIAL, + WRL2_MOVIETEXTURE, + WRL2_NAVIGATIONINFO, + WRL2_NORMAL, + WRL2_NORMALINTERPOLATOR, + WRL2_ORIENTATIONINTERPOLATOR, + WRL2_PIXELTEXTURE, + WRL2_PLANESENSOR, + WRL2_POINTLIGHT, + WRL2_POINTSET, + WRL2_POSITIONINTERPOLATOR, + WRL2_PROXIMITYSENSOR, + WRL2_SCALARINTERPOLATOR, + WRL2_SCRIPT, + WRL2_SHAPE, + WRL2_SOUND, + WRL2_SPHERE, + WRL2_SPHERESENSOR, + WRL2_SPOTLIGHT, + WRL2_SWITCH, + WRL2_TEXT, + WRL2_TEXTURECOORDINATE, + WRL2_TEXTURETRANSFORM, + WRL2_TIMESENSOR, + WRL2_TOUCHSENSOR, + WRL2_TRANSFORM, + WRL2_VIEWPOINT, + WRL2_VISIBILITYSENSOR, + WRL2_WORLDINFO, + WRL2_END +}; + + +struct WRLVEC2F +{ + float x; + float y; +}; + +struct WRLVEC3F +{ + float x; + float y; + float z; +}; + +struct WRLROTATION +{ + float x; + float y; + float z; + float w; +}; + +#endif // WRLTYPES_H diff --git a/plugins/3d/vrml/vrml.cpp b/plugins/3d/vrml/vrml.cpp new file mode 100644 index 0000000000..c392865067 --- /dev/null +++ b/plugins/3d/vrml/vrml.cpp @@ -0,0 +1,191 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + */ + +/* + * Description: + * This plugin implements the legacy kicad VRML1/VRML2 parsers. + * This VRML plugin will invoke a VRML1 or VRML2 parser depending + * on the identifying information in the file header: + * + * #VRML V1.0 ascii + * #VRML V2.0 utf8 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "plugins/3d/3d_plugin.h" +#include "plugins/3dapi/ifsg_all.h" +#include "wrlproc.h" + + +#define PLUGIN_VRML_MAJOR 1 +#define PLUGIN_VRML_MINOR 0 +#define PLUGIN_VRML_PATCH 0 +#define PLUGIN_VRML_REVNO 0 + + +const char* GetKicadPluginName( void ) +{ + return "PLUGIN_3D_VRML"; +} + + +void GetPluginVersion( unsigned char* Major, + unsigned char* Minor, unsigned char* Patch, unsigned char* Revision ) +{ + if( Major ) + *Major = PLUGIN_VRML_MAJOR; + + if( Minor ) + *Minor = PLUGIN_VRML_MINOR; + + if( Patch ) + *Patch = PLUGIN_VRML_PATCH; + + if( Revision ) + *Revision = PLUGIN_VRML_REVNO; + + return; +} + +// number of extensions supported +#ifdef _WIN32 +#define NEXTS 1 +#else +#define NEXTS 2 +#endif + +// number of filter sets supported +#define NFILS 1 + +static char ext0[] = "wrl"; + +#ifdef _WIN32 +static char fil0[] = "VRML 1.0/2.0 (*.wrl)|*.wrl"; +#else +static char ext1[] = "WRL"; +static char fil0[] = "VRML 1.0/2.0 (*.wrl;*.WRL)|*.wrl;*.WRL"; +#endif + +static struct FILE_DATA +{ + char const* extensions[NEXTS]; + char const* filters[NFILS]; + + FILE_DATA() + { + extensions[0] = ext0; + filters[0] = fil0; + +#ifndef _WIN32 + extensions[1] = ext1; +#endif + + return; + } + +} file_data; + + +int GetNExtensions( void ) +{ + return NEXTS; +} + + +char const* GetModelExtension( int aIndex ) +{ + if( aIndex < 0 || aIndex >= NEXTS ) + return NULL; + + return file_data.extensions[aIndex]; +} + + +int GetNFilters( void ) +{ + return NFILS; +} + + +char const* GetFileFilter( int aIndex ) +{ + if( aIndex < 0 || aIndex >= NFILS ) + return NULL; + + return file_data.filters[aIndex]; +} + + +bool CanRender( void ) +{ + // this plugin supports rendering of IDF component outlines + return true; +} + + +class LOCALESWITCH +{ +public: + LOCALESWITCH() + { + setlocale( LC_NUMERIC, "C" ); + } + + ~LOCALESWITCH() + { + setlocale( LC_NUMERIC, "" ); + } +}; + + +SCENEGRAPH* Load( char const* aFileName ) +{ + if( NULL == aFileName ) + return NULL; + + wxString fname = wxString::FromUTF8Unchecked( aFileName ); + + if( !wxFileName::FileExists( fname ) ) + return NULL; + + LOCALESWITCH switcher; + + // VRML file processor + WRLPROC proc; + + if( !proc.Open( std::string( fname.ToUTF8() ) ) ) + return NULL; + + if( proc.GetVRMLType() == VRML_V1 ) + std::cout << "XXX: Processing VRML 1.0 file\n"; + else + std::cout << "XXX: Processing VRML 2.0 file\n"; + + return NULL; +}