Browse Source

Merge branch 'master' into coverity_scan

Kim Kulling 8 years ago
parent
commit
e6cfe6b5c8
100 changed files with 6357 additions and 3294 deletions
  1. 2 1
      .travis.sh
  2. 38 9
      .travis.yml
  3. 13 2
      CMakeLists.txt
  4. 8 8
      Readme.md
  5. 1 1
      code/3DSExporter.cpp
  6. 1 1
      code/AMFImporter_Postprocess.cpp
  7. 12 19
      code/Assimp.cpp
  8. 2 1
      code/AssimpCExport.cpp
  9. 10 43
      code/BaseImporter.cpp
  10. 1 5
      code/BaseImporter.h
  11. 2 2
      code/BlenderModifier.cpp
  12. 3 7
      code/CMakeLists.txt
  13. 1 1
      code/ColladaExporter.cpp
  14. 12 4
      code/ColladaLoader.cpp
  15. 1 1
      code/Exporter.cpp
  16. 2 3
      code/HalfLifeFileData.h
  17. 40 17
      code/IFCLoader.cpp
  18. 90 5
      code/IOStreamBuffer.h
  19. 1 1
      code/IRRLoader.cpp
  20. 1 1
      code/IRRLoader.h
  21. 1 0
      code/LWOAnimation.cpp
  22. 3 4
      code/LWOAnimation.h
  23. 1 1
      code/LWSLoader.cpp
  24. 1 1
      code/LWSLoader.h
  25. 12 15
      code/MD3FileData.h
  26. 1 1
      code/MD3Loader.cpp
  27. 1 1
      code/MDCFileData.h
  28. 51 76
      code/MDLFileData.h
  29. 40 0
      code/MMDCpp14.h
  30. 40 0
      code/MMDPmdParser.h
  31. 42 10
      code/MMDPmxParser.cpp
  32. 40 0
      code/MMDPmxParser.h
  33. 40 0
      code/MMDVmdParser.h
  34. 32 43
      code/ObjFileParser.cpp
  35. 4 5
      code/ObjFileParser.h
  36. 5 3
      code/ObjTools.h
  37. 1 1
      code/OptimizeGraph.cpp
  38. 1 1
      code/OptimizeMeshes.cpp
  39. 2 4
      code/PlyExporter.h
  40. 855 911
      code/PlyLoader.cpp
  41. 14 47
      code/PlyLoader.h
  42. 930 754
      code/PlyParser.cpp
  43. 39 56
      code/PlyParser.h
  44. 1 1
      code/PretransformVertices.cpp
  45. 22 9
      code/SIBImporter.cpp
  46. 25 32
      code/STEPFileEncoding.cpp
  47. 3 3
      code/STLLoader.cpp
  48. 1 1
      code/SceneCombiner.cpp
  49. 2 3
      code/SpatialSort.cpp
  50. 2 1
      code/StepExporter.cpp
  51. 1 1
      code/Subdivision.cpp
  52. 2 1
      code/XFileExporter.cpp
  53. 10 3
      code/fast_atof.h
  54. 5 2
      code/glTFExporter.cpp
  55. 0 539
      contrib/ConvertUTF/ConvertUTF.c
  56. 0 151
      contrib/ConvertUTF/ConvertUTF.h
  57. 0 43
      contrib/ConvertUTF/readme.txt
  58. 114 8
      contrib/openddlparser/CMakeLists.txt
  59. 3 0
      contrib/openddlparser/CREDITS
  60. 2 2
      contrib/openddlparser/README.md
  61. 14 6
      contrib/openddlparser/code/DDLNode.cpp
  62. 35 9
      contrib/openddlparser/code/OpenDDLCommon.cpp
  63. 1 55
      contrib/openddlparser/code/OpenDDLExport.cpp
  64. 80 65
      contrib/openddlparser/code/OpenDDLParser.cpp
  65. 96 0
      contrib/openddlparser/code/OpenDDLStream.cpp
  66. 17 18
      contrib/openddlparser/code/Value.cpp
  67. 19 10
      contrib/openddlparser/include/openddlparser/DDLNode.h
  68. 3 4
      contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
  69. 3 27
      contrib/openddlparser/include/openddlparser/OpenDDLExport.h
  70. 11 1
      contrib/openddlparser/include/openddlparser/OpenDDLParser.h
  71. 36 8
      contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
  72. 89 0
      contrib/openddlparser/include/openddlparser/OpenDDLStream.h
  73. 7 3
      contrib/openddlparser/include/openddlparser/Value.h
  74. 23 31
      contrib/poly2tri/poly2tri/common/shapes.cc
  75. 29 31
      contrib/poly2tri/poly2tri/common/shapes.h
  76. 32 8
      contrib/poly2tri/poly2tri/common/utils.h
  77. 2 3
      contrib/poly2tri/poly2tri/poly2tri.h
  78. 3 4
      contrib/poly2tri/poly2tri/sweep/advancing_front.cc
  79. 3 3
      contrib/poly2tri/poly2tri/sweep/advancing_front.h
  80. 4 5
      contrib/poly2tri/poly2tri/sweep/cdt.cc
  81. 17 17
      contrib/poly2tri/poly2tri/sweep/cdt.h
  82. 91 42
      contrib/poly2tri/poly2tri/sweep/sweep.cc
  83. 28 21
      contrib/poly2tri/poly2tri/sweep/sweep.h
  84. 31 22
      contrib/poly2tri/poly2tri/sweep/sweep_context.cc
  85. 17 17
      contrib/poly2tri/poly2tri/sweep/sweep_context.h
  86. 12 0
      contrib/utf8cpp/doc/ReleaseNotes
  87. 1789 0
      contrib/utf8cpp/doc/utf8cpp.html
  88. 34 0
      contrib/utf8cpp/source/utf8.h
  89. 327 0
      contrib/utf8cpp/source/utf8/checked.h
  90. 329 0
      contrib/utf8cpp/source/utf8/core.h
  91. 228 0
      contrib/utf8cpp/source/utf8/unchecked.h
  92. 0 2
      include/assimp/SceneCombiner.h
  93. 0 2
      include/assimp/color4.inl
  94. 16 4
      include/assimp/material.inl
  95. 4 3
      include/assimp/matrix4x4.h
  96. 1 4
      port/PyAssimp/pyassimp/helper.py
  97. 1 3
      port/PyAssimp/setup.py
  98. 28 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln
  99. 102 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h
  100. 205 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

+ 2 - 1
.travis.sh

@@ -5,7 +5,8 @@ function generate()
 
 
 if [ $ANDROID ]; then
 if [ $ANDROID ]; then
     ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
     ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
-else
+fi
+if [ "$TRAVIS_OS_NAME" = "linux" ]; then
     generate \
     generate \
     && make -j4 \
     && make -j4 \
     && sudo make install \
     && sudo make install \

+ 38 - 9
.travis.yml

@@ -1,23 +1,52 @@
-env:
-  global:
-    - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
+sudo: required
+language: cpp
 
 
 before_install:
 before_install:
-  - sudo apt-get update -qq
-  - sudo apt-get install cmake
-  - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
+  - if [ "$TRAVIS_OS_NAME" =   "osx" ]; then brew install cmake python3 homebrew/x11/freeglut; fi
+  - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
+  # install latest LCOV (1.9 was failing)
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz && tar xf lcov_1.11.orig.tar.gz && sudo make -C lcov-1.11/ install && gem install coveralls-lcov && lcov --version && g++ --version ; fi
 
 
-language: cpp
+branches:
+  only:
+    - master
+
+osx_image: xcode8.3
+
+env:
+  global:
+    - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
+    - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
+  matrix:
+    - LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
+    - LINUX=1 TRAVIS_NO_EXPORT=NO  ENABLE_COVERALLS=OFF
+    - LINUX=1 SHARED_BUILD=ON      ENABLE_COVERALLS=OFF
+    - LINUX=1 SHARED_BUILD=OFF     ENABLE_COVERALLS=OFF
+    #exclude:
+    #    - os: linux
+    #      compiler: clang
+    #    - os: osx
+    #      compiler: gcc  
 
 
 compiler:
 compiler:
   - gcc
   - gcc
   - clang
   - clang
 
 
 before_script:
 before_script:
-  cmake .
+  # init coverage to 0 (optional)
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi
 
 
 script:
 script:
-  make
+  - export COVERALLS_SERVICE_NAME=travis-ci
+  - export COVERALLS_REPO_TOKEN=abc12345
+  - . ./.travis.sh
+os:
+  - linux
+  - osx
+ 
+after_success:
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi
 
 
 addons:
 addons:
   coverity_scan:
   coverity_scan:

+ 13 - 2
CMakeLists.txt

@@ -89,6 +89,10 @@ OPTION ( BUILD_DOCS
    OFF
    OFF
 )
 )
 
 
+if (WIN32)
+    add_definitions( -DWIN32_LEAN_AND_MEAN )
+endif()
+
 IF(MSVC)
 IF(MSVC)
   set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   OPTION( ASSIMP_INSTALL_PDB
   OPTION( ASSIMP_INSTALL_PDB
@@ -141,6 +145,13 @@ IF(ASSIMP_DOUBLE_PRECISION)
   ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
   ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
 ENDIF(ASSIMP_DOUBLE_PRECISION)
 ENDIF(ASSIMP_DOUBLE_PRECISION)
 
 
+# Check for OpenMP support
+find_package(OpenMP)
+if (OPENMP_FOUND)
+    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+endif()
+
 configure_file(
 configure_file(
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
   ${CMAKE_CURRENT_BINARY_DIR}/revision.h
   ${CMAKE_CURRENT_BINARY_DIR}/revision.h
@@ -157,7 +168,7 @@ include_directories(
     ${CMAKE_CURRENT_BINARY_DIR}/include
     ${CMAKE_CURRENT_BINARY_DIR}/include
 )
 )
 
 
-SET(CMAKE_MODULE_PATH       "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
+LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
 SET(LIBASSIMP_COMPONENT     "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" )
 SET(LIBASSIMP_COMPONENT     "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" )
 SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" )
 SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" )
 SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
 SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
@@ -178,7 +189,7 @@ ENDIF( UNIX )
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
   # hide all not-exported symbols
   # hide all not-exported symbols
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x")
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x")
-  SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -fPIC)
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
   SET(LIBSTDC++_LIBRARIES -lstdc++)
   SET(LIBSTDC++_LIBRARIES -lstdc++)
 ELSEIF(MSVC)
 ELSEIF(MSVC)
   # enable multi-core compilation with MSVC
   # enable multi-core compilation with MSVC

+ 8 - 8
Readme.md

@@ -1,6 +1,6 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ==================================
 ==================================
-
+### Current build status ###
 [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
 [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
 <a href="https://scan.coverity.com/projects/5607">
 <a href="https://scan.coverity.com/projects/5607">
@@ -9,22 +9,19 @@ Open Asset Import Library (assimp)
 </a>
 </a>
 <span class="badge-patreon"><a href="https://www.patreon.com/assimp" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
 <span class="badge-patreon"><a href="https://www.patreon.com/assimp" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
 [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
 [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
+[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 <br>
 <br>
 
 
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 
 
 Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 
 
-This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories.
-The current build status is:
-
-Gitter chat: [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
+This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
 
 
-And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type
-> /join #assetimporterlib
+One-off donations via PayPal:
+<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
 
 
 <br>
 <br>
-__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
 
 
 Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 
 
@@ -100,6 +97,9 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
 
 
+### Other tools ###
+[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
+
 #### Repository structure ####
 #### Repository structure ####
 Open Asset Import Library is implemented in C++. The directory structure is:
 Open Asset Import Library is implemented in C++. The directory structure is:
 
 

+ 1 - 1
code/3DSExporter.cpp

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "3DSExporter.h"
 #include "3DSExporter.h"
 #include "3DSLoader.h"
 #include "3DSLoader.h"
 #include "3DSHelper.h"
 #include "3DSHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "SplitLargeMeshes.h"
 #include "SplitLargeMeshes.h"
 #include "StringComparison.h"
 #include "StringComparison.h"
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>

+ 1 - 1
code/AMFImporter_Postprocess.cpp

@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter.hpp"
 #include "AMFImporter.hpp"
 
 
 // Header files, Assimp.
 // Header files, Assimp.
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StandardShapes.h"
 #include "StandardShapes.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 
 

+ 12 - 19
code/Assimp.cpp

@@ -66,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 using namespace Assimp;
 using namespace Assimp;
 
 
-namespace Assimp
-{
+namespace Assimp {
     // underlying structure for aiPropertyStore
     // underlying structure for aiPropertyStore
     typedef BatchLoader::PropertyMap PropertyMap;
     typedef BatchLoader::PropertyMap PropertyMap;
 
 
@@ -110,12 +109,11 @@ static std::mutex gLogStreamMutex;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Custom LogStream implementation for the C-API
 // Custom LogStream implementation for the C-API
-class LogToCallbackRedirector : public LogStream
-{
+class LogToCallbackRedirector : public LogStream {
 public:
 public:
     explicit LogToCallbackRedirector(const aiLogStream& s)
     explicit LogToCallbackRedirector(const aiLogStream& s)
-        : stream (s)    {
-            ai_assert(NULL != s.callback);
+    : stream (s)    {
+        ai_assert(NULL != s.callback);
     }
     }
 
 
     ~LogToCallbackRedirector()  {
     ~LogToCallbackRedirector()  {
@@ -146,8 +144,7 @@ private:
 };
 };
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ReportSceneNotFoundError()
-{
+void ReportSceneNotFoundError() {
     DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
     DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
         "The C-API does not accept scenes produced by the C++ API and vice versa");
         "The C-API does not accept scenes produced by the C++ API and vice versa");
 
 
@@ -156,22 +153,18 @@ void ReportSceneNotFoundError()
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Reads the given file and returns its content.
 // Reads the given file and returns its content.
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
-{
+const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
     return aiImportFileEx(pFile,pFlags,NULL);
     return aiImportFileEx(pFile,pFlags,NULL);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS)
-{
+const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS) {
     return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
     return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
-    aiFileIO* pFS,
-    const aiPropertyStore* props)
-{
+const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, 
+        aiFileIO* pFS, const aiPropertyStore* props) {
     ai_assert(NULL != pFile);
     ai_assert(NULL != pFile);
 
 
     const aiScene* scene = NULL;
     const aiScene* scene = NULL;
@@ -190,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
         pimpl->mMatrixProperties = pp->matrices;
         pimpl->mMatrixProperties = pp->matrices;
     }
     }
     // setup a custom IO system if necessary
     // setup a custom IO system if necessary
-    if (pFS)    {
+    if (pFS) {
         imp->SetIOHandler( new CIOSystemWrapper (pFS) );
         imp->SetIOHandler( new CIOSystemWrapper (pFS) );
     }
     }
 
 
@@ -201,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
     if( scene)  {
     if( scene)  {
         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
         priv->mOrigImporter = imp;
         priv->mOrigImporter = imp;
-    }
-    else    {
+    } else {
         // if failed, extract error code and destroy the import
         // if failed, extract error code and destroy the import
         gLastErrorString = imp->GetErrorString();
         gLastErrorString = imp->GetErrorString();
         delete imp;
         delete imp;
@@ -210,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
 
 
     // return imported data. If the import failed the pointer is NULL anyways
     // return imported data. If the import failed the pointer is NULL anyways
     ASSIMP_END_EXCEPTION_REGION(const aiScene*);
     ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+    
     return scene;
     return scene;
 }
 }
 
 

+ 2 - 1
code/AssimpCExport.cpp

@@ -45,8 +45,9 @@ Assimp C export interface. See Exporter.cpp for some notes.
 */
 */
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
+
 #include "CInterfaceIOWrapper.h"
 #include "CInterfaceIOWrapper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "ScenePrivate.h"
 #include "ScenePrivate.h"
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
 
 

+ 10 - 43
code/BaseImporter.cpp

@@ -303,24 +303,13 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
     return false;
     return false;
 }
 }
 
 
-#include "../contrib/ConvertUTF/ConvertUTF.h"
-
-// ------------------------------------------------------------------------------------------------
-void ReportResult(ConversionResult res)
-{
-    if(res == sourceExhausted) {
-        DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails");
-    }
-    else if(res == sourceIllegal) {
-        DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails");
-    }
-}
+#include "../contrib/utf8cpp/source/utf8.h"
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Convert to UTF8 data
 // Convert to UTF8 data
 void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 {
 {
-    ConversionResult result;
+    //ConversionResult result;
     if(data.size() < 8) {
     if(data.size() < 8) {
         throw DeadlyImportError("File is too small");
         throw DeadlyImportError("File is too small");
     }
     }
@@ -333,7 +322,8 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
         data.resize(data.size()-3);
         data.resize(data.size()-3);
         return;
         return;
     }
     }
-
+    
+    
     // UTF 32 BE with BOM
     // UTF 32 BE with BOM
     if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
     if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
 
 
@@ -347,21 +337,10 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
         DefaultLogger::get()->debug("Found UTF-32 BOM ...");
         DefaultLogger::get()->debug("Found UTF-32 BOM ...");
 
 
-        const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1;
-        char* dstart,*dend;
         std::vector<char> output;
         std::vector<char> output;
-        do {
-            output.resize(output.size()?output.size()*3/2:data.size()/2);
-            dstart = &output.front(),dend = &output.back()+1;
-
-            result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
-        } while(result == targetExhausted);
-
-        ReportResult(result);
-
-        // copy to output buffer.
-        const size_t outlen = (size_t)(dstart-&output.front());
-        data.assign(output.begin(),output.begin()+outlen);
+        int *ptr = (int*)&data[ 0 ];
+        int *end = ptr + ( data.size() / sizeof(int) ) +1;
+        utf8::utf32to8( ptr, end, back_inserter(output));
         return;
         return;
     }
     }
 
 
@@ -378,21 +357,9 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
         DefaultLogger::get()->debug("Found UTF-16 BOM ...");
         DefaultLogger::get()->debug("Found UTF-16 BOM ...");
 
 
-        const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
-        char* dstart,*dend;
-        std::vector<char> output;
-        do {
-            output.resize(output.size()?output.size()*3/2:data.size()*3/4);
-            dstart = &output.front(),dend = &output.back()+1;
-
-            result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
-        } while(result == targetExhausted);
-
-        ReportResult(result);
-
-        // copy to output buffer.
-        const size_t outlen = (size_t)(dstart-&output.front());
-        data.assign(output.begin(),output.begin()+outlen);
+        std::vector<unsigned char> output;
+        int16_t *ptr = (int16_t*) &data[ 0 ];
+        utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
         return;
         return;
     }
     }
 }
 }

+ 1 - 5
code/BaseImporter.h

@@ -61,7 +61,6 @@ class BaseProcess;
 class SharedPostProcessInfo;
 class SharedPostProcessInfo;
 class IOStream;
 class IOStream;
 
 
-
 // utility to do char4 to uint32 in a portable manner
 // utility to do char4 to uint32 in a portable manner
 #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
 #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
     (string[1] << 16) + (string[2] << 8) + string[3]))
     (string[1] << 16) + (string[2] << 8) + string[3]))
@@ -194,14 +193,11 @@ public:
         const Importer* pImp
         const Importer* pImp
         );
         );
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Called by #Importer::GetImporterInfo to get a description of
     /** Called by #Importer::GetImporterInfo to get a description of
      *  some loader features. Importers must provide this information. */
      *  some loader features. Importers must provide this information. */
     virtual const aiImporterDesc* GetInfo() const = 0;
     virtual const aiImporterDesc* GetInfo() const = 0;
 
 
-
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Called by #Importer::GetExtensionList for each loaded importer.
     /** Called by #Importer::GetExtensionList for each loaded importer.
      *  Take the extension list contained in the structure returned by
      *  Take the extension list contained in the structure returned by
@@ -317,7 +313,7 @@ public: // static utilities
      *  @param Size of one token, in bytes. Maximally 16 bytes.
      *  @param Size of one token, in bytes. Maximally 16 bytes.
      *  @return true if one of the given tokens was found
      *  @return true if one of the given tokens was found
      *
      *
-     *  @note For convinence, the check is also performed for the
+     *  @note For convenience, the check is also performed for the
      *  byte-swapped variant of all tokens (big endian). Only for
      *  byte-swapped variant of all tokens (big endian). Only for
      *  tokens of size 2,4.
      *  tokens of size 2,4.
      */
      */

+ 2 - 2
code/BlenderModifier.cpp

@@ -43,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of some blender modifiers (i.e subdivision, mirror).
  *  @brief Implementation of some blender modifiers (i.e subdivision, mirror).
  */
  */
 
 
-
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
+
 #include "BlenderModifier.h"
 #include "BlenderModifier.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Subdivision.h"
 #include "Subdivision.h"
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <memory>
 #include <memory>

+ 3 - 7
code/CMakeLists.txt

@@ -96,6 +96,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/Exporter.hpp
   ${HEADER_PATH}/Exporter.hpp
   ${HEADER_PATH}/DefaultIOStream.h
   ${HEADER_PATH}/DefaultIOStream.h
   ${HEADER_PATH}/DefaultIOSystem.h
   ${HEADER_PATH}/DefaultIOSystem.h
+  ${HEADER_PATH}/SceneCombiner.h
 )
 )
 
 
 SET( Core_SRCS
 SET( Core_SRCS
@@ -148,7 +149,6 @@ SET( Common_SRCS
   SpatialSort.cpp
   SpatialSort.cpp
   SpatialSort.h
   SpatialSort.h
   SceneCombiner.cpp
   SceneCombiner.cpp
-  SceneCombiner.h
   ScenePreprocessor.cpp
   ScenePreprocessor.cpp
   ScenePreprocessor.h
   ScenePreprocessor.h
   SkeletonMeshBuilder.cpp
   SkeletonMeshBuilder.cpp
@@ -695,11 +695,6 @@ SET( Extra_SRCS
 )
 )
 SOURCE_GROUP( Extra FILES ${Extra_SRCS})
 SOURCE_GROUP( Extra FILES ${Extra_SRCS})
 
 
-SET( ConvertUTF_SRCS
-  ../contrib/ConvertUTF/ConvertUTF.h
-  ../contrib/ConvertUTF/ConvertUTF.c
-)
-SOURCE_GROUP( ConvertUTF FILES ${ConvertUTF_SRCS})
 
 
 SET( Clipper_SRCS
 SET( Clipper_SRCS
   ../contrib/clipper/clipper.hpp
   ../contrib/clipper/clipper.hpp
@@ -737,10 +732,12 @@ SET ( openddl_parser_SRCS
   ../contrib/openddlparser/code/OpenDDLCommon.cpp
   ../contrib/openddlparser/code/OpenDDLCommon.cpp
   ../contrib/openddlparser/code/OpenDDLExport.cpp
   ../contrib/openddlparser/code/OpenDDLExport.cpp
   ../contrib/openddlparser/code/Value.cpp
   ../contrib/openddlparser/code/Value.cpp
+  ../contrib/openddlparser/code/OpenDDLStream.cpp
   ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
+  ../contrib/openddlparser/include/openddlparser/OpenDDLStream.h
   ../contrib/openddlparser/include/openddlparser/DDLNode.h
   ../contrib/openddlparser/include/openddlparser/DDLNode.h
   ../contrib/openddlparser/include/openddlparser/Value.h
   ../contrib/openddlparser/include/openddlparser/Value.h
 )
 )
@@ -835,7 +832,6 @@ SET( assimp_src
 
 
   # Third-party libraries
   # Third-party libraries
   ${IrrXML_SRCS}
   ${IrrXML_SRCS}
-  ${ConvertUTF_SRCS}
   ${unzip_compile_SRCS}
   ${unzip_compile_SRCS}
   ${Poly2Tri_SRCS}
   ${Poly2Tri_SRCS}
   ${Clipper_SRCS}
   ${Clipper_SRCS}

+ 1 - 1
code/ColladaExporter.cpp

@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ColladaExporter.h"
 #include "ColladaExporter.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include "XMLTools.h"
 #include "XMLTools.h"
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>

+ 12 - 4
code/ColladaLoader.cpp

@@ -1726,6 +1726,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
 aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
     const Collada::Effect& pEffect, const std::string& pName)
     const Collada::Effect& pEffect, const std::string& pName)
 {
 {
+    aiString result;
+
     // recurse through the param references until we end up at an image
     // recurse through the param references until we end up at an image
     std::string name = pName;
     std::string name = pName;
     while( 1)
     while( 1)
@@ -1744,11 +1746,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     if( imIt == pParser.mImageLibrary.end())
     if( imIt == pParser.mImageLibrary.end())
     {
     {
-        throw DeadlyImportError( format() <<
-            "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
-    }
+        //missing texture should not stop the conversion
+        //throw DeadlyImportError( format() <<
+        //    "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
 
 
-    aiString result;
+        DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
+
+        //set default texture file name
+        result.Set(name + ".jpg");
+        ConvertPath(result);
+        return result;
+    }
 
 
     // if this is an embedded texture image setup an aiTexture for it
     // if this is an embedded texture image setup an aiTexture for it
     if (imIt->second.mFileName.empty())
     if (imIt->second.mFileName.empty())

+ 1 - 1
code/Exporter.cpp

@@ -54,7 +54,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
 
 #include "BlobIOSystem.h"
 #include "BlobIOSystem.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "BaseProcess.h"
 #include "BaseProcess.h"
 #include "Importer.h" // need this for GetPostProcessingStepInstanceList()
 #include "Importer.h" // need this for GetPostProcessingStepInstanceList()
 
 

+ 2 - 3
code/HalfLifeFileData.h

@@ -66,8 +66,7 @@ namespace MDL   {
  *  \brief Data structure for the HL2 main header
  *  \brief Data structure for the HL2 main header
  */
  */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
-struct Header_HL2
-{
+struct Header_HL2 {
     //! magic number: "IDST"/"IDSQ"
     //! magic number: "IDST"/"IDSQ"
     char    ident[4];
     char    ident[4];
 
 
@@ -139,7 +138,7 @@ struct Header_HL2
     //! Number of animation transitions
     //! Number of animation transitions
     int32_t         numtransitions;
     int32_t         numtransitions;
     int32_t         transitionindex;
     int32_t         transitionindex;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #include "./../include/assimp/Compiler/poppack1.h"
 #include "./../include/assimp/Compiler/poppack1.h"
 
 

+ 40 - 17
code/IFCLoader.cpp

@@ -882,6 +882,7 @@ void ProcessSpatialStructures(ConversionData& conv)
         }
         }
     }
     }
 
 
+	std::vector<aiNode*> nodes;
 
 
     for(const STEP::LazyObject* lz : *range) {
     for(const STEP::LazyObject* lz : *range) {
         const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
         const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
@@ -890,20 +891,19 @@ void ProcessSpatialStructures(ConversionData& conv)
         }
         }
         IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():""));
         IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():""));
 
 
-        // the primary site is referenced by an IFCRELAGGREGATES element which assigns it to the IFCPRODUCT
+        // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT
         const STEP::DB::RefMap& refs = conv.db.GetRefs();
         const STEP::DB::RefMap& refs = conv.db.GetRefs();
-        STEP::DB::RefMapRange range = refs.equal_range(conv.proj.GetID());
-        for(;range.first != range.second; ++range.first) {
-            if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
+        STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID());
+        for(; ref_range.first != ref_range.second; ++ref_range.first) {
+            if(const IfcRelAggregates* const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr<IfcRelAggregates>()) {
 
 
                 for(const IfcObjectDefinition& def : aggr->RelatedObjects) {
                 for(const IfcObjectDefinition& def : aggr->RelatedObjects) {
                     // comparing pointer values is not sufficient, we would need to cast them to the same type first
                     // comparing pointer values is not sufficient, we would need to cast them to the same type first
                     // as there is multiple inheritance in the game.
                     // as there is multiple inheritance in the game.
                     if (def.GetID() == prod->GetID()) {
                     if (def.GetID() == prod->GetID()) {
                         IFCImporter::LogDebug("selecting this spatial structure as root structure");
                         IFCImporter::LogDebug("selecting this spatial structure as root structure");
-                        // got it, this is the primary site.
-                        conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
-                        return;
+                        // got it, this is one primary site.
+						nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
                     }
                     }
                 }
                 }
 
 
@@ -911,19 +911,42 @@ void ProcessSpatialStructures(ConversionData& conv)
         }
         }
     }
     }
 
 
+	size_t nb_nodes = nodes.size();
 
 
-    IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite");
-    for(const STEP::LazyObject* lz : *range) {
-        const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
-        if(!prod) {
-            continue;
-        }
+	if (nb_nodes == 0) {
+		IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite");
+		for (const STEP::LazyObject* lz : *range) {
+			const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
+			if (!prod) {
+				continue;
+			}
 
 
-        conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
-        return;
-    }
+			nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
+		}
+
+		nb_nodes = nodes.size();
+	}
+
+	if (nb_nodes == 1) {
+		conv.out->mRootNode = nodes[0];
+	}
+	else if (nb_nodes > 1) {
+		conv.out->mRootNode = new aiNode("Root");
+		conv.out->mRootNode->mParent = NULL;
+		conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
+		conv.out->mRootNode->mChildren = new aiNode*[conv.out->mRootNode->mNumChildren];
+		
+		for (size_t i = 0; i < nb_nodes; ++i) {
+			aiNode* node = nodes[i];
+
+			node->mParent = conv.out->mRootNode;
 
 
-    IFCImporter::ThrowException("failed to determine primary site element");
+			conv.out->mRootNode->mChildren[i] = node;
+		}
+	}
+	else {
+		IFCImporter::ThrowException("failed to determine primary site element");
+	}
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 90 - 5
code/IOStreamBuffer.h

@@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
 
 
+#include <vector>
+
 namespace Assimp {
 namespace Assimp {
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -69,8 +71,8 @@ public:
     /// @return true if successful.
     /// @return true if successful.
     bool close();
     bool close();
 
 
-    /// @brief  Returns the filesize.
-    /// @return The filesize.
+    /// @brief  Returns the file-size.
+    /// @return The file-size.
     size_t size() const;
     size_t size() const;
     
     
     /// @brief  Returns the cache size.
     /// @brief  Returns the cache size.
@@ -96,7 +98,17 @@ public:
     /// @brief  Will read the next line.
     /// @brief  Will read the next line.
     /// @param  buffer      The buffer for the next line.
     /// @param  buffer      The buffer for the next line.
     /// @return true if successful.
     /// @return true if successful.
-    bool getNextLine( std::vector<T> &buffer );
+    bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
+
+    /// @brief  Will read the next line ascii or binary end line char.
+    /// @param  buffer      The buffer for the next line.
+    /// @return true if successful.
+    bool getNextLine(std::vector<T> &buffer);
+
+    /// @brief  Will read the next block.
+    /// @param  buffer      The buffer for the next block.
+    /// @return true if successful.
+    bool getNextBlock( std::vector<T> &buffer );
 
 
 private:
 private:
     IOStream *m_stream;
     IOStream *m_stream;
@@ -227,15 +239,35 @@ size_t IOStreamBuffer<T>::getFilePos() const {
 
 
 template<class T>
 template<class T>
 inline
 inline
-bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
+bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
     buffer.resize( m_cacheSize );
     buffer.resize( m_cacheSize );
     if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
     if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
         if ( !readNextBlock() ) {
         if ( !readNextBlock() ) {
             return false;
             return false;
         }
         }
     }
     }
+
+    bool continuationFound( false ), endOfDataLine( false );
     size_t i = 0;
     size_t i = 0;
-    while ( !IsLineEnd( m_cache[ m_cachePos ] ) ) {
+    while ( !endOfDataLine ) {
+        if ( continuationToken == m_cache[ m_cachePos ] ) {
+            continuationFound = true;
+            ++m_cachePos;
+        }
+        if ( IsLineEnd( m_cache[ m_cachePos ] ) ) {
+            if ( !continuationFound ) {
+                // the end of the data line
+                break;
+            } else {
+                // skip line end
+                while ( m_cache[m_cachePos] != '\n') {
+                    ++m_cachePos;
+                }
+                ++m_cachePos;
+                continuationFound = false;
+            }
+        }
+
         buffer[ i ] = m_cache[ m_cachePos ];
         buffer[ i ] = m_cache[ m_cachePos ];
         m_cachePos++;
         m_cachePos++;
         i++;
         i++;
@@ -245,10 +277,63 @@ bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
             }
             }
         }
         }
     }
     }
+    
     buffer[ i ] = '\n';
     buffer[ i ] = '\n';
     m_cachePos++;
     m_cachePos++;
 
 
     return true;
     return true;
 }
 }
 
 
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
+    buffer.resize(m_cacheSize);
+    if (m_cachePos == m_cacheSize || 0 == m_filePos) {
+       if (!readNextBlock()) {
+          return false;
+       }
+      }
+
+    if (IsLineEnd(m_cache[m_cachePos])) {
+        // skip line end
+        while (m_cache[m_cachePos] != '\n') {
+            ++m_cachePos;
+        }
+        ++m_cachePos;
+    }
+
+    size_t i = 0;
+    while (!IsLineEnd(m_cache[m_cachePos])) {
+        buffer[i] = m_cache[m_cachePos];
+        m_cachePos++;
+        i++;
+        if (m_cachePos >= m_cacheSize) {
+            if (!readNextBlock()) {
+                return false;
+            }
+        }
+    }
+    buffer[i] = '\n';
+    m_cachePos++;
+
+    return true;
+}
+
+template<class T>
+inline
+bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
+  //just return the last blockvalue if getNextLine was used before
+  if ( m_cachePos !=  0) {      
+      buffer = std::vector<T>(m_cache.begin() + m_cachePos, m_cache.end());
+      m_cachePos = 0;
+  }
+  else {
+      if ( !readNextBlock() )
+          return false;
+
+      buffer = std::vector<T>(m_cache.begin(), m_cache.end());
+  }
+  return true;
+}
+
 } // !ns Assimp
 } // !ns Assimp

+ 1 - 1
code/IRRLoader.cpp

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include "GenericProperty.h"
 #include "GenericProperty.h"
 
 
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StandardShapes.h"
 #include "StandardShapes.h"
 #include "Importer.h"
 #include "Importer.h"
 
 

+ 1 - 1
code/IRRLoader.h

@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_IRRLOADER_H_INCLUDED
 #define AI_IRRLOADER_H_INCLUDED
 
 
 #include "IRRShared.h"
 #include "IRRShared.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Importer.h"
 #include "Importer.h"
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include <assimp/anim.h>
 #include <assimp/anim.h>

+ 1 - 0
code/LWOAnimation.cpp

@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 // internal headers
 // internal headers
 #include "LWOFileData.h"
 #include "LWOFileData.h"
+#include <assimp/anim.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace Assimp::LWO;
 using namespace Assimp::LWO;

+ 3 - 4
code/LWOAnimation.h

@@ -48,11 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_LWO_ANIMATION_INCLUDED
 #ifndef AI_LWO_ANIMATION_INCLUDED
 #define AI_LWO_ANIMATION_INCLUDED
 #define AI_LWO_ANIMATION_INCLUDED
 
 
-#include <assimp/anim.h>
+//
 #include <vector>
 #include <vector>
 #include <list>
 #include <list>
 
 
 struct aiNodeAnim;
 struct aiNodeAnim;
+struct aiVectorKey;
 
 
 namespace Assimp {
 namespace Assimp {
 namespace LWO {
 namespace LWO {
@@ -166,7 +167,6 @@ struct Envelope
     //! Keyframes for this envelope
     //! Keyframes for this envelope
     std::vector<Key> keys;
     std::vector<Key> keys;
 
 
-
     // temporary data for AnimResolver
     // temporary data for AnimResolver
     size_t old_first,old_last;
     size_t old_first,old_last;
 };
 };
@@ -198,8 +198,7 @@ public:
      *  @param Output tick rate, per second
      *  @param Output tick rate, per second
      *  @note The input envelopes are possibly modified.
      *  @note The input envelopes are possibly modified.
      */
      */
-    AnimResolver(std::list<Envelope>& envelopes,
-        double tick);
+    AnimResolver(std::list<Envelope>& envelopes, double tick);
 
 
 public:
 public:
 
 

+ 1 - 1
code/LWSLoader.cpp

@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 
 
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "GenericProperty.h"
 #include "GenericProperty.h"
 #include "SkeletonMeshBuilder.h"
 #include "SkeletonMeshBuilder.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"

+ 1 - 1
code/LWSLoader.h

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_LWSLOADER_H_INCLUDED
 #define AI_LWSLOADER_H_INCLUDED
 
 
 #include "LWOFileData.h"
 #include "LWOFileData.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 
 
 struct aiImporterDesc;
 struct aiImporterDesc;

+ 12 - 15
code/MD3FileData.h

@@ -142,14 +142,14 @@ struct Frame
     //! name of frame
     //! name of frame
     char name[ AI_MD3_MAXFRAME ];
     char name[ AI_MD3_MAXFRAME ];
 
 
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
-/** @brief Data structure for the tag header
+/**
+ * @brief Data structure for the tag header
  */
  */
-struct Tag
-{
+struct Tag {
     //! name of the tag
     //! name of the tag
     char NAME[ AI_MD3_MAXQPATH ];
     char NAME[ AI_MD3_MAXQPATH ];
 
 
@@ -157,14 +157,13 @@ struct Tag
     aiVector3D  origin;
     aiVector3D  origin;
     ai_real  orientation[3][3];
     ai_real  orientation[3][3];
 
 
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /** @brief Data structure for the surface header
 /** @brief Data structure for the surface header
  */
  */
-struct Surface
-{
+struct Surface {
     //! magic number
     //! magic number
     int32_t IDENT;
     int32_t IDENT;
 
 
@@ -186,7 +185,6 @@ struct Surface
     //! number of triangles in the surface
     //! number of triangles in the surface
     uint32_t NUM_TRIANGLES;
     uint32_t NUM_TRIANGLES;
 
 
-
     //! offset to the triangle data
     //! offset to the triangle data
     uint32_t OFS_TRIANGLES;
     uint32_t OFS_TRIANGLES;
 
 
@@ -201,19 +199,18 @@ struct Surface
 
 
     //! offset to the end of the Surface object
     //! offset to the end of the Surface object
     int32_t OFS_END;
     int32_t OFS_END;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /** @brief Data structure for a shader defined in there
 /** @brief Data structure for a shader defined in there
  */
  */
-struct Shader
-{
+struct Shader {
     //! filename of the shader
     //! filename of the shader
     char NAME[ AI_MD3_MAXQPATH ];
     char NAME[ AI_MD3_MAXQPATH ];
 
 
     //! index of the shader
     //! index of the shader
     uint32_t SHADER_INDEX;
     uint32_t SHADER_INDEX;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -223,7 +220,7 @@ struct Triangle
 {
 {
     //! triangle indices
     //! triangle indices
     uint32_t INDEXES[3];
     uint32_t INDEXES[3];
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -233,7 +230,7 @@ struct TexCoord
 {
 {
     //! UV coordinates
     //! UV coordinates
     ai_real U,V;
     ai_real U,V;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -246,7 +243,7 @@ struct Vertex
 
 
     //! encoded normal vector
     //! encoded normal vector
     uint16_t  NORMAL;
     uint16_t  NORMAL;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 #include "./../include/assimp/Compiler/poppack1.h"
 #include "./../include/assimp/Compiler/poppack1.h"
 
 

+ 1 - 1
code/MD3Loader.cpp

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
 #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
 
 
 #include "MD3Loader.h"
 #include "MD3Loader.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "GenericProperty.h"
 #include "GenericProperty.h"
 #include "RemoveComments.h"
 #include "RemoveComments.h"
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"

+ 1 - 1
code/MDCFileData.h

@@ -157,7 +157,7 @@ struct Frame
 
 
     //! Name of the frame
     //! Name of the frame
     char name [ 16 ] ;
     char name [ 16 ] ;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** \brief Data structure for a MDC triangle
 /** \brief Data structure for a MDC triangle

+ 51 - 76
code/MDLFileData.h

@@ -53,10 +53,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MDLFILEHELPER_H_INC
 #ifndef AI_MDLFILEHELPER_H_INC
 #define AI_MDLFILEHELPER_H_INC
 #define AI_MDLFILEHELPER_H_INC
 
 
+#include <assimp/anim.h>
+#include <assimp/mesh.h>
+#include <assimp/Compiler/pushpack1.h>
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
-#include "./../include/assimp/anim.h"
-#include "./../include/assimp/mesh.h"
-#include "./../include/assimp/Compiler/pushpack1.h"
 #include <stdint.h>
 #include <stdint.h>
 #include <vector>
 #include <vector>
 
 
@@ -90,7 +90,6 @@ namespace MDL   {
 #define AI_MDL_MAGIC_NUMBER_BE_GS7  AI_MAKE_MAGIC("MDL7")
 #define AI_MDL_MAGIC_NUMBER_BE_GS7  AI_MAKE_MAGIC("MDL7")
 #define AI_MDL_MAGIC_NUMBER_LE_GS7  AI_MAKE_MAGIC("7LDM")
 #define AI_MDL_MAGIC_NUMBER_LE_GS7  AI_MAKE_MAGIC("7LDM")
 
 
-
 // common limitations for Quake1 meshes. The loader does not check them,
 // common limitations for Quake1 meshes. The loader does not check them,
 // (however it warns) but models should not exceed these limits.
 // (however it warns) but models should not exceed these limits.
 #if (!defined AI_MDL_VERSION)
 #if (!defined AI_MDL_VERSION)
@@ -119,8 +118,7 @@ namespace MDL   {
 /** \struct Header
 /** \struct Header
  *  \brief Data structure for the MDL main header
  *  \brief Data structure for the MDL main header
  */
  */
-struct Header
-{
+struct Header {
     //! magic number: "IDPO"
     //! magic number: "IDPO"
     uint32_t ident;
     uint32_t ident;
 
 
@@ -166,15 +164,14 @@ struct Header
 
 
     //! Could be the total size of the file (and not a float)
     //! Could be the total size of the file (and not a float)
     float size;
     float size;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Header_MDL7
 /** \struct Header_MDL7
  *  \brief Data structure for the MDL 7 main header
  *  \brief Data structure for the MDL 7 main header
  */
  */
-struct Header_MDL7
-{
+struct Header_MDL7 {
     //! magic number: "MDL7"
     //! magic number: "MDL7"
     char    ident[4];
     char    ident[4];
 
 
@@ -226,15 +223,14 @@ struct Header_MDL7
 
 
     //! Size of the Frame_MDL7 data structure used in the file
     //! Size of the Frame_MDL7 data structure used in the file
     uint16_t frame_stc_size;
     uint16_t frame_stc_size;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Bone_MDL7
 /** \struct Bone_MDL7
  *  \brief Data structure for a bone in a MDL7 file
  *  \brief Data structure for a bone in a MDL7 file
  */
  */
-struct Bone_MDL7
-{
+struct Bone_MDL7 {
     //! Index of the parent bone of *this* bone. 0xffff means:
     //! Index of the parent bone of *this* bone. 0xffff means:
     //! "hey, I have no parent, I'm an orphan"
     //! "hey, I have no parent, I'm an orphan"
     uint16_t parent_index;
     uint16_t parent_index;
@@ -246,7 +242,7 @@ struct Bone_MDL7
 
 
     //! Optional name of the bone
     //! Optional name of the bone
     char name[1 /* DUMMY SIZE */];
     char name[1 /* DUMMY SIZE */];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
 #if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
 #   define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
 #   define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
@@ -268,8 +264,7 @@ struct Bone_MDL7
 /** \struct Group_MDL7
 /** \struct Group_MDL7
  *  \brief Group in a MDL7 file
  *  \brief Group in a MDL7 file
  */
  */
-struct Group_MDL7
-{
+struct Group_MDL7 {
     //! = '1' -> triangle based Mesh
     //! = '1' -> triangle based Mesh
     unsigned char   typ;
     unsigned char   typ;
 
 
@@ -295,7 +290,7 @@ struct Group_MDL7
 
 
     //! Number of frames
     //! Number of frames
     int32_t numframes;
     int32_t numframes;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #define AI_MDL7_SKINTYPE_MIPFLAG                0x08
 #define AI_MDL7_SKINTYPE_MIPFLAG                0x08
 #define AI_MDL7_SKINTYPE_MATERIAL               0x10
 #define AI_MDL7_SKINTYPE_MATERIAL               0x10
@@ -310,41 +305,36 @@ struct Group_MDL7
 /** \struct Deformer_MDL7
 /** \struct Deformer_MDL7
  *  \brief Deformer in a MDL7 file
  *  \brief Deformer in a MDL7 file
  */
  */
-struct Deformer_MDL7
-{
+struct Deformer_MDL7 {
     int8_t  deformer_version;       // 0
     int8_t  deformer_version;       // 0
     int8_t  deformer_typ;           // 0 - bones
     int8_t  deformer_typ;           // 0 - bones
     int8_t  _unused_[2];
     int8_t  _unused_[2];
     int32_t group_index;
     int32_t group_index;
     int32_t elements;
     int32_t elements;
     int32_t deformerdata_size;
     int32_t deformerdata_size;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct DeformerElement_MDL7
 /** \struct DeformerElement_MDL7
  *  \brief Deformer element in a MDL7 file
  *  \brief Deformer element in a MDL7 file
  */
  */
-struct DeformerElement_MDL7
-{
+struct DeformerElement_MDL7 {
     //! bei deformer_typ==0 (==bones) element_index == bone index
     //! bei deformer_typ==0 (==bones) element_index == bone index
     int32_t element_index;
     int32_t element_index;
     char    element_name[AI_MDL7_MAX_BONENAMESIZE];
     char    element_name[AI_MDL7_MAX_BONENAMESIZE];
     int32_t weights;
     int32_t weights;
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct DeformerWeight_MDL7
 /** \struct DeformerWeight_MDL7
  *  \brief Deformer weight in a MDL7 file
  *  \brief Deformer weight in a MDL7 file
  */
  */
-struct DeformerWeight_MDL7
-{
+struct DeformerWeight_MDL7 {
     //! for deformer_typ==0 (==bones) index == vertex index
     //! for deformer_typ==0 (==bones) index == vertex index
     int32_t index;
     int32_t index;
     float   weight;
     float   weight;
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // don't know why this was in the original headers ...
 // don't know why this was in the original headers ...
 typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
 typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
@@ -353,17 +343,15 @@ typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
 /** \struct ColorValue_MDL7
 /** \struct ColorValue_MDL7
  *  \brief Data structure for a color value in a MDL7 file
  *  \brief Data structure for a color value in a MDL7 file
  */
  */
-struct ColorValue_MDL7
-{
+struct ColorValue_MDL7 {
     float r,g,b,a;
     float r,g,b,a;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Material_MDL7
 /** \struct Material_MDL7
  *  \brief Data structure for a Material in a MDL7 file
  *  \brief Data structure for a Material in a MDL7 file
  */
  */
-struct Material_MDL7
-{
+struct Material_MDL7 {
     //! Diffuse base color of the material
     //! Diffuse base color of the material
     ColorValue_MDL7 Diffuse;
     ColorValue_MDL7 Diffuse;
 
 
@@ -378,15 +366,13 @@ struct Material_MDL7
 
 
     //! Phong power
     //! Phong power
     float           Power;
     float           Power;
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Skin
 /** \struct Skin
  *  \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
  *  \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4
  */
  */
-struct Skin
-{
+struct Skin {
     //! 0 = single (Skin), 1 = group (GroupSkin)
     //! 0 = single (Skin), 1 = group (GroupSkin)
     //! For MDL3-5: Defines the type of the skin and there
     //! For MDL3-5: Defines the type of the skin and there
     //! fore the size of the data to skip:
     //! fore the size of the data to skip:
@@ -402,7 +388,7 @@ struct Skin
 
 
     //! Texture data
     //! Texture data
     uint8_t *data;
     uint8_t *data;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
@@ -410,11 +396,10 @@ struct Skin
  *  \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
  *  \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7
  *  \see Skin
  *  \see Skin
  */
  */
-struct Skin_MDL5
-{
+struct Skin_MDL5 {
     int32_t size, width, height;
     int32_t size, width, height;
     uint8_t *data;
     uint8_t *data;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // maximum length of texture file name
 // maximum length of texture file name
 #if (!defined AI_MDL7_MAX_TEXNAMESIZE)
 #if (!defined AI_MDL7_MAX_TEXNAMESIZE)
@@ -425,44 +410,40 @@ struct Skin_MDL5
 /** \struct Skin_MDL7
 /** \struct Skin_MDL7
  *  \brief Skin data structure #3 - used by MDL7 and HMP7
  *  \brief Skin data structure #3 - used by MDL7 and HMP7
  */
  */
-struct Skin_MDL7
-{
+struct Skin_MDL7 {
     uint8_t         typ;
     uint8_t         typ;
     int8_t          _unused_[3];
     int8_t          _unused_[3];
     int32_t         width;
     int32_t         width;
     int32_t         height;
     int32_t         height;
     char            texture_name[AI_MDL7_MAX_TEXNAMESIZE];
     char            texture_name[AI_MDL7_MAX_TEXNAMESIZE];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct RGB565
 /** \struct RGB565
  *  \brief Data structure for a RGB565 pixel in a texture
  *  \brief Data structure for a RGB565 pixel in a texture
  */
  */
-struct RGB565
-{
+struct RGB565 {
     uint16_t r : 5;
     uint16_t r : 5;
     uint16_t g : 6;
     uint16_t g : 6;
     uint16_t b : 5;
     uint16_t b : 5;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct ARGB4
 /** \struct ARGB4
  *  \brief Data structure for a ARGB4444 pixel in a texture
  *  \brief Data structure for a ARGB4444 pixel in a texture
  */
  */
-struct ARGB4
-{
+struct ARGB4 {
     uint16_t a : 4;
     uint16_t a : 4;
     uint16_t r : 4;
     uint16_t r : 4;
     uint16_t g : 4;
     uint16_t g : 4;
     uint16_t b : 4;
     uint16_t b : 4;
-} PACK_STRUCT;
+} /*PACK_STRUCT*/;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct GroupSkin
 /** \struct GroupSkin
  *  \brief Skin data structure #2 (group of pictures)
  *  \brief Skin data structure #2 (group of pictures)
  */
  */
-struct GroupSkin
-{
+struct GroupSkin {
     //! 0 = single (Skin), 1 = group (GroupSkin)
     //! 0 = single (Skin), 1 = group (GroupSkin)
     int32_t group;
     int32_t group;
 
 
@@ -474,14 +455,13 @@ struct GroupSkin
 
 
     //! Data of each image
     //! Data of each image
     uint8_t **data;
     uint8_t **data;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct TexCoord
 /** \struct TexCoord
  *  \brief Texture coordinate data structure used by the Quake1 MDL format
  *  \brief Texture coordinate data structure used by the Quake1 MDL format
  */
  */
-struct TexCoord
-{
+struct TexCoord {
     //! Is the vertex on the noundary between front and back piece?
     //! Is the vertex on the noundary between front and back piece?
     int32_t onseam;
     int32_t onseam;
 
 
@@ -490,33 +470,31 @@ struct TexCoord
 
 
     //! Texture coordinate in the ty direction
     //! Texture coordinate in the ty direction
     int32_t t;
     int32_t t;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct TexCoord_MDL3
 /** \struct TexCoord_MDL3
  *  \brief Data structure for an UV coordinate in the 3DGS MDL3 format
  *  \brief Data structure for an UV coordinate in the 3DGS MDL3 format
  */
  */
-struct TexCoord_MDL3
-{
+struct TexCoord_MDL3 {
     //! position, horizontally in range 0..skinwidth-1
     //! position, horizontally in range 0..skinwidth-1
     int16_t u;
     int16_t u;
 
 
     //! position, vertically in range 0..skinheight-1
     //! position, vertically in range 0..skinheight-1
     int16_t v;
     int16_t v;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct TexCoord_MDL7
 /** \struct TexCoord_MDL7
  *  \brief Data structure for an UV coordinate in the 3DGS MDL7 format
  *  \brief Data structure for an UV coordinate in the 3DGS MDL7 format
  */
  */
-struct TexCoord_MDL7
-{
+struct TexCoord_MDL7 {
     //! position, horizontally in range 0..1
     //! position, horizontally in range 0..1
     float u;
     float u;
 
 
     //! position, vertically in range 0..1
     //! position, vertically in range 0..1
     float v;
     float v;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct SkinSet_MDL7
 /** \struct SkinSet_MDL7
@@ -532,7 +510,7 @@ struct SkinSet_MDL7
 
 
     //! Material index
     //! Material index
     int32_t     material;    // size 4
     int32_t     material;    // size 4
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Triangle
 /** \struct Triangle
@@ -545,7 +523,7 @@ struct Triangle
 
 
     //! Vertex indices
     //! Vertex indices
     int32_t vertex[3];
     int32_t vertex[3];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Triangle_MDL3
 /** \struct Triangle_MDL3
@@ -558,7 +536,7 @@ struct Triangle_MDL3
 
 
     //! Index of 3 skin vertices in range 0..numskinverts
     //! Index of 3 skin vertices in range 0..numskinverts
     uint16_t index_uv[3];
     uint16_t index_uv[3];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Triangle_MDL7
 /** \struct Triangle_MDL7
@@ -571,7 +549,7 @@ struct Triangle_MDL7
 
 
     //! Two skinsets. The second will be used for multi-texturing
     //! Two skinsets. The second will be used for multi-texturing
     SkinSet_MDL7  skinsets[2];
     SkinSet_MDL7  skinsets[2];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
 #if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
 #   define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
 #   define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
@@ -599,7 +577,7 @@ struct Vertex
 {
 {
     uint8_t v[3];
     uint8_t v[3];
     uint8_t normalIndex;
     uint8_t normalIndex;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
@@ -625,8 +603,7 @@ struct Vertex_MDL7
         uint8_t norm162index;
         uint8_t norm162index;
         float norm[3];
         float norm[3];
     };
     };
-} PACK_STRUCT;
-
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct BoneTransform_MDL7
 /** \struct BoneTransform_MDL7
@@ -643,12 +620,11 @@ struct BoneTransform_MDL7
     //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
     //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
     //! THIS STUPID FILE FORMAT!
     //! THIS STUPID FILE FORMAT!
     int8_t _unused_[2];
     int8_t _unused_[2];
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 #define AI_MDL7_MAX_FRAMENAMESIZE       16
 #define AI_MDL7_MAX_FRAMENAMESIZE       16
 
 
-
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Frame_MDL7
 /** \struct Frame_MDL7
  *  \brief Frame data structure used by MDL7 files
  *  \brief Frame data structure used by MDL7 files
@@ -678,7 +654,7 @@ struct SimpleFrame
 
 
     //! Vertex list of the frame
     //! Vertex list of the frame
     Vertex *verts;
     Vertex *verts;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct Frame
 /** \struct Frame
@@ -691,7 +667,7 @@ struct Frame
 
 
     //! Frame data
     //! Frame data
     SimpleFrame frame;
     SimpleFrame frame;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
@@ -708,7 +684,7 @@ struct SimpleFrame_MDLn_SP
 
 
     //! Vertex list of the frame
     //! Vertex list of the frame
     Vertex_MDL4 *verts;
     Vertex_MDL4 *verts;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 // -------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------
 /** \struct GroupFrame
 /** \struct GroupFrame
@@ -730,7 +706,7 @@ struct GroupFrame
 
 
     //! List of single frames
     //! List of single frames
     SimpleFrame *frames;
     SimpleFrame *frames;
-} PACK_STRUCT;
+} /* PACK_STRUCT */;
 
 
 #include "./../include/assimp/Compiler/poppack1.h"
 #include "./../include/assimp/Compiler/poppack1.h"
 
 
@@ -738,8 +714,7 @@ struct GroupFrame
 /** \struct IntFace_MDL7
 /** \struct IntFace_MDL7
  *  \brief Internal data structure to temporarily represent a face
  *  \brief Internal data structure to temporarily represent a face
  */
  */
-struct IntFace_MDL7
-{
+struct IntFace_MDL7 {
     // provide a constructor for our own convenience
     // provide a constructor for our own convenience
     IntFace_MDL7()
     IntFace_MDL7()
     {
     {

+ 40 - 0
code/MMDCpp14.h

@@ -1,3 +1,43 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
 #pragma once
 #pragma once
 
 
 #ifndef MMD_CPP14_H
 #ifndef MMD_CPP14_H

+ 40 - 0
code/MMDPmdParser.h

@@ -1,3 +1,43 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
 #pragma once
 #pragma once
 
 
 #include <vector>
 #include <vector>

+ 42 - 10
code/MMDPmxParser.cpp

@@ -1,7 +1,47 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
 #include <utility>
 #include <utility>
 #include "MMDPmxParser.h"
 #include "MMDPmxParser.h"
+#include "../contrib/utf8cpp/source/utf8.h"
 #include "Exceptional.h"
 #include "Exceptional.h"
-#include "../contrib/ConvertUTF/ConvertUTF.h"
 
 
 namespace pmx
 namespace pmx
 {
 {
@@ -60,15 +100,7 @@ namespace pmx
 			const unsigned int targetSize = size * 3; // enough to encode
 			const unsigned int targetSize = size * 3; // enough to encode
 			char* targetStart = new char[targetSize]();
 			char* targetStart = new char[targetSize]();
 			const char* targetReserved = targetStart;
 			const char* targetReserved = targetStart;
-			ConversionFlags flags = ConversionFlags::lenientConversion;
-
-			ConversionResult conversionResult;
-			if( ( conversionResult = ConvertUTF16toUTF8(
-				(const UTF16**)&sourceStart, (const UTF16*)(sourceStart + size),
-				(UTF8**)&targetStart, (UTF8*)(targetStart + targetSize),
-				flags) ) != ConversionResult::conversionOK) {
-				throw DeadlyImportError( "Convert " + std::string(sourceStart) + " to UTF8 is not valid." );
-			}
+            utf8::utf16to8( sourceStart, sourceStart + size, targetStart );
 
 
 			result.assign(targetReserved, targetStart - targetReserved);
 			result.assign(targetReserved, targetStart - targetReserved);
 			delete[] targetReserved;
 			delete[] targetReserved;

+ 40 - 0
code/MMDPmxParser.h

@@ -1,3 +1,43 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
 #pragma once
 #pragma once
 
 
 #include <vector>
 #include <vector>

+ 40 - 0
code/MMDVmdParser.h

@@ -1,3 +1,43 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
 #pragma once
 #pragma once
 
 
 #include <vector>
 #include <vector>

+ 32 - 43
code/ObjFileParser.cpp

@@ -64,7 +64,7 @@ ObjFileParser::ObjFileParser()
 , m_uiLine( 0 )
 , m_uiLine( 0 )
 , m_pIO( nullptr )
 , m_pIO( nullptr )
 , m_progress( nullptr )
 , m_progress( nullptr )
-, m_originalObjFileName( "" ) {
+, m_originalObjFileName() {
     // empty
     // empty
 }
 }
 
 
@@ -109,28 +109,6 @@ ObjFile::Model *ObjFileParser::GetModel() const {
     return m_pModel;
     return m_pModel;
 }
 }
 
 
-void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
-{
-    auto curPosition = buffer.begin();
-    do
-    {
-        while (*curPosition!='\n'&&*curPosition!='\\')
-        {
-            ++curPosition;
-        }
-        if (*curPosition=='\\')
-        {
-            std::vector<char> tempBuf;
-            do
-            {
-                streamBuffer.getNextLine(tempBuf);
-            } while (tempBuf[0]=='\n');
-            *curPosition = ' ';
-            std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
-        }
-    } while (*curPosition!='\n');
-}
-
 void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
 void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
     // only update every 100KB or it'll be too slow
     // only update every 100KB or it'll be too slow
     //const unsigned int updateProgressEveryBytes = 100 * 1024;
     //const unsigned int updateProgressEveryBytes = 100 * 1024;
@@ -142,7 +120,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
     size_t lastFilePos( 0 );
     size_t lastFilePos( 0 );
 
 
     std::vector<char> buffer;
     std::vector<char> buffer;
-    while ( streamBuffer.getNextLine( buffer ) ) {
+    while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
         m_DataIt = buffer.begin();
         m_DataIt = buffer.begin();
         m_DataItEnd = buffer.end();
         m_DataItEnd = buffer.end();
 
 
@@ -154,14 +132,14 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
             progressCounter++;
             progressCounter++;
             m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
             m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
         }
         }
-		//ignoreNewLines(streamBuffer, buffer);
+
         // parse line
         // parse line
         switch (*m_DataIt) {
         switch (*m_DataIt) {
         case 'v': // Parse a vertex texture coordinate
         case 'v': // Parse a vertex texture coordinate
             {
             {
                 ++m_DataIt;
                 ++m_DataIt;
                 if (*m_DataIt == ' ' || *m_DataIt == '\t') {
                 if (*m_DataIt == ' ' || *m_DataIt == '\t') {
-                    size_t numComponents = getNumComponentsInLine();
+                    size_t numComponents = getNumComponentsInDataDefinition();
                     if (numComponents == 3) {
                     if (numComponents == 3) {
                         // read in vertex definition
                         // read in vertex definition
                         getVector3(m_pModel->m_Vertices);
                         getVector3(m_pModel->m_Vertices);
@@ -245,7 +223,6 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
         default:
         default:
             {
             {
 pf_skip_line:
 pf_skip_line:
-
                 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
                 m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
             }
             }
             break;
             break;
@@ -274,21 +251,44 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) {
     pBuffer[index] = '\0';
     pBuffer[index] = '\0';
 }
 }
 
 
-size_t ObjFileParser::getNumComponentsInLine() {
+static bool isDataDefinitionEnd( const char *tmp ) {
+    if ( *tmp == '\\' ) {
+        tmp++;
+        if ( IsLineEnd( *tmp ) ) {
+            tmp++;
+            return true;
+        }
+    }
+    return false;
+}
+
+size_t ObjFileParser::getNumComponentsInDataDefinition() {
     size_t numComponents( 0 );
     size_t numComponents( 0 );
     const char* tmp( &m_DataIt[0] );
     const char* tmp( &m_DataIt[0] );
-    while( !IsLineEnd( *tmp ) ) {        
+    bool end_of_definition = false;
+    while ( !end_of_definition ) {
+        if ( isDataDefinitionEnd( tmp ) ) {
+            tmp += 2;
+        } else if ( IsLineEnd( *tmp ) ) {
+            end_of_definition = true;
+        }
         if ( !SkipSpaces( &tmp ) ) {
         if ( !SkipSpaces( &tmp ) ) {
             break;
             break;
         }
         }
+        const bool isNum( IsNumeric( *tmp ) );
         SkipToken( tmp );
         SkipToken( tmp );
-        ++numComponents;
+        if ( isNum ) {
+            ++numComponents;
+        }
+        if ( !SkipSpaces( &tmp ) ) {
+            break;
+        }
     }
     }
     return numComponents;
     return numComponents;
 }
 }
 
 
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
 void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
-    size_t numComponents = getNumComponentsInLine();
+    size_t numComponents = getNumComponentsInDataDefinition();
     ai_real x, y, z;
     ai_real x, y, z;
     if( 2 == numComponents ) {
     if( 2 == numComponents ) {
         copyNextWord( m_buffer, Buffersize );
         copyNextWord( m_buffer, Buffersize );
@@ -397,10 +397,6 @@ static const std::string DefaultObjName = "defaultobject";
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //  Get values for a new face instance
 //  Get values for a new face instance
 void ObjFileParser::getFace( aiPrimitiveType type ) {
 void ObjFileParser::getFace( aiPrimitiveType type ) {
-    //copyNextLine(m_buffer, Buffersize);
-    //char *pPtr = m_DataIt;
-    //char *pPtr = m_buffer;
-    //char *pEnd = &pPtr[Buffersize];
     m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
     m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
     if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
     if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
         return;
         return;
@@ -571,14 +567,7 @@ void ObjFileParser::getMaterialDesc() {
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 //  Get a comment, values will be skipped
 //  Get a comment, values will be skipped
 void ObjFileParser::getComment() {
 void ObjFileParser::getComment() {
-    while (m_DataIt != m_DataItEnd) {
-        if ( '\n' == (*m_DataIt)) {
-            ++m_DataIt;
-            break;
-        } else {
-            ++m_DataIt;
-        }
-    }
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------

+ 4 - 5
code/ObjFileParser.h

@@ -91,6 +91,8 @@ protected:
     void copyNextWord(char *pBuffer, size_t length);
     void copyNextWord(char *pBuffer, size_t length);
     /// Method to copy the new line.
     /// Method to copy the new line.
 //    void copyNextLine(char *pBuffer, size_t length);
 //    void copyNextLine(char *pBuffer, size_t length);
+    /// Get the number of components in a line.
+    size_t getNumComponentsInDataDefinition();
     /// Stores the vector
     /// Stores the vector
     void getVector( std::vector<aiVector3D> &point3d_array );
     void getVector( std::vector<aiVector3D> &point3d_array );
     /// Stores the following 3d vector.
     /// Stores the following 3d vector.
@@ -129,8 +131,6 @@ protected:
     bool needsNewMesh( const std::string &rMaterialName );
     bool needsNewMesh( const std::string &rMaterialName );
     /// Error report in token
     /// Error report in token
     void reportErrorTokenInFace();
     void reportErrorTokenInFace();
-    /// Get the number of components in a line.
-    size_t getNumComponentsInLine();
 
 
 private:
 private:
     // Copy and assignment constructor should be private
     // Copy and assignment constructor should be private
@@ -154,9 +154,8 @@ private:
     IOSystem *m_pIO;
     IOSystem *m_pIO;
     //! Pointer to progress handler
     //! Pointer to progress handler
     ProgressHandler* m_progress;
     ProgressHandler* m_progress;
-    /// Path to the current model
-    // name of the obj file where the buffer comes from
-    const std::string& m_originalObjFileName;
+    /// Path to the current model, name of the obj file where the buffer comes from
+    const std::string m_originalObjFileName;
 };
 };
 
 
 }   // Namespace Assimp
 }   // Namespace Assimp

+ 5 - 3
code/ObjTools.h

@@ -116,14 +116,16 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
     while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
     while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
         ++it;
         ++it;
     }
     }
-    if ( it != end )
-    {
+    
+    if ( it != end ) {
         ++it;
         ++it;
         ++uiLine;
         ++uiLine;
     }
     }
     // fix .. from time to time there are spaces at the beginning of a material line
     // fix .. from time to time there are spaces at the beginning of a material line
-    while ( it != end && (*it == '\t' || *it == ' ') )
+    while ( it != end && ( *it == '\t' || *it == ' ' ) ) {
         ++it;
         ++it;
+    }
+
     return it;
     return it;
 }
 }
 
 

+ 1 - 1
code/OptimizeGraph.cpp

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "OptimizeGraph.h"
 #include "OptimizeGraph.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Exceptional.h"
 #include "Exceptional.h"
 #include <stdio.h>
 #include <stdio.h>
 
 

+ 1 - 1
code/OptimizeMeshes.cpp

@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "OptimizeMeshes.h"
 #include "OptimizeMeshes.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Exceptional.h"
 #include "Exceptional.h"
 
 
 using namespace Assimp;
 using namespace Assimp;

+ 2 - 4
code/PlyExporter.h

@@ -51,14 +51,12 @@ struct aiScene;
 struct aiNode;
 struct aiNode;
 struct aiMesh;
 struct aiMesh;
 
 
-namespace Assimp
-{
+namespace Assimp {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 /** Helper class to export a given scene to a Stanford Ply file. */
 /** Helper class to export a given scene to a Stanford Ply file. */
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-class PlyExporter
-{
+class PlyExporter {
 public:
 public:
     /// The class constructor for a specific scene to export
     /// The class constructor for a specific scene to export
     PlyExporter(const char* filename, const aiScene* pScene, bool binary = false);
     PlyExporter(const char* filename, const aiScene* pScene, bool binary = false);

+ 855 - 911
code/PlyLoader.cpp

@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2017, assimp team
 Copyright (c) 2006-2017, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -13,18 +12,18 @@ with or without modification, are permitted provided that the following
 conditions are met:
 conditions are met:
 
 
 * Redistributions of source code must retain the above
 * Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
+copyright notice, this list of conditions and the
+following disclaimer.
 
 
 * Redistributions in binary form must reproduce the above
 * Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
 
 
 * Neither the name of the assimp team, nor the names of its
 * Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
 
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -48,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 // internal headers
 // internal headers
 #include "PlyLoader.h"
 #include "PlyLoader.h"
+#include "IOStreamBuffer.h"
 #include "Macros.h"
 #include "Macros.h"
 #include <memory>
 #include <memory>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
@@ -57,16 +57,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 using namespace Assimp;
 
 
 static const aiImporterDesc desc = {
 static const aiImporterDesc desc = {
-    "Stanford Polygon Library (PLY) Importer",
-    "",
-    "",
-    "",
-    aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
-    0,
-    0,
-    0,
-    0,
-    "ply"
+  "Stanford Polygon Library (PLY) Importer",
+  "",
+  "",
+  "",
+  aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
+  0,
+  0,
+  0,
+  0,
+  "ply"
 };
 };
 
 
 
 
@@ -74,1040 +74,984 @@ static const aiImporterDesc desc = {
 // Internal stuff
 // Internal stuff
 namespace
 namespace
 {
 {
-    // ------------------------------------------------------------------------------------------------
-    // Checks that property index is within range
-    template <class T>
-    const T &GetProperty(const std::vector<T> &props, int idx)
-    {
-        if( static_cast< size_t >( idx ) >= props.size() ) {
-            throw DeadlyImportError( "Invalid .ply file: Property index is out of range." );
-        }
-
-        return props[idx];
+  // ------------------------------------------------------------------------------------------------
+  // Checks that property index is within range
+  template <class T>
+  const T &GetProperty(const std::vector<T> &props, int idx)
+  {
+    if (static_cast<size_t>(idx) >= props.size()) {
+      throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
     }
     }
+
+    return props[idx];
+  }
 }
 }
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 PLYImporter::PLYImporter()
 PLYImporter::PLYImporter()
-: mBuffer()
-, pcDOM(){
-    // empty
+  : mBuffer()
+  , pcDOM()
+  , mGeneratedMesh(NULL){
+  // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
 PLYImporter::~PLYImporter() {
 PLYImporter::~PLYImporter() {
-    // empty
+  // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
-bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 {
 {
-    const std::string extension = GetExtension(pFile);
-
-    if (extension == "ply")
-        return true;
-    else if (!extension.length() || checkSig)
-    {
-        if (!pIOHandler)return true;
-        const char* tokens[] = {"ply"};
-        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-    }
-    return false;
+  const std::string extension = GetExtension(pFile);
+
+  if (extension == "ply")
+    return true;
+  else if (!extension.length() || checkSig)
+  {
+    if (!pIOHandler)return true;
+    const char* tokens[] = { "ply" };
+    return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+  }
+  return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* PLYImporter::GetInfo () const
+const aiImporterDesc* PLYImporter::GetInfo() const
 {
 {
-    return &desc;
+  return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-static bool isBigEndian( const char* szMe ) {
-    ai_assert( NULL != szMe );
+static bool isBigEndian(const char* szMe) {
+  ai_assert(NULL != szMe);
 
 
-    // binary_little_endian
-    // binary_big_endian
-    bool isBigEndian( false );
+  // binary_little_endian
+  // binary_big_endian
+  bool isBigEndian(false);
 #if (defined AI_BUILD_BIG_ENDIAN)
 #if (defined AI_BUILD_BIG_ENDIAN)
-    if ( 'l' == *szMe || 'L' == *szMe ) {
-        isBigEndian = true;
-}
+  if ( 'l' == *szMe || 'L' == *szMe ) {
+    isBigEndian = true;
+  }
 #else
 #else
-    if ( 'b' == *szMe || 'B' == *szMe ) {
-        isBigEndian = true;
-    }
+  if ('b' == *szMe || 'B' == *szMe) {
+    isBigEndian = true;
+  }
 #endif // ! AI_BUILD_BIG_ENDIAN
 #endif // ! AI_BUILD_BIG_ENDIAN
 
 
-    return isBigEndian;
+  return isBigEndian;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // Imports the given file into the given scene structure.
-void PLYImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
+void PLYImporter::InternReadFile(const std::string& pFile,
+  aiScene* pScene, IOSystem* pIOHandler)
 {
 {
-    std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
-
-    // Check whether we can read from the file
-    if( file.get() == NULL) {
-        throw DeadlyImportError( "Failed to open PLY file " + pFile + ".");
+  static const std::string mode = "rb";
+  std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
+  if (!fileStream.get()) {
+    throw DeadlyImportError("Failed to open file " + pFile + ".");
+  }
+
+  // Get the file-size
+  size_t fileSize = fileStream->FileSize();
+
+  IOStreamBuffer<char> streamedBuffer(1024 * 1024);
+  streamedBuffer.open(fileStream.get());
+
+  // the beginning of the file must be PLY - magic, magic
+  std::vector<char> headerCheck;
+  streamedBuffer.getNextLine(headerCheck);
+
+  if ((headerCheck.size() >= 3) && (headerCheck[0] != 'P' && headerCheck[0] != 'p') ||
+    (headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
+    (headerCheck[2] != 'Y' && headerCheck[2] != 'y'))
+  {
+    streamedBuffer.close();
+    throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there");
+  }
+
+  std::vector<char> mBuffer2;
+  streamedBuffer.getNextLine(mBuffer2);
+  mBuffer = (unsigned char*)&mBuffer2[0];
+
+  char* szMe = (char*)&this->mBuffer[0];
+  SkipSpacesAndLineEnd(szMe, (const char**)&szMe);
+
+  // determine the format of the file data and construct the aimesh
+  PLY::DOM sPlyDom;
+  this->pcDOM = &sPlyDom;
+
+  if (TokenMatch(szMe, "format", 6)) {
+    if (TokenMatch(szMe, "ascii", 5)) {
+      SkipLine(szMe, (const char**)&szMe);
+      if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this))
+      {
+        if (mGeneratedMesh != NULL)
+          delete(mGeneratedMesh);
+
+        streamedBuffer.close();
+        throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#1)");
+      }
+    }
+    else if (!::strncmp(szMe, "binary_", 7))
+    {
+      szMe += 7;
+      const bool bIsBE(isBigEndian(szMe));
+
+      // skip the line, parse the rest of the header and build the DOM
+      if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE))
+      {
+        if (mGeneratedMesh != NULL)
+          delete(mGeneratedMesh);
+
+        streamedBuffer.close();
+        throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
+      }
     }
     }
+    else
+    {
+      if (mGeneratedMesh != NULL)
+        delete(mGeneratedMesh);
 
 
-    // allocate storage and copy the contents of the file to a memory buffer
-    std::vector<char> mBuffer2;
-    TextFileToBuffer(file.get(),mBuffer2);
-    mBuffer = (unsigned char*)&mBuffer2[0];
+      streamedBuffer.close();
+      throw DeadlyImportError("Invalid .ply file: Unknown file format");
+    }
+  }
+  else
+  {
+    AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+    if (mGeneratedMesh != NULL)
+      delete(mGeneratedMesh);
+
+    streamedBuffer.close();
+    throw DeadlyImportError("Invalid .ply file: Missing format specification");
+  }
+
+  //free the file buffer
+  streamedBuffer.close();
+
+  if (mGeneratedMesh == NULL)
+  {
+    throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data ");
+  }
+
+  // if no face list is existing we assume that the vertex
+  // list is containing a list of points
+  bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false;
+  if (pointsOnly)
+  {
+    if (mGeneratedMesh->mNumVertices < 3)
+    {
+      if (mGeneratedMesh != NULL)
+        delete(mGeneratedMesh);
 
 
-    // the beginning of the file must be PLY - magic, magic
-    if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') ||
-        (mBuffer[1] != 'L' && mBuffer[1] != 'l') ||
-        (mBuffer[2] != 'Y' && mBuffer[2] != 'y'))   {
-        throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there");
+      streamedBuffer.close();
+      throw DeadlyImportError("Invalid .ply file: Not enough "
+        "vertices to build a proper face list. ");
     }
     }
 
 
-    char* szMe = (char*)&this->mBuffer[3];
-    SkipSpacesAndLineEnd(szMe,(const char**)&szMe);
-
-    // determine the format of the file data
-    PLY::DOM sPlyDom;
-    if (TokenMatch(szMe,"format",6)) {
-        if (TokenMatch(szMe,"ascii",5)) {
-            SkipLine(szMe,(const char**)&szMe);
-            if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
-                throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)");
-        } else if (!::strncmp(szMe,"binary_",7))
-        {
-            szMe += 7;
-            const bool bIsBE( isBigEndian( szMe ) );
+    const unsigned int iNum = (unsigned int)mGeneratedMesh->mNumVertices / 3;
+    mGeneratedMesh->mNumFaces = iNum;
+    mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
 
 
-            // skip the line, parse the rest of the header and build the DOM
-            SkipLine(szMe,(const char**)&szMe);
-            if ( !PLY::DOM::ParseInstanceBinary( szMe, &sPlyDom, bIsBE ) ) {
-                throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)" );
-            }
-        } else {
-            throw DeadlyImportError( "Invalid .ply file: Unknown file format" );
-        }
-    }
-    else
+    for (unsigned int i = 0; i < iNum; ++i)
     {
     {
-        AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
-        throw DeadlyImportError( "Invalid .ply file: Missing format specification");
+      mGeneratedMesh->mFaces[i].mNumIndices = 3;
+      mGeneratedMesh->mFaces[i].mIndices = new unsigned int[3];
+      mGeneratedMesh->mFaces[i].mIndices[0] = (i * 3);
+      mGeneratedMesh->mFaces[i].mIndices[1] = (i * 3) + 1;
+      mGeneratedMesh->mFaces[i].mIndices[2] = (i * 3) + 2;
     }
     }
-    this->pcDOM = &sPlyDom;
+  }
+
+  // now load a list of all materials
+  std::vector<aiMaterial*> avMaterials;
+  std::string defaultTexture;
+  LoadMaterial(&avMaterials, defaultTexture, pointsOnly);
+
+  // now generate the output scene object. Fill the material list
+  pScene->mNumMaterials = (unsigned int)avMaterials.size();
+  pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+  for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
+    pScene->mMaterials[i] = avMaterials[i];
+  }
+
+  // fill the mesh list
+  pScene->mNumMeshes = 1;
+  pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+  pScene->mMeshes[0] = mGeneratedMesh;
+
+  // generate a simple node structure
+  pScene->mRootNode = new aiNode();
+  pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+  pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+
+  for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i) {
+    pScene->mRootNode->mMeshes[i] = i;
+  }
+}
 
 
-    // now load a list of vertices. This must be successfully in order to procedure
-    std::vector<aiVector3D> avPositions;
-    this->LoadVertices(&avPositions,false);
+void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos)
+{
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != instElement);
 
 
-    if ( avPositions.empty() ) {
-        throw DeadlyImportError( "Invalid .ply file: No vertices found. "
-            "Unable to parse the data format of the PLY file." );
-    }
+  ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
+
+  ai_uint aiNormal[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
+
+  unsigned int aiColors[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char };
+
+  unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF };
+  PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
 
 
-    // now load a list of normals.
-    std::vector<aiVector3D> avNormals;
-    LoadVertices(&avNormals,true);
+  unsigned int cnt = 0;
 
 
-    // load the face list
-    std::vector<PLY::Face> avFaces;
-    LoadFaces(&avFaces);
+  // now check whether which normal components are available
+  unsigned int _a = 0;
+  for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+    a != pcElement->alProperties.end(); ++a, ++_a)
+  {
+    if ((*a).bIsList)continue;
 
 
-    // if no face list is existing we assume that the vertex
-    // list is containing a list of triangles
-    if (avFaces.empty())
+    // Positions
+    if (PLY::EST_XCoord == (*a).Semantic)
     {
     {
-        if (avPositions.size() < 3)
-        {
-            throw DeadlyImportError( "Invalid .ply file: Not enough "
-                "vertices to build a proper face list. ");
-        }
+      cnt++;
+      aiPositions[0] = _a;
+      aiTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_YCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiPositions[1] = _a;
+      aiTypes[1] = (*a).eType;
+    }
+    else if (PLY::EST_ZCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiPositions[2] = _a;
+      aiTypes[2] = (*a).eType;
+    }
 
 
-        const unsigned int iNum = (unsigned int)avPositions.size() / 3;
-        for (unsigned int i = 0; i< iNum;++i)
-        {
-            PLY::Face sFace;
-            sFace.mIndices.push_back((iNum*3));
-            sFace.mIndices.push_back((iNum*3)+1);
-            sFace.mIndices.push_back((iNum*3)+2);
-            avFaces.push_back(sFace);
-        }
+    // Normals
+    else if (PLY::EST_XNormal == (*a).Semantic)
+    {
+      cnt++;
+      aiNormal[0] = _a;
+      aiNormalTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_YNormal == (*a).Semantic)
+    {
+      cnt++;
+      aiNormal[1] = _a;
+      aiNormalTypes[1] = (*a).eType;
+    }
+    else if (PLY::EST_ZNormal == (*a).Semantic)
+    {
+      cnt++;
+      aiNormal[2] = _a;
+      aiNormalTypes[2] = (*a).eType;
+    }
+    // Colors
+    else if (PLY::EST_Red == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[0] = _a;
+      aiColorsTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_Green == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[1] = _a;
+      aiColorsTypes[1] = (*a).eType;
+    }
+    else if (PLY::EST_Blue == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[2] = _a;
+      aiColorsTypes[2] = (*a).eType;
+    }
+    else if (PLY::EST_Alpha == (*a).Semantic)
+    {
+      cnt++;
+      aiColors[3] = _a;
+      aiColorsTypes[3] = (*a).eType;
+    }
+    // Texture coordinates
+    else if (PLY::EST_UTextureCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiTexcoord[0] = _a;
+      aiTexcoordTypes[0] = (*a).eType;
+    }
+    else if (PLY::EST_VTextureCoord == (*a).Semantic)
+    {
+      cnt++;
+      aiTexcoord[1] = _a;
+      aiTexcoordTypes[1] = (*a).eType;
+    }
+  }
+
+  // check whether we have a valid source for the vertex data
+  if (0 != cnt)
+  {
+    // Position
+    aiVector3D vOut;
+    if (0xFFFFFFFF != aiPositions[0])
+    {
+      vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
     }
     }
 
 
-    // now load a list of all materials
-    std::vector<aiMaterial*> avMaterials;
-    LoadMaterial(&avMaterials);
+    if (0xFFFFFFFF != aiPositions[1])
+    {
+      vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
+    }
 
 
-    // now load a list of all vertex color channels
-    std::vector<aiColor4D> avColors;
-    avColors.reserve(avPositions.size());
-    LoadVertexColor(&avColors);
+    if (0xFFFFFFFF != aiPositions[2])
+    {
+      vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
+    }
 
 
-    // now try to load texture coordinates
-    std::vector<aiVector2D> avTexCoords;
-    avTexCoords.reserve(avPositions.size());
-    LoadTextureCoordinates(&avTexCoords);
+    // Normals
+    aiVector3D nOut;
+    bool haveNormal = false;
+    if (0xFFFFFFFF != aiNormal[0])
+    {
+      nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
+      haveNormal = true;
+    }
 
 
-    // now replace the default material in all faces and validate all material indices
-    ReplaceDefaultMaterial(&avFaces,&avMaterials);
+    if (0xFFFFFFFF != aiNormal[1])
+    {
+      nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
+      haveNormal = true;
+    }
 
 
-    // now convert this to a list of aiMesh instances
-    std::vector<aiMesh*> avMeshes;
-    avMeshes.reserve(avMaterials.size()+1);
-    ConvertMeshes(&avFaces,&avPositions,&avNormals,
-        &avColors,&avTexCoords,&avMaterials,&avMeshes);
+    if (0xFFFFFFFF != aiNormal[2])
+    {
+      nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
+      haveNormal = true;
+    }
 
 
-    if ( avMeshes.empty() ) {
-        throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data " );
+    //Colors
+    aiColor4D cOut;
+    bool haveColor = false;
+    if (0xFFFFFFFF != aiColors[0])
+    {
+      cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[0]).avList.front(), aiColorsTypes[0]);
+      haveColor = true;
     }
     }
 
 
-    // now generate the output scene object. Fill the material list
-    pScene->mNumMaterials = (unsigned int)avMaterials.size();
-    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-    for ( unsigned int i = 0; i < pScene->mNumMaterials; ++i ) {
-        pScene->mMaterials[ i ] = avMaterials[ i ];
+    if (0xFFFFFFFF != aiColors[1])
+    {
+      cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[1]).avList.front(), aiColorsTypes[1]);
+      haveColor = true;
     }
     }
 
 
-    // fill the mesh list
-    pScene->mNumMeshes = (unsigned int)avMeshes.size();
-    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-    for ( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) {
-        pScene->mMeshes[ i ] = avMeshes[ i ];
+    if (0xFFFFFFFF != aiColors[2])
+    {
+      cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[2]).avList.front(), aiColorsTypes[2]);
+      haveColor = true;
     }
     }
 
 
-    // generate a simple node structure
-    pScene->mRootNode = new aiNode();
-    pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
-    pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+    // assume 1.0 for the alpha channel ifit is not set
+    if (0xFFFFFFFF == aiColors[3])
+    {
+      cOut.a = 1.0;
+    }
+    else
+    {
+      cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
+        aiColors[3]).avList.front(), aiColorsTypes[3]);
 
 
-    for ( unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i ) {
-        pScene->mRootNode->mMeshes[ i ] = i;
+      haveColor = true;
     }
     }
-}
 
 
-// ------------------------------------------------------------------------------------------------
-// Split meshes by material IDs
-void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
-    const std::vector<aiVector3D>*          avPositions,
-    const std::vector<aiVector3D>*          avNormals,
-    const std::vector<aiColor4D>*           avColors,
-    const std::vector<aiVector2D>*          avTexCoords,
-    const std::vector<aiMaterial*>*     avMaterials,
-    std::vector<aiMesh*>* avOut)
-{
-    ai_assert(NULL != avFaces);
-    ai_assert(NULL != avPositions);
-    ai_assert(NULL != avMaterials);
+    //Texture coordinates
+    aiVector3D tOut;
+    tOut.z = 0;
+    bool haveTextureCoords = false;
+    if (0xFFFFFFFF != aiTexcoord[0])
+    {
+      tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
+      haveTextureCoords = true;
+    }
 
 
-    // split by materials
-    std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()];
+    if (0xFFFFFFFF != aiTexcoord[1])
+    {
+      tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
+        GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
+      haveTextureCoords = true;
+    }
 
 
-    unsigned int iNum = 0;
-    for (std::vector<PLY::Face>::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum)
-        aiSplit[(*i).iMaterialIndex].push_back(iNum);
+    //create aiMesh if needed
+    if (mGeneratedMesh == NULL)
+    {
+      mGeneratedMesh = new aiMesh();
+      mGeneratedMesh->mMaterialIndex = 0;
+    }
 
 
-    // now generate sub-meshes
-    for (unsigned int p = 0; p < avMaterials->size();++p)
+    if (mGeneratedMesh->mVertices == NULL)
     {
     {
-        if (aiSplit[p].size() != 0)
-        {
-            // allocate the mesh object
-            aiMesh* p_pcOut = new aiMesh();
-            p_pcOut->mMaterialIndex = p;
+      mGeneratedMesh->mNumVertices = pcElement->NumOccur;
+      mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
+    }
 
 
-            p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
-            p_pcOut->mFaces = new aiFace[aiSplit[p].size()];
+    mGeneratedMesh->mVertices[pos] = vOut;
 
 
-            // at first we need to determine the size of the output vector array
-            unsigned int iNum = 0;
-            for (unsigned int i = 0; i < aiSplit[p].size();++i)
-            {
-                iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
-            }
-            p_pcOut->mNumVertices = iNum;
-            if( 0 == iNum ) {     // nothing to do
-                delete[] aiSplit; // cleanup
-                delete p_pcOut;
-                return;
-            }
-            p_pcOut->mVertices = new aiVector3D[iNum];
+    if (haveNormal)
+    {
+      if (mGeneratedMesh->mNormals == NULL)
+        mGeneratedMesh->mNormals = new aiVector3D[mGeneratedMesh->mNumVertices];
+      mGeneratedMesh->mNormals[pos] = nOut;
+    }
 
 
-            if (!avColors->empty())
-                p_pcOut->mColors[0] = new aiColor4D[iNum];
-            if (!avTexCoords->empty())
-            {
-                p_pcOut->mNumUVComponents[0] = 2;
-                p_pcOut->mTextureCoords[0] = new aiVector3D[iNum];
-            }
-            if (!avNormals->empty())
-                p_pcOut->mNormals = new aiVector3D[iNum];
-
-            // add all faces
-            iNum = 0;
-            unsigned int iVertex = 0;
-            for (std::vector<unsigned int>::const_iterator i =  aiSplit[p].begin();
-                i != aiSplit[p].end();++i,++iNum)
-            {
-                p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size();
-                p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices];
-
-                // build an unique set of vertices/colors for this face
-                for (unsigned int q = 0; q <  p_pcOut->mFaces[iNum].mNumIndices;++q)
-                {
-                    p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
-                    const size_t idx = ( *avFaces )[ *i ].mIndices[ q ];
-                    if( idx >= ( *avPositions ).size() ) {
-                        // out of border
-                        continue;
-                    }
-                    p_pcOut->mVertices[ iVertex ] = ( *avPositions )[ idx ];
-
-                    if (!avColors->empty())
-                        p_pcOut->mColors[ 0 ][ iVertex ] = ( *avColors )[ idx ];
-
-                    if (!avTexCoords->empty())
-                    {
-                        const aiVector2D& vec = ( *avTexCoords )[ idx ];
-                        p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
-                        p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
-                    }
-
-                    if (!avNormals->empty())
-                        p_pcOut->mNormals[ iVertex ] = ( *avNormals )[ idx ];
-                    iVertex++;
-                }
+    if (haveColor)
+    {
+      if (mGeneratedMesh->mColors[0] == NULL)
+        mGeneratedMesh->mColors[0] = new aiColor4D[mGeneratedMesh->mNumVertices];
+      mGeneratedMesh->mColors[0][pos] = cOut;
+    }
 
 
-            }
-            // add the mesh to the output list
-            avOut->push_back(p_pcOut);
-        }
+    if (haveTextureCoords)
+    {
+      if (mGeneratedMesh->mTextureCoords[0] == NULL)
+      {
+        mGeneratedMesh->mNumUVComponents[0] = 2;
+        mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
+      }
+      mGeneratedMesh->mTextureCoords[0][pos] = tOut;
     }
     }
-    delete[] aiSplit; // cleanup
+  }
 }
 }
 
 
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-// Generate a default material if none was specified and apply it to all vanilla faces
-void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
-    std::vector<aiMaterial*>* avMaterials)
+// Convert a color component to [0...1]
+ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val,
+  PLY::EDataType eType)
 {
 {
-    bool bNeedDefaultMat = false;
+  switch (eType)
+  {
+  case EDT_Float:
+    return val.fFloat;
+  case EDT_Double:
+    return (ai_real)val.fDouble;
+
+  case EDT_UChar:
+    return (ai_real)val.iUInt / (ai_real)0xFF;
+  case EDT_Char:
+    return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF;
+  case EDT_UShort:
+    return (ai_real)val.iUInt / (ai_real)0xFFFF;
+  case EDT_Short:
+    return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF;
+  case EDT_UInt:
+    return (ai_real)val.iUInt / (ai_real)0xFFFF;
+  case EDT_Int:
+    return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
+  default:;
+  };
+  return 0.0f;
+}
 
 
-    for (std::vector<PLY::Face>::iterator i =  avFaces->begin();i != avFaces->end();++i)    {
-        if (0xFFFFFFFF == (*i).iMaterialIndex)  {
-            bNeedDefaultMat = true;
-            (*i).iMaterialIndex = (unsigned int)avMaterials->size();
-        }
-        else if ((*i).iMaterialIndex >= avMaterials->size() )   {
-            // clamp the index
-            (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1;
-        }
-    }
+// ------------------------------------------------------------------------------------------------
+// Try to extract proper faces from the PLY DOM
+void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos)
+{
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != instElement);
 
 
-    if (bNeedDefaultMat)    {
-        // generate a default material
-        aiMaterial* pcHelper = new aiMaterial();
+  if (mGeneratedMesh == NULL)
+    throw DeadlyImportError("Invalid .ply file: Vertices shoud be declared before faces");
 
 
-        // fill in a default material
-        int iMode = (int)aiShadingMode_Gouraud;
-        pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+  bool bOne = false;
 
 
-        aiColor3D clr;
-        clr.b = clr.g = clr.r = 0.6f;
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+  // index of the vertex index list
+  unsigned int iProperty = 0xFFFFFFFF;
+  PLY::EDataType eType = EDT_Char;
+  bool bIsTriStrip = false;
 
 
-        clr.b = clr.g = clr.r = 0.05f;
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+  // index of the material index property
+  //unsigned int iMaterialIndex = 0xFFFFFFFF;
+  //PLY::EDataType eType2 = EDT_Char;
 
 
-        // The face order is absolutely undefined for PLY, so we have to
-        // use two-sided rendering to be sure it's ok.
-        const int two_sided = 1;
-        pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
+  // texture coordinates
+  unsigned int iTextureCoord = 0xFFFFFFFF;
+  PLY::EDataType eType3 = EDT_Char;
 
 
-        avMaterials->push_back(pcHelper);
+  // face = unique number of vertex indices
+  if (PLY::EEST_Face == pcElement->eSemantic)
+  {
+    unsigned int _a = 0;
+    for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+      a != pcElement->alProperties.end(); ++a, ++_a)
+    {
+      if (PLY::EST_VertexIndex == (*a).Semantic)
+      {
+        // must be a dynamic list!
+        if (!(*a).bIsList)
+          continue;
+
+        iProperty = _a;
+        bOne = true;
+        eType = (*a).eType;
+      }
+      /*else if (PLY::EST_MaterialIndex == (*a).Semantic)
+      {
+      if ((*a).bIsList)
+      continue;
+      iMaterialIndex = _a;
+      bOne = true;
+      eType2 = (*a).eType;
+      }*/
+      else if (PLY::EST_TextureCoordinates == (*a).Semantic)
+      {
+        // must be a dynamic list!
+        if (!(*a).bIsList)
+          continue;
+        iTextureCoord = _a;
+        bOne = true;
+        eType3 = (*a).eType;
+      }
     }
     }
-}
-
-// ------------------------------------------------------------------------------------------------
-void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
-{
-    ai_assert(NULL != pvOut);
-
-    unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF};
-    PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char};
-    PLY::ElementInstanceList* pcList = NULL;
-    unsigned int cnt = 0;
-
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
+  }
+  // triangle strip
+  // TODO: triangle strip and material index support???
+  else if (PLY::EEST_TriStrip == pcElement->eSemantic)
+  {
+    unsigned int _a = 0;
+    for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+      a != pcElement->alProperties.end(); ++a, ++_a)
     {
     {
-        if (PLY::EEST_Vertex == (*i).eSemantic)
-        {
-            pcList = &this->pcDOM->alElementData[_i];
+      // must be a dynamic list!
+      if (!(*a).bIsList)
+        continue;
+      iProperty = _a;
+      bOne = true;
+      bIsTriStrip = true;
+      eType = (*a).eType;
+      break;
+    }
+  }
 
 
-            // now check whether which normal components are available
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if ((*a).bIsList)continue;
-                if (PLY::EST_UTextureCoord == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[0] = _a;
-                    aiTypes[0] = (*a).eType;
-                }
-                else if (PLY::EST_VTextureCoord == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[1] = _a;
-                    aiTypes[1] = (*a).eType;
-                }
-            }
-        }
+  // check whether we have at least one per-face information set
+  if (bOne)
+  {
+    if (mGeneratedMesh->mFaces == NULL)
+    {
+      mGeneratedMesh->mNumFaces = pcElement->NumOccur;
+      mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
     }
     }
-    // check whether we have a valid source for the texture coordinates data
-    if (NULL != pcList && 0 != cnt)
+
+    if (!bIsTriStrip)
     {
     {
-        pvOut->reserve(pcList->alInstances.size());
-        for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
-            i != pcList->alInstances.end();++i)
-        {
-            // convert the vertices to sp floats
-            aiVector2D vOut;
+      // parse the list of vertex indices
+      if (0xFFFFFFFF != iProperty)
+      {
+        const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
+        mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
+        mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
 
 
-            if (0xFFFFFFFF != aiPositions[0])
-            {
-                vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
-            }
+        std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+          GetProperty(instElement->alProperties, iProperty).avList.begin();
 
 
-            if (0xFFFFFFFF != aiPositions[1])
-            {
-                vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
-            }
-            // and add them to our nice list
-            pvOut->push_back(vOut);
+        for (unsigned int a = 0; a < iNum; ++a, ++p)
+        {
+          mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
         }
         }
-    }
-}
+      }
 
 
-// ------------------------------------------------------------------------------------------------
-// Try to extract vertices from the PLY DOM
-void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
-{
-    ai_assert(NULL != pvOut);
+      // parse the material index
+      // cannot be handled without processing the whole file first
+      /*if (0xFFFFFFFF != iMaterialIndex)
+      {
+      mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo<unsigned int>(
+      GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
+      }*/
 
 
-    ai_uint aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-    PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char};
-    PLY::ElementInstanceList* pcList = NULL;
-    unsigned int cnt = 0;
+      if (0xFFFFFFFF != iTextureCoord)
+      {
+        const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
 
 
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i =  pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
-    {
-        if (PLY::EEST_Vertex == (*i).eSemantic)
-        {
-            pcList = &pcDOM->alElementData[_i];
+        //should be 6 coords
+        std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+          GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
 
 
-            // load normal vectors?
-            if (p_bNormals)
-            {
-                // now check whether which normal components are available
-                unsigned int _a = 0;
-                for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
-                    a != (*i).alProperties.end();++a,++_a)
-                {
-                    if ((*a).bIsList)continue;
-                    if (PLY::EST_XNormal == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[0] = _a;
-                        aiTypes[0] = (*a).eType;
-                    }
-                    else if (PLY::EST_YNormal == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[1] = _a;
-                        aiTypes[1] = (*a).eType;
-                    }
-                    else if (PLY::EST_ZNormal == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[2] = _a;
-                        aiTypes[2] = (*a).eType;
-                    }
-                }
-            }
-            // load vertex coordinates
-            else
+        if ((iNum / 3) == 2) // X Y coord
+        {
+          for (unsigned int a = 0; a < iNum; ++a, ++p)
+          {
+            unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
+            if (vindex < mGeneratedMesh->mNumVertices)
             {
             {
-                // now check whether which coordinate sets are available
-                unsigned int _a = 0;
-                for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
-                    a != (*i).alProperties.end();++a,++_a)
-                {
-                    if ((*a).bIsList)continue;
-                    if (PLY::EST_XCoord == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[0] = _a;
-                        aiTypes[0] = (*a).eType;
-                    }
-                    else if (PLY::EST_YCoord == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[1] = _a;
-                        aiTypes[1] = (*a).eType;
-                    }
-                    else if (PLY::EST_ZCoord == (*a).Semantic)
-                    {
-                        cnt++;
-                        aiPositions[2] = _a;
-                        aiTypes[2] = (*a).eType;
-                    }
-                    if (3 == cnt)break;
-                }
+              if (mGeneratedMesh->mTextureCoords[0] == NULL)
+              {
+                mGeneratedMesh->mNumUVComponents[0] = 2;
+                mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
+              }
+
+              if (a % 2 == 0)
+                mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
+              else
+                mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
+
+              mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
             }
             }
-            break;
+          }
         }
         }
+      }
     }
     }
-    // check whether we have a valid source for the vertex data
-    if (NULL != pcList && 0 != cnt)
+    else // triangle strips
     {
     {
-        pvOut->reserve(pcList->alInstances.size());
-        for (std::vector<ElementInstance>::const_iterator
-            i =  pcList->alInstances.begin();
-            i != pcList->alInstances.end();++i)
-        {
-            // convert the vertices to sp floats
-            aiVector3D vOut;
-
-            if (0xFFFFFFFF != aiPositions[0])
-            {
-                vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
-            }
+      // normally we have only one triangle strip instance where
+      // a value of -1 indicates a restart of the strip
+      bool flip = false;
+      const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty(instElement->alProperties, iProperty).avList;
+      //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
+
+      int aiTable[2] = { -1, -1 };
+      for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a)  {
+        const int p = PLY::PropertyInstance::ConvertTo<int>(*a, eType);
+
+        if (-1 == p)    {
+          // restart the strip ...
+          aiTable[0] = aiTable[1] = -1;
+          flip = false;
+          continue;
+        }
+        if (-1 == aiTable[0]) {
+          aiTable[0] = p;
+          continue;
+        }
+        if (-1 == aiTable[1]) {
+          aiTable[1] = p;
+          continue;
+        }
 
 
-            if (0xFFFFFFFF != aiPositions[1])
-            {
-                vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
-            }
+        if (mGeneratedMesh->mFaces == NULL)
+        {
+          mGeneratedMesh->mNumFaces = pcElement->NumOccur;
+          mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
+        }
 
 
-            if (0xFFFFFFFF != aiPositions[2])
-            {
-                vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
-                    GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
-            }
+        mGeneratedMesh->mFaces[pos].mNumIndices = 3;
+        mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3];
+        mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0];
+        mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
+        mGeneratedMesh->mFaces[pos].mIndices[2] = aiTable[2];
 
 
-            // and add them to our nice list
-            pvOut->push_back(vOut);
+        if ((flip = !flip)) {
+          std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
         }
         }
+
+        aiTable[0] = aiTable[1];
+        aiTable[1] = p;
+      }
     }
     }
+  }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-// Convert a color component to [0...1]
-ai_real PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,
-    PLY::EDataType eType)
+// Get a RGBA color in [0...1] range
+void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
+  unsigned int aiPositions[4],
+  PLY::EDataType aiTypes[4],
+  aiColor4D* clrOut)
 {
 {
-    switch (eType)
-    {
-    case EDT_Float:
-        return val.fFloat;
-    case EDT_Double:
-        return (ai_real)val.fDouble;
-
-    case EDT_UChar:
-        return (ai_real)val.iUInt / (ai_real)0xFF;
-    case EDT_Char:
-        return (ai_real)(val.iInt+(0xFF/2)) / (ai_real)0xFF;
-    case EDT_UShort:
-        return (ai_real)val.iUInt / (ai_real)0xFFFF;
-    case EDT_Short:
-        return (ai_real)(val.iInt+(0xFFFF/2)) / (ai_real)0xFFFF;
-    case EDT_UInt:
-        return (ai_real)val.iUInt / (ai_real)0xFFFF;
-    case EDT_Int:
-        return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
-    default: ;
-    };
-    return 0.0f;
+  ai_assert(NULL != clrOut);
+
+  if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
+  else
+  {
+    clrOut->r = NormalizeColorValue(GetProperty(avList,
+      aiPositions[0]).avList.front(), aiTypes[0]);
+  }
+
+  if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
+  else
+  {
+    clrOut->g = NormalizeColorValue(GetProperty(avList,
+      aiPositions[1]).avList.front(), aiTypes[1]);
+  }
+
+  if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
+  else
+  {
+    clrOut->b = NormalizeColorValue(GetProperty(avList,
+      aiPositions[2]).avList.front(), aiTypes[2]);
+  }
+
+  // assume 1.0 for the alpha channel ifit is not set
+  if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
+  else
+  {
+    clrOut->a = NormalizeColorValue(GetProperty(avList,
+      aiPositions[3]).avList.front(), aiTypes[3]);
+  }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-// Try to extract proper vertex colors from the PLY DOM
-void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
+// Extract a material from the PLY DOM
+void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly)
 {
 {
-    ai_assert(NULL != pvOut);
-
-    unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-    PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc
-    unsigned int cnt = 0;
-    PLY::ElementInstanceList* pcList = NULL;
-
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
+  ai_assert(NULL != pvOut);
+
+  // diffuse[4], specular[4], ambient[4]
+  // rgba order
+  unsigned int aaiPositions[3][4] = {
+
+    { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
+    { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
+    { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
+  };
+
+  PLY::EDataType aaiTypes[3][4] = {
+    { EDT_Char, EDT_Char, EDT_Char, EDT_Char },
+    { EDT_Char, EDT_Char, EDT_Char, EDT_Char },
+    { EDT_Char, EDT_Char, EDT_Char, EDT_Char }
+  };
+  PLY::ElementInstanceList* pcList = NULL;
+
+  unsigned int iPhong = 0xFFFFFFFF;
+  PLY::EDataType ePhong = EDT_Char;
+
+  unsigned int iOpacity = 0xFFFFFFFF;
+  PLY::EDataType eOpacity = EDT_Char;
+
+  // search in the DOM for a vertex entry
+  unsigned int _i = 0;
+  for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
+    i != this->pcDOM->alElements.end(); ++i, ++_i)
+  {
+    if (PLY::EEST_Material == (*i).eSemantic)
     {
     {
-        if (PLY::EEST_Vertex == (*i).eSemantic)
+      pcList = &this->pcDOM->alElementData[_i];
+
+      // now check whether which coordinate sets are available
+      unsigned int _a = 0;
+      for (std::vector<PLY::Property>::const_iterator
+        a = (*i).alProperties.begin();
+        a != (*i).alProperties.end(); ++a, ++_a)
+      {
+        if ((*a).bIsList)continue;
+
+        // pohng specularity      -----------------------------------
+        if (PLY::EST_PhongPower == (*a).Semantic)
         {
         {
-            pcList = &this->pcDOM->alElementData[_i];
-
-            // now check whether which coordinate sets are available
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator
-                a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if ((*a).bIsList)continue;
-                if (PLY::EST_Red == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[0] = _a;
-                    aiTypes[0] = (*a).eType;
-                }
-                else if (PLY::EST_Green == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[1] = _a;
-                    aiTypes[1] = (*a).eType;
-                }
-                else if (PLY::EST_Blue == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[2] = _a;
-                    aiTypes[2] = (*a).eType;
-                }
-                else if (PLY::EST_Alpha == (*a).Semantic)
-                {
-                    cnt++;
-                    aiPositions[3] = _a;
-                    aiTypes[3] = (*a).eType;
-                }
-                if (4 == cnt)break;
-            }
-            break;
+          iPhong = _a;
+          ePhong = (*a).eType;
         }
         }
-    }
-    // check whether we have a valid source for the vertex data
-    if (NULL != pcList && 0 != cnt)
-    {
-        pvOut->reserve(pcList->alInstances.size());
-        for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
-            i != pcList->alInstances.end();++i)
-        {
-            // convert the vertices to sp floats
-            aiColor4D vOut;
-
-            if (0xFFFFFFFF != aiPositions[0])
-            {
-                vOut.r = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[0]).avList.front(),aiTypes[0]);
-            }
-
-            if (0xFFFFFFFF != aiPositions[1])
-            {
-                vOut.g = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[1]).avList.front(),aiTypes[1]);
-            }
-
-            if (0xFFFFFFFF != aiPositions[2])
-            {
-                vOut.b = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[2]).avList.front(),aiTypes[2]);
-            }
-
-            // assume 1.0 for the alpha channel ifit is not set
-            if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0;
-            else
-            {
-                vOut.a = NormalizeColorValue(GetProperty((*i).alProperties,
-                    aiPositions[3]).avList.front(),aiTypes[3]);
-            }
 
 
-            // and add them to our nice list
-            pvOut->push_back(vOut);
+        // general opacity        -----------------------------------
+        if (PLY::EST_Opacity == (*a).Semantic)
+        {
+          iOpacity = _a;
+          eOpacity = (*a).eType;
         }
         }
-    }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Try to extract proper faces from the PLY DOM
-void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
-{
-    ai_assert(NULL != pvOut);
 
 
-    PLY::ElementInstanceList* pcList = NULL;
-    bool bOne = false;
-
-    // index of the vertex index list
-    unsigned int iProperty = 0xFFFFFFFF;
-    PLY::EDataType eType = EDT_Char;
-    bool bIsTriStrip = false;
-
-    // index of the material index property
-    unsigned int iMaterialIndex = 0xFFFFFFFF;
-    PLY::EDataType eType2 = EDT_Char;
-
-    // search in the DOM for a face entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i =  pcDOM->alElements.begin();
-        i != pcDOM->alElements.end();++i,++_i)
-    {
-        // face = unique number of vertex indices
-        if (PLY::EEST_Face == (*i).eSemantic)
+        // diffuse color channels -----------------------------------
+        if (PLY::EST_DiffuseRed == (*a).Semantic)
         {
         {
-            pcList = &pcDOM->alElementData[_i];
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if (PLY::EST_VertexIndex == (*a).Semantic)
-                {
-                    // must be a dynamic list!
-                    if (!(*a).bIsList)continue;
-                    iProperty   = _a;
-                    bOne        = true;
-                    eType       = (*a).eType;
-                }
-                else if (PLY::EST_MaterialIndex == (*a).Semantic)
-                {
-                    if ((*a).bIsList)continue;
-                    iMaterialIndex  = _a;
-                    bOne            = true;
-                    eType2      = (*a).eType;
-                }
-            }
-            break;
+          aaiPositions[0][0] = _a;
+          aaiTypes[0][0] = (*a).eType;
         }
         }
-        // triangle strip
-        // TODO: triangle strip and material index support???
-        else if (PLY::EEST_TriStrip == (*i).eSemantic)
+        else if (PLY::EST_DiffuseGreen == (*a).Semantic)
         {
         {
-            // find a list property in this ...
-            pcList = &this->pcDOM->alElementData[_i];
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                // must be a dynamic list!
-                if (!(*a).bIsList)continue;
-                iProperty   = _a;
-                bOne        = true;
-                bIsTriStrip = true;
-                eType       = (*a).eType;
-                break;
-            }
-            break;
+          aaiPositions[0][1] = _a;
+          aaiTypes[0][1] = (*a).eType;
         }
         }
-    }
-    // check whether we have at least one per-face information set
-    if (pcList && bOne)
-    {
-        if (!bIsTriStrip)
+        else if (PLY::EST_DiffuseBlue == (*a).Semantic)
         {
         {
-            pvOut->reserve(pcList->alInstances.size());
-            for (std::vector<ElementInstance>::const_iterator i =  pcList->alInstances.begin();
-                i != pcList->alInstances.end();++i)
-            {
-                PLY::Face sFace;
-
-                // parse the list of vertex indices
-                if (0xFFFFFFFF != iProperty)
-                {
-                    const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size();
-                    sFace.mIndices.resize(iNum);
-
-                    std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
-                        GetProperty((*i).alProperties, iProperty).avList.begin();
-
-                    for (unsigned int a = 0; a < iNum;++a,++p)
-                    {
-                        sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p,eType);
-                    }
-                }
-
-                // parse the material index
-                if (0xFFFFFFFF != iMaterialIndex)
-                {
-                    sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
-                        GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
-                }
-                pvOut->push_back(sFace);
-            }
+          aaiPositions[0][2] = _a;
+          aaiTypes[0][2] = (*a).eType;
         }
         }
-        else // triangle strips
+        else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
         {
         {
-            // normally we have only one triangle strip instance where
-            // a value of -1 indicates a restart of the strip
-            bool flip = false;
-            for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
-                const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty((*i).alProperties, iProperty).avList;
-                pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
-
-                int aiTable[2] = {-1,-1};
-                for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a =  quak.begin();a != quak.end();++a)  {
-                    const int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType);
-
-                    if (-1 == p)    {
-                        // restart the strip ...
-                        aiTable[0] = aiTable[1] = -1;
-                        flip = false;
-                        continue;
-                    }
-                    if (-1 == aiTable[0]) {
-                        aiTable[0] = p;
-                        continue;
-                    }
-                    if (-1 == aiTable[1]) {
-                        aiTable[1] = p;
-                        continue;
-                    }
-
-                    pvOut->push_back(PLY::Face());
-                    PLY::Face& sFace = pvOut->back();
-                    sFace.mIndices[0] = aiTable[0];
-                    sFace.mIndices[1] = aiTable[1];
-                    sFace.mIndices[2] = p;
-                    if ((flip = !flip)) {
-                        std::swap(sFace.mIndices[0],sFace.mIndices[1]);
-                    }
-
-                    aiTable[0] = aiTable[1];
-                    aiTable[1] = p;
-                }
-            }
+          aaiPositions[0][3] = _a;
+          aaiTypes[0][3] = (*a).eType;
+        }
+        // specular color channels -----------------------------------
+        else if (PLY::EST_SpecularRed == (*a).Semantic)
+        {
+          aaiPositions[1][0] = _a;
+          aaiTypes[1][0] = (*a).eType;
         }
         }
+        else if (PLY::EST_SpecularGreen == (*a).Semantic)
+        {
+          aaiPositions[1][1] = _a;
+          aaiTypes[1][1] = (*a).eType;
+        }
+        else if (PLY::EST_SpecularBlue == (*a).Semantic)
+        {
+          aaiPositions[1][2] = _a;
+          aaiTypes[1][2] = (*a).eType;
+        }
+        else if (PLY::EST_SpecularAlpha == (*a).Semantic)
+        {
+          aaiPositions[1][3] = _a;
+          aaiTypes[1][3] = (*a).eType;
+        }
+        // ambient color channels -----------------------------------
+        else if (PLY::EST_AmbientRed == (*a).Semantic)
+        {
+          aaiPositions[2][0] = _a;
+          aaiTypes[2][0] = (*a).eType;
+        }
+        else if (PLY::EST_AmbientGreen == (*a).Semantic)
+        {
+          aaiPositions[2][1] = _a;
+          aaiTypes[2][1] = (*a).eType;
+        }
+        else if (PLY::EST_AmbientBlue == (*a).Semantic)
+        {
+          aaiPositions[2][2] = _a;
+          aaiTypes[2][2] = (*a).eType;
+        }
+        else if (PLY::EST_AmbientAlpha == (*a).Semantic)
+        {
+          aaiPositions[2][3] = _a;
+          aaiTypes[2][3] = (*a).eType;
+        }
+      }
+      break;
     }
     }
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get a RGBA color in [0...1] range
-void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
-    unsigned int aiPositions[4],
-    PLY::EDataType aiTypes[4],
-     aiColor4D* clrOut)
-{
-    ai_assert(NULL != clrOut);
-
-    if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
-    else
+    else if (PLY::EEST_TextureFile == (*i).eSemantic)
     {
     {
-        clrOut->r = NormalizeColorValue(GetProperty(avList,
-            aiPositions[0]).avList.front(),aiTypes[0]);
+      defaultTexture = (*i).szName;
     }
     }
-
-    if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
-    else
-    {
-        clrOut->g = NormalizeColorValue(GetProperty(avList,
-            aiPositions[1]).avList.front(),aiTypes[1]);
+  }
+  // check whether we have a valid source for the material data
+  if (NULL != pcList) {
+    for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i)  {
+      aiColor4D clrOut;
+      aiMaterial* pcHelper = new aiMaterial();
+
+      // build the diffuse material color
+      GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut);
+      pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE);
+
+      // build the specular material color
+      GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut);
+      pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR);
+
+      // build the ambient material color
+      GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut);
+      pcHelper->AddProperty<aiColor4D>(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT);
+
+      // handle phong power and shading mode
+      int iMode = (int)aiShadingMode_Gouraud;
+      if (0xFFFFFFFF != iPhong)   {
+        ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong);
+
+        // if shininess is 0 (and the pow() calculation would therefore always
+        // become 1, not depending on the angle), use gouraud lighting
+        if (fSpec)  {
+          // scale this with 15 ... hopefully this is correct
+          fSpec *= 15;
+          pcHelper->AddProperty<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
+
+          iMode = (int)aiShadingMode_Phong;
+        }
+      }
+      pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+      // handle opacity
+      if (0xFFFFFFFF != iOpacity) {
+        ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity);
+        pcHelper->AddProperty<ai_real>(&fOpacity, 1, AI_MATKEY_OPACITY);
+      }
+
+      // The face order is absolutely undefined for PLY, so we have to
+      // use two-sided rendering to be sure it's ok.
+      const int two_sided = 1;
+      pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
+
+      //default texture
+      if (!defaultTexture.empty())
+      {
+        const aiString name(defaultTexture.c_str());
+        pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
+      }
+
+      if (!pointsOnly)
+      {
+        const int two_sided = 1;
+        pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
+      }
+
+      //set to wireframe, so when using this material info we can switch to points rendering
+      if (pointsOnly)
+      {
+        const int wireframe = 1;
+        pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
+      }
+
+      // add the newly created material instance to the list
+      pvOut->push_back(pcHelper);
     }
     }
-
-    if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
-    else
+  }
+  else
+  {
+    // generate a default material
+    aiMaterial* pcHelper = new aiMaterial();
+
+    // fill in a default material
+    int iMode = (int)aiShadingMode_Gouraud;
+    pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+    //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
+    aiColor3D clr;
+    clr.b = clr.g = clr.r = 1.0f;
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
+
+    clr.b = clr.g = clr.r = 1.0f;
+    pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
+
+    // The face order is absolutely undefined for PLY, so we have to
+    // use two-sided rendering to be sure it's ok.
+    if (!pointsOnly)
     {
     {
-        clrOut->b = NormalizeColorValue(GetProperty(avList,
-            aiPositions[2]).avList.front(),aiTypes[2]);
+      const int two_sided = 1;
+      pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
     }
     }
 
 
-    // assume 1.0 for the alpha channel ifit is not set
-    if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
-    else
+    //default texture
+    if (!defaultTexture.empty())
     {
     {
-        clrOut->a = NormalizeColorValue(GetProperty(avList,
-            aiPositions[3]).avList.front(),aiTypes[3]);
+      const aiString name(defaultTexture.c_str());
+      pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
     }
     }
-}
 
 
-// ------------------------------------------------------------------------------------------------
-// Extract a material from the PLY DOM
-void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
-{
-    ai_assert(NULL != pvOut);
-
-    // diffuse[4], specular[4], ambient[4]
-    // rgba order
-    unsigned int aaiPositions[3][4] = {
-
-        {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
-        {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
-        {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
-    };
-
-    PLY::EDataType aaiTypes[3][4] = {
-        {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
-        {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
-        {EDT_Char,EDT_Char,EDT_Char,EDT_Char}
-    };
-    PLY::ElementInstanceList* pcList = NULL;
-
-    unsigned int iPhong = 0xFFFFFFFF;
-    PLY::EDataType ePhong = EDT_Char;
-
-    unsigned int iOpacity = 0xFFFFFFFF;
-    PLY::EDataType eOpacity = EDT_Char;
-
-    // search in the DOM for a vertex entry
-    unsigned int _i = 0;
-    for (std::vector<PLY::Element>::const_iterator i =  this->pcDOM->alElements.begin();
-        i != this->pcDOM->alElements.end();++i,++_i)
+    //set to wireframe, so when using this material info we can switch to points rendering
+    if (pointsOnly)
     {
     {
-        if (PLY::EEST_Material == (*i).eSemantic)
-        {
-            pcList = &this->pcDOM->alElementData[_i];
-
-            // now check whether which coordinate sets are available
-            unsigned int _a = 0;
-            for (std::vector<PLY::Property>::const_iterator
-                a =  (*i).alProperties.begin();
-                a != (*i).alProperties.end();++a,++_a)
-            {
-                if ((*a).bIsList)continue;
-
-                // pohng specularity      -----------------------------------
-                if (PLY::EST_PhongPower == (*a).Semantic)
-                {
-                    iPhong      = _a;
-                    ePhong      = (*a).eType;
-                }
-
-                // general opacity        -----------------------------------
-                if (PLY::EST_Opacity == (*a).Semantic)
-                {
-                    iOpacity        = _a;
-                    eOpacity        = (*a).eType;
-                }
-
-                // diffuse color channels -----------------------------------
-                if (PLY::EST_DiffuseRed == (*a).Semantic)
-                {
-                    aaiPositions[0][0]  = _a;
-                    aaiTypes[0][0]      = (*a).eType;
-                }
-                else if (PLY::EST_DiffuseGreen == (*a).Semantic)
-                {
-                    aaiPositions[0][1]  = _a;
-                    aaiTypes[0][1]      = (*a).eType;
-                }
-                else if (PLY::EST_DiffuseBlue == (*a).Semantic)
-                {
-                    aaiPositions[0][2]  = _a;
-                    aaiTypes[0][2]      = (*a).eType;
-                }
-                else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
-                {
-                    aaiPositions[0][3]  = _a;
-                    aaiTypes[0][3]      = (*a).eType;
-                }
-                // specular color channels -----------------------------------
-                else if (PLY::EST_SpecularRed == (*a).Semantic)
-                {
-                    aaiPositions[1][0]  = _a;
-                    aaiTypes[1][0]      = (*a).eType;
-                }
-                else if (PLY::EST_SpecularGreen == (*a).Semantic)
-                {
-                    aaiPositions[1][1]  = _a;
-                    aaiTypes[1][1]      = (*a).eType;
-                }
-                else if (PLY::EST_SpecularBlue == (*a).Semantic)
-                {
-                    aaiPositions[1][2]  = _a;
-                    aaiTypes[1][2]      = (*a).eType;
-                }
-                else if (PLY::EST_SpecularAlpha == (*a).Semantic)
-                {
-                    aaiPositions[1][3]  = _a;
-                    aaiTypes[1][3]      = (*a).eType;
-                }
-                // ambient color channels -----------------------------------
-                else if (PLY::EST_AmbientRed == (*a).Semantic)
-                {
-                    aaiPositions[2][0]  = _a;
-                    aaiTypes[2][0]      = (*a).eType;
-                }
-                else if (PLY::EST_AmbientGreen == (*a).Semantic)
-                {
-                    aaiPositions[2][1]  = _a;
-                    aaiTypes[2][1]      = (*a).eType;
-                }
-                else if (PLY::EST_AmbientBlue == (*a).Semantic)
-                {
-                    aaiPositions[2][2]  = _a;
-                    aaiTypes[2][2]      = (*a).eType;
-                }
-                else if (PLY::EST_AmbientAlpha == (*a).Semantic)
-                {
-                    aaiPositions[2][3]  = _a;
-                    aaiTypes[2][3]      = (*a).eType;
-                }
-            }
-            break;
-        }
+      const int wireframe = 1;
+      pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
     }
     }
-    // check whether we have a valid source for the material data
-    if (NULL != pcList) {
-        for (std::vector<ElementInstance>::const_iterator i =  pcList->alInstances.begin();i != pcList->alInstances.end();++i)  {
-            aiColor4D clrOut;
-            aiMaterial* pcHelper = new aiMaterial();
-
-            // build the diffuse material color
-            GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
-            pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE);
-
-            // build the specular material color
-            GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
-            pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR);
-
-            // build the ambient material color
-            GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
-            pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT);
-
-            // handle phong power and shading mode
-            int iMode = (int)aiShadingMode_Gouraud;
-            if (0xFFFFFFFF != iPhong)   {
-                ai_real fSpec = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong);
-
-                // if shininess is 0 (and the pow() calculation would therefore always
-                // become 1, not depending on the angle), use gouraud lighting
-                if (fSpec)  {
-                    // scale this with 15 ... hopefully this is correct
-                    fSpec *= 15;
-                    pcHelper->AddProperty<ai_real>(&fSpec, 1, AI_MATKEY_SHININESS);
-
-                    iMode = (int)aiShadingMode_Phong;
-                }
-            }
-            pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
-            // handle opacity
-            if (0xFFFFFFFF != iOpacity) {
-                ai_real fOpacity = PLY::PropertyInstance::ConvertTo<ai_real>(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity);
-                pcHelper->AddProperty<ai_real>(&fOpacity, 1, AI_MATKEY_OPACITY);
-            }
 
 
-            // The face order is absolutely undefined for PLY, so we have to
-            // use two-sided rendering to be sure it's ok.
-            const int two_sided = 1;
-            pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
-
-            // add the newly created material instance to the list
-            pvOut->push_back(pcHelper);
-        }
-    }
+    pvOut->push_back(pcHelper);
+  }
 }
 }
 
 
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

+ 14 - 47
code/PlyLoader.h

@@ -68,7 +68,6 @@ public:
     PLYImporter();
     PLYImporter();
     ~PLYImporter();
     ~PLYImporter();
 
 
-
 public:
 public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
@@ -78,6 +77,16 @@ public:
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
         bool checkSig) const;
         bool checkSig) const;
 
 
+    // -------------------------------------------------------------------
+    /** Extract a vertex from the DOM
+    */
+    void LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
+
+    // -------------------------------------------------------------------
+    /** Extract a face from the DOM
+    */
+    void LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
+
 protected:
 protected:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
@@ -94,53 +103,10 @@ protected:
         IOSystem* pIOHandler);
         IOSystem* pIOHandler);
 
 
 protected:
 protected:
-
-
-    // -------------------------------------------------------------------
-    /** Extract vertices from the DOM
-    */
-    void LoadVertices(std::vector<aiVector3D>* pvOut,
-        bool p_bNormals = false);
-
-    // -------------------------------------------------------------------
-    /** Extract vertex color channels from the DOM
-    */
-    void LoadVertexColor(std::vector<aiColor4D>* pvOut);
-
-    // -------------------------------------------------------------------
-    /** Extract texture coordinate channels from the DOM
-    */
-    void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut);
-
-    // -------------------------------------------------------------------
-    /** Extract a face list from the DOM
-    */
-    void LoadFaces(std::vector<PLY::Face>* pvOut);
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Extract a material list from the DOM
     /** Extract a material list from the DOM
     */
     */
-    void LoadMaterial(std::vector<aiMaterial*>* pvOut);
-
-
-    // -------------------------------------------------------------------
-    /** Validate material indices, replace default material identifiers
-    */
-    void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
-        std::vector<aiMaterial*>* avMaterials);
-
-
-    // -------------------------------------------------------------------
-    /** Convert all meshes into our ourer representation
-    */
-    void ConvertMeshes(std::vector<PLY::Face>* avFaces,
-        const std::vector<aiVector3D>* avPositions,
-        const std::vector<aiVector3D>* avNormals,
-        const std::vector<aiColor4D>* avColors,
-        const std::vector<aiVector2D>* avTexCoords,
-        const std::vector<aiMaterial*>* avMaterials,
-        std::vector<aiMesh*>* avOut);
-
+    void LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Static helper to parse a color from four single channels in
     /** Static helper to parse a color from four single channels in
@@ -151,7 +117,6 @@ protected:
         PLY::EDataType aiTypes[4],
         PLY::EDataType aiTypes[4],
         aiColor4D* clrOut);
         aiColor4D* clrOut);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Static helper to parse a color channel value. The input value
     /** Static helper to parse a color channel value. The input value
     *  is normalized to 0-1.
     *  is normalized to 0-1.
@@ -160,12 +125,14 @@ protected:
         PLY::PropertyInstance::ValueUnion val,
         PLY::PropertyInstance::ValueUnion val,
         PLY::EDataType eType);
         PLY::EDataType eType);
 
 
-
     /** Buffer to hold the loaded file */
     /** Buffer to hold the loaded file */
     unsigned char* mBuffer;
     unsigned char* mBuffer;
 
 
     /** Document object model representation extracted from the file */
     /** Document object model representation extracted from the file */
     PLY::DOM* pcDOM;
     PLY::DOM* pcDOM;
+
+    /** Mesh generated by loader */
+    aiMesh* mGeneratedMesh;
 };
 };
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp

+ 930 - 754
code/PlyParser.cpp

@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2017, assimp team
 Copyright (c) 2006-2017, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -13,18 +12,18 @@ with or without modification, are permitted provided that the following
 conditions are met:
 conditions are met:
 
 
 * Redistributions of source code must retain the above
 * Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
+copyright notice, this list of conditions and the
+following disclaimer.
 
 
 * Redistributions in binary form must reproduce the above
 * Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
 
 
 * Neither the name of the assimp team, nor the names of its
 * Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
 
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -45,916 +44,1093 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
 #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
 
 
-#include "PlyLoader.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
-
+#include "PlyLoader.h"
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-PLY::EDataType PLY::Property::ParseDataType(const char* pCur,const char** pCurOut) {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-
-    PLY::EDataType eOut = PLY::EDT_INVALID;
-
-    if (TokenMatch(pCur,"char",4) ||
-        TokenMatch(pCur,"int8",4))
-    {
-        eOut = PLY::EDT_Char;
-    }
-    else if (TokenMatch(pCur,"uchar",5) ||
-             TokenMatch(pCur,"uint8",5))
-    {
-        eOut = PLY::EDT_UChar;
-    }
-    else if (TokenMatch(pCur,"short",5) ||
-             TokenMatch(pCur,"int16",5))
-    {
-        eOut = PLY::EDT_Short;
-    }
-    else if (TokenMatch(pCur,"ushort",6) ||
-             TokenMatch(pCur,"uint16",6))
-    {
-        eOut = PLY::EDT_UShort;
-    }
-    else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3))
-    {
-        eOut = PLY::EDT_Int;
-    }
-    else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4))
-    {
-        eOut = PLY::EDT_UInt;
-    }
-    else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7))
-    {
-        eOut = PLY::EDT_Float;
-    }
-    else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) ||
-             TokenMatch(pCur,"float64",7))
-    {
-        eOut = PLY::EDT_Double;
-    }
-    if (PLY::EDT_INVALID == eOut)
-    {
-        DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
-    }
-    *pCurOut = pCur;
-
-    return eOut;
+PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) {
+  ai_assert(!buffer.empty());
+
+  PLY::EDataType eOut = PLY::EDT_INVALID;
+
+  if (PLY::DOM::TokenMatch(buffer, "char", 4) ||
+    PLY::DOM::TokenMatch(buffer, "int8", 4))
+  {
+    eOut = PLY::EDT_Char;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) ||
+    PLY::DOM::TokenMatch(buffer, "uint8", 5))
+  {
+    eOut = PLY::EDT_UChar;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "short", 5) ||
+    PLY::DOM::TokenMatch(buffer, "int16", 5))
+  {
+    eOut = PLY::EDT_Short;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) ||
+    PLY::DOM::TokenMatch(buffer, "uint16", 6))
+  {
+    eOut = PLY::EDT_UShort;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3))
+  {
+    eOut = PLY::EDT_Int;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4))
+  {
+    eOut = PLY::EDT_UInt;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7))
+  {
+    eOut = PLY::EDT_Float;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) ||
+    PLY::DOM::TokenMatch(buffer, "float64", 7))
+  {
+    eOut = PLY::EDT_Double;
+  }
+  if (PLY::EDT_INVALID == eOut)
+  {
+    DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
+  }
+
+  return eOut;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOut) {
-    ai_assert (NULL != pCur );
-    ai_assert( NULL != pCurOut );
-
-    PLY::ESemantic eOut = PLY::EST_INVALID;
-    if (TokenMatch(pCur,"red",3)) {
-        eOut = PLY::EST_Red;
-    } else if (TokenMatch(pCur,"green",5)) {
-        eOut = PLY::EST_Green;
-    } else if (TokenMatch(pCur,"blue",4)) {
-        eOut = PLY::EST_Blue;
-    } else if (TokenMatch(pCur,"alpha",5)) {
-        eOut = PLY::EST_Alpha;
-    } else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14)) {
-        eOut = PLY::EST_VertexIndex;
-    }
-    else if (TokenMatch(pCur,"material_index",14))
-    {
-        eOut = PLY::EST_MaterialIndex;
-    }
-    else if (TokenMatch(pCur,"ambient_red",11))
-    {
-        eOut = PLY::EST_AmbientRed;
-    }
-    else if (TokenMatch(pCur,"ambient_green",13))
-    {
-        eOut = PLY::EST_AmbientGreen;
-    }
-    else if (TokenMatch(pCur,"ambient_blue",12))
-    {
-        eOut = PLY::EST_AmbientBlue;
-    }
-    else if (TokenMatch(pCur,"ambient_alpha",13))
-    {
-        eOut = PLY::EST_AmbientAlpha;
-    }
-    else if (TokenMatch(pCur,"diffuse_red",11))
-    {
-        eOut = PLY::EST_DiffuseRed;
-    }
-    else if (TokenMatch(pCur,"diffuse_green",13))
-    {
-        eOut = PLY::EST_DiffuseGreen;
-    }
-    else if (TokenMatch(pCur,"diffuse_blue",12))
-    {
-        eOut = PLY::EST_DiffuseBlue;
-    }
-    else if (TokenMatch(pCur,"diffuse_alpha",13))
-    {
-        eOut = PLY::EST_DiffuseAlpha;
-    }
-    else if (TokenMatch(pCur,"specular_red",12))
-    {
-        eOut = PLY::EST_SpecularRed;
-    }
-    else if (TokenMatch(pCur,"specular_green",14))
-    {
-        eOut = PLY::EST_SpecularGreen;
-    }
-    else if (TokenMatch(pCur,"specular_blue",13))
-    {
-        eOut = PLY::EST_SpecularBlue;
-    }
-    else if (TokenMatch(pCur,"specular_alpha",14))
-    {
-        eOut = PLY::EST_SpecularAlpha;
-    }
-    else if (TokenMatch(pCur,"opacity",7))
-    {
-        eOut = PLY::EST_Opacity;
-    }
-    else if (TokenMatch(pCur,"specular_power",14))
-    {
-        eOut = PLY::EST_PhongPower;
-    }
-    else if (TokenMatch(pCur,"r",1))
-    {
-        eOut = PLY::EST_Red;
-    }
-    else if (TokenMatch(pCur,"g",1))
-    {
-        eOut = PLY::EST_Green;
-    }
-    else if (TokenMatch(pCur,"b",1))
-    {
-        eOut = PLY::EST_Blue;
-    }
-    // NOTE: Blender3D exports texture coordinates as s,t tuples
-    else if (TokenMatch(pCur,"u",1) ||  TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2) || TokenMatch(pCur,"texture_u",9))
-    {
-        eOut = PLY::EST_UTextureCoord;
-    }
-    else if (TokenMatch(pCur,"v",1) ||  TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2) || TokenMatch(pCur,"texture_v",9))
-    {
-        eOut = PLY::EST_VTextureCoord;
-    }
-    else if (TokenMatch(pCur,"x",1))
-    {
-        eOut = PLY::EST_XCoord;
-    } else if (TokenMatch(pCur,"y",1)) {
-        eOut = PLY::EST_YCoord;
-    } else if (TokenMatch(pCur,"z",1)) {
-        eOut = PLY::EST_ZCoord;
-    } else if (TokenMatch(pCur,"nx",2)) {
-        eOut = PLY::EST_XNormal;
-    } else if (TokenMatch(pCur,"ny",2)) {
-        eOut = PLY::EST_YNormal;
-    } else if (TokenMatch(pCur,"nz",2)) {
-        eOut = PLY::EST_ZNormal;
-    } else {
-        DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
-        SkipLine(&pCur);
-    }
-    *pCurOut = pCur;
-    return eOut;
+PLY::ESemantic PLY::Property::ParseSemantic(std::vector<char> &buffer) {
+  ai_assert(!buffer.empty());
+
+  PLY::ESemantic eOut = PLY::EST_INVALID;
+  if (PLY::DOM::TokenMatch(buffer, "red", 3)) {
+    eOut = PLY::EST_Red;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "green", 5)) {
+    eOut = PLY::EST_Green;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) {
+    eOut = PLY::EST_Blue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) {
+    eOut = PLY::EST_Alpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) {
+    eOut = PLY::EST_VertexIndex;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces
+  {
+    eOut = PLY::EST_TextureCoordinates;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "material_index", 14))
+  {
+    eOut = PLY::EST_MaterialIndex;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11))
+  {
+    eOut = PLY::EST_AmbientRed;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13))
+  {
+    eOut = PLY::EST_AmbientGreen;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12))
+  {
+    eOut = PLY::EST_AmbientBlue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13))
+  {
+    eOut = PLY::EST_AmbientAlpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11))
+  {
+    eOut = PLY::EST_DiffuseRed;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13))
+  {
+    eOut = PLY::EST_DiffuseGreen;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12))
+  {
+    eOut = PLY::EST_DiffuseBlue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13))
+  {
+    eOut = PLY::EST_DiffuseAlpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12))
+  {
+    eOut = PLY::EST_SpecularRed;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14))
+  {
+    eOut = PLY::EST_SpecularGreen;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13))
+  {
+    eOut = PLY::EST_SpecularBlue;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14))
+  {
+    eOut = PLY::EST_SpecularAlpha;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "opacity", 7))
+  {
+    eOut = PLY::EST_Opacity;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14))
+  {
+    eOut = PLY::EST_PhongPower;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "r", 1))
+  {
+    eOut = PLY::EST_Red;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "g", 1))
+  {
+    eOut = PLY::EST_Green;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "b", 1))
+  {
+    eOut = PLY::EST_Blue;
+  }
+
+  // NOTE: Blender3D exports texture coordinates as s,t tuples
+  else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2) || PLY::DOM::TokenMatch(buffer, "texture_u", 9))
+  {
+    eOut = PLY::EST_UTextureCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9))
+  {
+    eOut = PLY::EST_VTextureCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "x", 1))
+  {
+    eOut = PLY::EST_XCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "y", 1)) {
+    eOut = PLY::EST_YCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "z", 1)) {
+    eOut = PLY::EST_ZCoord;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) {
+    eOut = PLY::EST_XNormal;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) {
+    eOut = PLY::EST_YNormal;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) {
+    eOut = PLY::EST_ZNormal;
+  }
+  else {
+    DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
+    PLY::DOM::SkipLine(buffer);
+  }
+  return eOut;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::Property::ParseProperty (const char* pCur,
-    const char** pCurOut,
-    PLY::Property* pOut)
+bool PLY::Property::ParseProperty(std::vector<char> &buffer, PLY::Property* pOut)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
+  ai_assert(!buffer.empty());
 
 
-    // Forms supported:
-    // "property float x"
-    // "property list uchar int vertex_index"
-    *pCurOut = pCur;
+  // Forms supported:
+  // "property float x"
+  // "property list uchar int vertex_index"
 
 
-    // skip leading spaces
-    if (!SkipSpaces(pCur,&pCur)) {
-        return false;
-    }
+  // skip leading spaces
+  if (!PLY::DOM::SkipSpaces(buffer)) {
+    return false;
+  }
 
 
-    // skip the "property" string at the beginning
-    if (!TokenMatch(pCur,"property",8))
+  // skip the "property" string at the beginning
+  if (!PLY::DOM::TokenMatch(buffer, "property", 8))
+  {
+    // seems not to be a valid property entry
+    return false;
+  }
+  // get next word
+  if (!PLY::DOM::SkipSpaces(buffer)) {
+    return false;
+  }
+  if (PLY::DOM::TokenMatch(buffer, "list", 4))
+  {
+    pOut->bIsList = true;
+
+    // seems to be a list.
+    if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer)))
     {
     {
-        // seems not to be a valid property entry
-        return false;
+      // unable to parse list size data type
+      PLY::DOM::SkipLine(buffer);
+      return false;
     }
     }
-    // get next word
-    if (!SkipSpaces(pCur,&pCur)) {
-        return false;
-    }
-    if (TokenMatch(pCur,"list",4))
+    if (!PLY::DOM::SkipSpaces(buffer))return false;
+    if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer)))
     {
     {
-        pOut->bIsList = true;
-
-        // seems to be a list.
-        if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur)))
-        {
-            // unable to parse list size data type
-            SkipLine(pCur,&pCur);
-            *pCurOut = pCur;
-            return false;
-        }
-        if (!SkipSpaces(pCur,&pCur))return false;
-        if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
-        {
-            // unable to parse list data type
-            SkipLine(pCur,&pCur);
-            *pCurOut = pCur;
-            return false;
-        }
-    }
-    else
+      // unable to parse list data type
+      PLY::DOM::SkipLine(buffer);
+      return false;
+    }
+  }
+  else
+  {
+    if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer)))
     {
     {
-        if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
-        {
-            // unable to parse data type. Skip the property
-            SkipLine(pCur,&pCur);
-            *pCurOut = pCur;
-            return false;
-        }
+      // unable to parse data type. Skip the property
+      PLY::DOM::SkipLine(buffer);
+      return false;
     }
     }
+  }
 
 
-    if (!SkipSpaces(pCur,&pCur))return false;
-    const char* szCur = pCur;
-    pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur);
-
-    if (PLY::EST_INVALID == pOut->Semantic)
-    {
-        // store the name of the semantic
-        uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+  if (!PLY::DOM::SkipSpaces(buffer))
+    return false;
 
 
-        DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
-        pOut->szName = std::string(szCur,iDiff);
-    }
+  pOut->Semantic = PLY::Property::ParseSemantic(buffer);
 
 
-    SkipSpacesAndLineEnd(pCur,&pCur);
-    *pCurOut = pCur;
+  if (PLY::EST_INVALID == pOut->Semantic)
+  {
+    DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
+    std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
+  }
 
 
-    return true;
+  PLY::DOM::SkipSpacesAndLineEnd(buffer);
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur,
-    const char** pCurOut)
+PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector<char> &buffer)
 {
 {
-    ai_assert(NULL != pCur && NULL != pCurOut);
-    PLY::EElementSemantic eOut = PLY::EEST_INVALID;
-    if (TokenMatch(pCur,"vertex",6))
-    {
-        eOut = PLY::EEST_Vertex;
-    }
-    else if (TokenMatch(pCur,"face",4))
-    {
-        eOut = PLY::EEST_Face;
-    }
+  ai_assert(!buffer.empty());
+
+  PLY::EElementSemantic eOut = PLY::EEST_INVALID;
+  if (PLY::DOM::TokenMatch(buffer, "vertex", 6))
+  {
+    eOut = PLY::EEST_Vertex;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "face", 4))
+  {
+    eOut = PLY::EEST_Face;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9))
+  {
+    eOut = PLY::EEST_TriStrip;
+  }
 #if 0
 #if 0
-    // TODO: maybe implement this?
-    else if (TokenMatch(pCur,"range_grid",10))
-    {
-        eOut = PLY::EEST_Face;
-    }
+  // TODO: maybe implement this?
+  else if (PLY::DOM::TokenMatch(buffer,"range_grid",10))
+  {
+    eOut = PLY::EEST_Face;
+  }
 #endif
 #endif
-    else if (TokenMatch(pCur,"tristrips",9))
-    {
-        eOut = PLY::EEST_TriStrip;
-    }
-    else if (TokenMatch(pCur,"edge",4))
-    {
-        eOut = PLY::EEST_Edge;
-    }
-    else if (TokenMatch(pCur,"material",8))
-    {
-        eOut = PLY::EEST_Material;
-    }
-    *pCurOut = pCur;
-
-    return eOut;
+  else if (PLY::DOM::TokenMatch(buffer, "edge", 4))
+  {
+    eOut = PLY::EEST_Edge;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "material", 8))
+  {
+    eOut = PLY::EEST_Material;
+  }
+  else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11))
+  {
+    eOut = PLY::EEST_TextureFile;
+  }
+
+  return eOut;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::Element::ParseElement (const char* pCur,
-    const char** pCurOut,
-    PLY::Element* pOut)
+bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLY::Element* pOut)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pOut );
+  ai_assert(NULL != pOut);
+  // Example format: "element vertex 8"
 
 
-    // Example format: "element vertex 8"
-    *pCurOut = pCur;
+  // skip leading spaces
+  if (!PLY::DOM::SkipSpaces(buffer))
+  {
+    return false;
+  }
 
 
-    // skip leading spaces
-    if (!SkipSpaces(&pCur)) {
-        return false;
-    }
+  // skip the "element" string at the beginning
+  if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7))
+  {
+    // seems not to be a valid property entry
+    return false;
+  }
+  // get next word
+  if (!PLY::DOM::SkipSpaces(buffer))
+    return false;
 
 
-    // skip the "element" string at the beginning
-    if (!TokenMatch(pCur,"element",7))
-    {
-        // seems not to be a valid property entry
-        return false;
-    }
-    // get next word
-    if (!SkipSpaces(&pCur))return false;
+  // parse the semantic of the element
+  pOut->eSemantic = PLY::Element::ParseSemantic(buffer);
+  if (PLY::EEST_INVALID == pOut->eSemantic)
+  {
+    // if the exact semantic can't be determined, just store
+    // the original string identifier
+    pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
+  }
 
 
-    // parse the semantic of the element
-    const char* szCur = pCur;
-    pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur);
-    if (PLY::EEST_INVALID == pOut->eSemantic)
-    {
-        // if the exact semantic can't be determined, just store
-        // the original string identifier
-        uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
-        pOut->szName = std::string(szCur,iDiff);
-    }
+  if (!PLY::DOM::SkipSpaces(buffer))
+    return false;
 
 
-    if (!SkipSpaces(&pCur))return false;
+  if (PLY::EEST_TextureFile == pOut->eSemantic)
+  {
+    char* endPos = &buffer[0] + (strlen(&buffer[0]) - 1);
+    pOut->szName = std::string(&buffer[0], endPos);
+  }
 
 
-    //parse the number of occurrences of this element
-    pOut->NumOccur = strtoul10(pCur,&pCur);
+  //parse the number of occurrences of this element
+  const char* pCur = (char*)&buffer[0];
+  pOut->NumOccur = strtoul10(pCur, &pCur);
 
 
-    // go to the next line
-    SkipSpacesAndLineEnd(pCur,&pCur);
+  // go to the next line
+  PLY::DOM::SkipSpacesAndLineEnd(buffer);
 
 
-    // now parse all properties of the element
-    while(true)
-    {
-        // skip all comments
-        PLY::DOM::SkipComments(pCur,&pCur);
+  // now parse all properties of the element
+  while (true)
+  {
+    streamBuffer.getNextLine(buffer);
+    pCur = (char*)&buffer[0];
 
 
-        PLY::Property prop;
-        if(!PLY::Property::ParseProperty(pCur,&pCur,&prop))break;
-        pOut->alProperties.push_back(prop);
-    }
-    *pCurOut = pCur;
+    // skip all comments
+    PLY::DOM::SkipComments(buffer);
 
 
-    return true;
-}
+    PLY::Property prop;
+    if (!PLY::Property::ParseProperty(buffer, &prop))
+      break;
 
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::SkipComments (const char* pCur,
-    const char** pCurOut)
-{
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    *pCurOut = pCur;
+    pOut->alProperties.push_back(prop);
+  }
 
 
-    // skip spaces
-    if (!SkipSpaces(pCur,&pCur)) {
-        return false;
-    }
-
-    if (TokenMatch(pCur,"comment",7))
-    {
-        if ( !IsLineEnd(pCur[-1]) )
-        {
-            SkipLine(pCur,&pCur);
-        }
-        SkipComments(pCur,&pCur);
-        *pCurOut = pCur;
-        return true;
-    }
-    *pCurOut = pCur;
-
-    return false;
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut,bool isBinary) {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
+bool PLY::DOM::SkipSpaces(std::vector<char> &buffer)
+{
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::SkipSpaces(pCur, &pCur);
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
 
-    // after ply and format line
-    *pCurOut = pCur;
+  return ret;
+}
 
 
-    // parse all elements
-    while ((*pCur) != '\0')
-    {
-        // skip all comments
-        PLY::DOM::SkipComments(pCur,&pCur);
+bool PLY::DOM::SkipLine(std::vector<char> &buffer)
+{
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::SkipLine(pCur, &pCur);
 
 
-        PLY::Element out;
-        if(PLY::Element::ParseElement(pCur,&pCur,&out))
-        {
-            // add the element to the list of elements
-            alElements.push_back(out);
-        }
-        else if (TokenMatch(pCur,"end_header",10))
-        {
-            // we have reached the end of the header
-            break;
-        }
-        else
-        {
-            // ignore unknown header elements
-            SkipLine(&pCur);
-        }
-    }
-    if(!isBinary)
-    { // it would occur an error, if binary data start with values as space or line end.
-        SkipSpacesAndLineEnd(pCur,&pCur);
-    }
-    *pCurOut = pCur;
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
-    return true;
+  return ret;
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceLists (
-    const char* pCur,
-    const char** pCurOut)
+bool PLY::DOM::TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::TokenMatch(pCur, token, len);
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
-    *pCurOut = pCur;
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
 
-    alElementData.resize(alElements.size());
+  return ret;
+}
 
 
-    std::vector<PLY::Element>::const_iterator i = alElements.begin();
-    std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+bool PLY::DOM::SkipSpacesAndLineEnd(std::vector<char> &buffer)
+{
+  const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0];
+  bool ret = false;
+  if (pCur)
+  {
+    const char* szCur = pCur;
+    ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur);
 
 
-    // parse all element instances
-    for (;i != alElements.end();++i,++a)
-    {
-        (*a).alInstances.resize((*i).NumOccur);
-        PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a));
-    }
+    uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+    buffer.erase(buffer.begin(), buffer.begin() + iDiff);
+    return ret;
+  }
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
-    *pCurOut = pCur;
-    return true;
+  return ret;
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseElementInstanceListsBinary (
-    const char* pCur,
-    const char** pCurOut,
-    bool p_bBE)
+bool PLY::DOM::SkipComments(std::vector<char> &buffer)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut);
+  ai_assert(!buffer.empty());
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
-    *pCurOut = pCur;
-
-    alElementData.resize(alElements.size());
+  std::vector<char> nbuffer = buffer;
+  // skip spaces
+  if (!SkipSpaces(nbuffer)) {
+    return false;
+  }
 
 
-    std::vector<PLY::Element>::const_iterator i = alElements.begin();
-    std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+  if (TokenMatch(nbuffer, "comment", 7))
+  {
+    if (!SkipSpaces(nbuffer))
+      SkipLine(nbuffer);
 
 
-    // parse all element instances
-    for (;i != alElements.end();++i,++a)
+    if (!TokenMatch(nbuffer, "TextureFile", 11))
     {
     {
-        (*a).alInstances.resize((*i).NumOccur);
-        PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE);
+      SkipLine(nbuffer);
+      buffer = nbuffer;
+      return true;
     }
     }
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
-    *pCurOut = pCur;
     return true;
     return true;
+  }
+
+  return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE)
-{
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != p_pcOut );
+bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) {
+  DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
+  // parse all elements
+  while (!buffer.empty())
+  {
+    // skip all comments
+    PLY::DOM::SkipComments(buffer);
 
 
-    if(!p_pcOut->ParseHeader(pCur,&pCur,true))
+    PLY::Element out;
+    if (PLY::Element::ParseElement(streamBuffer, buffer, &out))
     {
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
-        return false;
+      // add the element to the list of elements
+      alElements.push_back(out);
     }
     }
-    if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE))
+    else if (TokenMatch(buffer, "end_header", 10))
     {
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
-        return false;
+      // we have reached the end of the header
+      break;
     }
     }
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
-    return true;
+    else
+    {
+      // ignore unknown header elements
+      streamBuffer.getNextLine(buffer);
+    }
+  }
+
+  if (!isBinary) // it would occur an error, if binary data start with values as space or line end.
+    SkipSpacesAndLineEnd(buffer);
+
+  DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut)
+bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader)
 {
 {
-    ai_assert(NULL != pCur);
-    ai_assert(NULL != p_pcOut);
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
+  alElementData.resize(alElements.size());
 
 
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
+  std::vector<PLY::Element>::const_iterator i = alElements.begin();
+  std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
 
 
-
-    if(!p_pcOut->ParseHeader(pCur,&pCur,false))
+  // parse all element instances
+  //construct vertices and faces
+  for (; i != alElements.end(); ++i, ++a)
+  {
+    if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip)
     {
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
-        return false;
+      PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), NULL, loader);
     }
     }
-    if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur))
+    else
     {
     {
-        DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
-        return false;
+      (*a).alInstances.resize((*i).NumOccur);
+      PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), NULL);
     }
     }
-    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
-    return true;
+  }
+
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceList (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstanceList* p_pcOut)
+bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+    const char* &pCur,
+    unsigned int &bufferSize,
+    PLYImporter* loader,
+    bool p_bBE)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
+  alElementData.resize(alElements.size());
 
 
-    if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
+  std::vector<PLY::Element>::const_iterator i = alElements.begin();
+  std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+
+  // parse all element instances
+  for (; i != alElements.end(); ++i, ++a)
+  {
+    if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip)
     {
     {
-        // if the element has an unknown semantic we can skip all lines
-        // However, there could be comments
-        for (unsigned int i = 0; i < pcElement->NumOccur;++i)
-        {
-            PLY::DOM::SkipComments(pCur,&pCur);
-            SkipLine(pCur,&pCur);
-        }
+      PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), NULL, loader, p_bBE);
     }
     }
     else
     else
     {
     {
-        // be sure to have enough storage
-        for (unsigned int i = 0; i < pcElement->NumOccur;++i)
-        {
-            PLY::DOM::SkipComments(pCur,&pCur);
-            PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement,
-                &p_pcOut->alInstances[i]);
-        }
+      (*a).alInstances.resize((*i).NumOccur);
+      PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), NULL, p_bBE);
     }
     }
-    *pCurOut = pCur;
-    return true;
-}
+  }
 
 
-// ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstanceList::ParseInstanceListBinary (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstanceList* p_pcOut,
-    bool p_bBE /* = false */)
-{
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
-
-    // we can add special handling code for unknown element semantics since
-    // we can't skip it as a whole block (we don't know its exact size
-    // due to the fact that lists could be contained in the property list
-    // of the unknown element)
-    for (unsigned int i = 0; i < pcElement->NumOccur;++i)
-    {
-        PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement,
-            &p_pcOut->alInstances[i], p_bBE);
-    }
-    *pCurOut = pCur;
-    return true;
+  DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstance (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstance* p_pcOut)
+bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
+  ai_assert(NULL != p_pcOut);
+  ai_assert(NULL != loader);
 
 
-    if (!SkipSpaces(pCur, &pCur)) {
-        return false;
-    }
-
-    // allocate enough storage
-    p_pcOut->alProperties.resize(pcElement->alProperties.size());
-
-    std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
-    std::vector<PLY::Property>::const_iterator  a = pcElement->alProperties.begin();
-    for (;i != p_pcOut->alProperties.end();++i,++a)
-    {
-        if(!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i))))
-        {
-            DefaultLogger::get()->warn("Unable to parse property instance. "
-                "Skipping this element instance");
+  std::vector<char> buffer;
+  streamBuffer.getNextLine(buffer);
 
 
-            // skip the rest of the instance
-            SkipLine(pCur, &pCur);
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
 
 
-            PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
-            (*i).avList.push_back(v);
-        }
-    }
-    *pCurOut = pCur;
-    return true;
+  if (!p_pcOut->ParseHeader(streamBuffer, buffer, true))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+    return false;
+  }
+
+  streamBuffer.getNextBlock(buffer);
+  unsigned int bufferSize = buffer.size();
+  const char* pCur = (char*)&buffer[0];
+  if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+    return false;
+  }
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::ElementInstance::ParseInstanceBinary (
-    const char* pCur,
-    const char** pCurOut,
-    const PLY::Element* pcElement,
-    PLY::ElementInstance* p_pcOut,
-    bool p_bBE /* = false */)
+bool PLY::DOM::ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != pcElement );
-    ai_assert( NULL != p_pcOut );
+  ai_assert(NULL != p_pcOut);
+  ai_assert(NULL != loader);
 
 
-    // allocate enough storage
-    p_pcOut->alProperties.resize(pcElement->alProperties.size());
+  std::vector<char> buffer;
+  streamBuffer.getNextLine(buffer);
 
 
-    std::vector<PLY::PropertyInstance>::iterator i =  p_pcOut->alProperties.begin();
-    std::vector<PLY::Property>::const_iterator   a =  pcElement->alProperties.begin();
-    for (;i != p_pcOut->alProperties.end();++i,++a)
-    {
-        if(!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE)))
-        {
-            DefaultLogger::get()->warn("Unable to parse binary property instance. "
-                "Skipping this element instance");
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
 
 
-            (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
-        }
-    }
-    *pCurOut = pCur;
-    return true;
+  if (!p_pcOut->ParseHeader(streamBuffer, buffer, false))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+    return false;
+  }
+
+  //get next line after header
+  streamBuffer.getNextLine(buffer);
+  if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader))
+  {
+    DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+    return false;
+  }
+  DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut,
-    const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
+bool PLY::ElementInstanceList::ParseInstanceList(
+  IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const PLY::Element* pcElement,
+  PLY::ElementInstanceList* p_pcOut,
+  PLYImporter* loader)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != prop );
-    ai_assert( NULL != p_pcOut );
-
-    *pCurOut = pCur;
-
-    // skip spaces at the beginning
-    if (!SkipSpaces(pCur, &pCur)) {
-        return false;
-    }
-
-    if (prop->bIsList)
+  ai_assert(NULL != pcElement);
+  const char* pCur = (const char*)&buffer[0];
+
+  // parse all elements
+  if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
+  {
+    // if the element has an unknown semantic we can skip all lines
+    // However, there could be comments
+    for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
     {
     {
-        // parse the number of elements in the list
-        PLY::PropertyInstance::ValueUnion v;
-        PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v);
-
-        // convert to unsigned int
-        unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
-
-        // parse all list elements
-        p_pcOut->avList.resize(iNum);
-        for (unsigned int i = 0; i < iNum;++i)
+      PLY::DOM::SkipComments(buffer);
+      PLY::DOM::SkipLine(buffer);
+      streamBuffer.getNextLine(buffer);
+      pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0];
+    }
+  }
+  else
+  {
+    // be sure to have enough storage
+    for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
+    {
+      if (p_pcOut)
+        PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]);
+      else
+      {
+        ElementInstance elt;
+        PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt);
+
+        // Create vertex or face
+        if (pcElement->eSemantic == EEST_Vertex)
         {
         {
-            if (!SkipSpaces(pCur, &pCur))return false;
-            PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]);
+          //call loader instance from here
+          loader->LoadVertex(pcElement, &elt, i);
         }
         }
-    }
-    else
-    {
-        // parse the property
-        PLY::PropertyInstance::ValueUnion v;
+        else if (pcElement->eSemantic == EEST_Face)
+        {
+          //call loader instance from here
+          loader->LoadFace(pcElement, &elt, i);
+        }
+        else if (pcElement->eSemantic == EEST_TriStrip)
+        {
+          //call loader instance from here
+          loader->LoadFace(pcElement, &elt, i);
+        }
+      }
 
 
-        PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v);
-        p_pcOut->avList.push_back(v);
+      streamBuffer.getNextLine(buffer);
+      pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0];
     }
     }
-    SkipSpacesAndLineEnd(pCur, &pCur);
-    *pCurOut = pCur;
-    return true;
+  }
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseInstanceBinary (
-    const char*  pCur,
-    const char** pCurOut,
-    const PLY::Property* prop,
-    PLY::PropertyInstance* p_pcOut,
-    bool p_bBE)
+bool PLY::ElementInstanceList::ParseInstanceListBinary(
+  IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  const PLY::Element* pcElement,
+  PLY::ElementInstanceList* p_pcOut,
+  PLYImporter* loader,
+  bool p_bBE /* = false */)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != prop );
-    ai_assert( NULL != p_pcOut );
-
-    if (prop->bIsList)
-    {
-        // parse the number of elements in the list
-        PLY::PropertyInstance::ValueUnion v;
-        PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE);
-
-        // convert to unsigned int
-        unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
-
-        // parse all list elements
-        p_pcOut->avList.resize(iNum);
-        for (unsigned int i = 0; i < iNum;++i){
-            PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE);
-        }
-    }
+  ai_assert(NULL != pcElement);
+
+  // we can add special handling code for unknown element semantics since
+  // we can't skip it as a whole block (we don't know its exact size
+  // due to the fact that lists could be contained in the property list
+  // of the unknown element)
+  for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
+  {
+    if (p_pcOut)
+      PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[i], p_bBE);
     else
     else
     {
     {
-        // parse the property
-        PLY::PropertyInstance::ValueUnion v;
-        PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE);
-        p_pcOut->avList.push_back(v);
-    }
-    *pCurOut = pCur;
-    return true;
+      ElementInstance elt;
+      PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE);
+
+      // Create vertex or face
+      if (pcElement->eSemantic == EEST_Vertex)
+      {
+        //call loader instance from here
+        loader->LoadVertex(pcElement, &elt, i);
+      }
+      else if (pcElement->eSemantic == EEST_Face)
+      {
+        //call loader instance from here
+        loader->LoadFace(pcElement, &elt, i);
+      }
+      else if (pcElement->eSemantic == EEST_TriStrip)
+      {
+        //call loader instance from here
+        loader->LoadFace(pcElement, &elt, i);
+      }
+    }
+  }
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue( PLY::EDataType eType )
+bool PLY::ElementInstance::ParseInstance(const char* &pCur,
+  const PLY::Element* pcElement,
+  PLY::ElementInstance* p_pcOut)
 {
 {
-    PLY::PropertyInstance::ValueUnion out;
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != p_pcOut);
 
 
-    switch (eType)
-    {
-    case EDT_Float:
-        out.fFloat = 0.f;
-        return out;
+  // allocate enough storage
+  p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
 
-    case EDT_Double:
-        out.fDouble = 0.;
-        return out;
+  std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+  std::vector<PLY::Property>::const_iterator  a = pcElement->alProperties.begin();
+  for (; i != p_pcOut->alProperties.end(); ++i, ++a)
+  {
+    if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i))))
+    {
+      DefaultLogger::get()->warn("Unable to parse property instance. "
+        "Skipping this element instance");
 
 
-    default: ;
-    };
-    out.iUInt = 0;
-    return out;
+      PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
+      (*i).avList.push_back(v);
+    }
+  }
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValue(
-    const char* pCur,
-    const char** pCurOut,
-    PLY::EDataType eType,
-    PLY::PropertyInstance::ValueUnion* out)
+bool PLY::ElementInstance::ParseInstanceBinary(
+  IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  const PLY::Element* pcElement,
+  PLY::ElementInstance* p_pcOut,
+  bool p_bBE /* = false */)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != out );
+  ai_assert(NULL != pcElement);
+  ai_assert(NULL != p_pcOut);
+
+  // allocate enough storage
+  p_pcOut->alProperties.resize(pcElement->alProperties.size());
 
 
-    bool ret = true;
-    *pCurOut = pCur;
-    switch (eType)
+  std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+  std::vector<PLY::Property>::const_iterator   a = pcElement->alProperties.begin();
+  for (; i != p_pcOut->alProperties.end(); ++i, ++a)
+  {
+    if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE)))
     {
     {
-    case EDT_UInt:
-    case EDT_UShort:
-    case EDT_UChar:
-
-        out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
-        break;
-
-    case EDT_Int:
-    case EDT_Short:
-    case EDT_Char:
-
-        out->iInt = (int32_t)strtol10(pCur, &pCur);
-        break;
-
-    case EDT_Float:
-        // technically this should cast to float, but people tend to use float descriptors for double data
-        // this is the best way to not risk losing precision on import and it doesn't hurt to do this
-        ai_real f;
-        pCur = fast_atoreal_move<ai_real>(pCur,f);
-        out->fFloat = (ai_real)f;
-        break;
-
-    case EDT_Double:
-        double d;
-        pCur = fast_atoreal_move<double>(pCur,d);
-        out->fDouble = (double)d;
-        break;
-
-    default:
-        ret = false;
-        break;
-    }
-    *pCurOut = pCur;
+      DefaultLogger::get()->warn("Unable to parse binary property instance. "
+        "Skipping this element instance");
 
 
-    return ret;
+      (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
+    }
+  }
+  return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool PLY::PropertyInstance::ParseValueBinary(
-    const char* pCur,
-    const char** pCurOut,
-    PLY::EDataType eType,
-    PLY::PropertyInstance::ValueUnion* out,
-    bool p_bBE)
+bool PLY::PropertyInstance::ParseInstance(const char* &pCur,
+  const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
 {
 {
-    ai_assert( NULL != pCur );
-    ai_assert( NULL != pCurOut );
-    ai_assert( NULL != out );
+  ai_assert(NULL != prop);
+  ai_assert(NULL != p_pcOut);
 
 
-    bool ret = true;
-    switch (eType)
-    {
-    case EDT_UInt:
-        out->iUInt = (uint32_t)*((uint32_t*)pCur);
-        pCur += 4;
+  // skip spaces at the beginning
+  if (!SkipSpaces(&pCur))
+  {
+    return false;
+  }
 
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
-        break;
+  if (prop->bIsList)
+  {
+    // parse the number of elements in the list
+    PLY::PropertyInstance::ValueUnion v;
+    PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v);
 
 
-    case EDT_UShort:
-        {
-        uint16_t i = *((uint16_t*)pCur);
+    // convert to unsigned int
+    unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType);
 
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap(&i);
-        out->iUInt = (uint32_t)i;
-        pCur += 2;
-        break;
-        }
+    // parse all list elements
+    p_pcOut->avList.resize(iNum);
+    for (unsigned int i = 0; i < iNum; ++i)
+    {
+      if (!SkipSpaces(&pCur))
+        return false;
 
 
-    case EDT_UChar:
-        {
-        out->iUInt = (uint32_t)(*((uint8_t*)pCur));
-        pCur ++;
-        break;
-        }
+      PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]);
+    }
+  }
+  else
+  {
+    // parse the property
+    PLY::PropertyInstance::ValueUnion v;
 
 
-    case EDT_Int:
-        out->iInt = *((int32_t*)pCur);
-        pCur += 4;
+    PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v);
+    p_pcOut->avList.push_back(v);
+  }
+  SkipSpacesAndLineEnd(&pCur);
+  return true;
+}
 
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap(&out->iInt);
-        break;
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  const PLY::Property* prop,
+  PLY::PropertyInstance* p_pcOut,
+  bool p_bBE)
+{
+  ai_assert(NULL != prop);
+  ai_assert(NULL != p_pcOut);
+
+  // parse all elements
+  if (prop->bIsList)
+  {
+    // parse the number of elements in the list
+    PLY::PropertyInstance::ValueUnion v;
+    PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eFirstType, &v, p_bBE);
+
+    // convert to unsigned int
+    unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v, prop->eFirstType);
+
+    // parse all list elements
+    p_pcOut->avList.resize(iNum);
+    for (unsigned int i = 0; i < iNum; ++i)
+    {
+      PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE);
+    }
+  }
+  else
+  {
+    // parse the property
+    PLY::PropertyInstance::ValueUnion v;
+    PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE);
+    p_pcOut->avList.push_back(v);
+  }
+  return true;
+}
 
 
-    case EDT_Short:
-        {
-        int16_t i = *((int16_t*)pCur);
+// ------------------------------------------------------------------------------------------------
+PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType)
+{
+  PLY::PropertyInstance::ValueUnion out;
 
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap(&i);
-        out->iInt = (int32_t)i;
-        pCur += 2;
-        break;
-        }
+  switch (eType)
+  {
+  case EDT_Float:
+    out.fFloat = 0.f;
+    return out;
 
 
-    case EDT_Char:
-        out->iInt = (int32_t)*((int8_t*)pCur);
-        pCur ++;
-        break;
+  case EDT_Double:
+    out.fDouble = 0.;
+    return out;
 
 
-    case EDT_Float:
-        {
-        out->fFloat = *((float*)pCur);
+  default:;
+  };
+  out.iUInt = 0;
+  return out;
+}
 
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
-        pCur += 4;
-        break;
-        }
-    case EDT_Double:
-        {
-        out->fDouble = *((double*)pCur);
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseValue(const char* &pCur,
+  PLY::EDataType eType,
+  PLY::PropertyInstance::ValueUnion* out)
+{
+  ai_assert(NULL != pCur);
+  ai_assert(NULL != out);
+  
+  //calc element size
+  unsigned int lsize = 0;
+  switch (eType)
+  {
+  case EDT_Char:
+  case EDT_UChar:
+    lsize = 1;
+    break;
+
+  case EDT_UShort:
+  case EDT_Short:
+    lsize = 2;
+    break;
+
+  case EDT_UInt:
+  case EDT_Int:
+  case EDT_Float:
+    lsize = 4;
+    break;
+
+  case EDT_Double:
+    lsize = 8;
+    break;
+  }
+
+  bool ret = true;
+  switch (eType)
+  {
+  case EDT_UInt:
+  case EDT_UShort:
+  case EDT_UChar:
+
+    out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
+    break;
+
+  case EDT_Int:
+  case EDT_Short:
+  case EDT_Char:
+
+    out->iInt = (int32_t)strtol10(pCur, &pCur);
+    break;
+
+  case EDT_Float:
+    // technically this should cast to float, but people tend to use float descriptors for double data
+    // this is the best way to not risk losing precision on import and it doesn't hurt to do this
+    ai_real f;
+    pCur = fast_atoreal_move<ai_real>(pCur, f);
+    out->fFloat = (ai_real)f;
+    break;
+
+  case EDT_Double:
+    double d;
+    pCur = fast_atoreal_move<double>(pCur, d);
+    out->fDouble = (double)d;
+    break;
+
+  default:
+    ret = false;
+    break;
+  }
+
+  return ret;
+}
 
 
-        // Swap endianness
-        if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
-        pCur += 8;
-        break;
-        }
-    default:
-        ret = false;
+// ------------------------------------------------------------------------------------------------
+bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
+  std::vector<char> &buffer,
+  const char* &pCur,
+  unsigned int &bufferSize,
+  PLY::EDataType eType,
+  PLY::PropertyInstance::ValueUnion* out,
+  bool p_bBE)
+{
+  ai_assert(NULL != out);
+
+  //calc element size
+  unsigned int lsize = 0;
+  switch (eType)
+  {
+  case EDT_Char:
+  case EDT_UChar:
+    lsize = 1;
+    break;
+
+  case EDT_UShort:
+  case EDT_Short:
+    lsize = 2;
+    break;
+
+  case EDT_UInt:
+  case EDT_Int:
+  case EDT_Float:
+    lsize = 4;
+    break;
+
+  case EDT_Double:
+    lsize = 8;
+    break;
+  }
+
+  //read the next file block if needed
+  if (bufferSize < lsize)
+  {
+    std::vector<char> nbuffer;
+    if (streamBuffer.getNextBlock(nbuffer))
+    {
+      //concat buffer contents
+      buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end());
+      buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end());
+      nbuffer.clear();
+      bufferSize = buffer.size();
+      pCur = (char*)&buffer[0];
     }
     }
-    *pCurOut = pCur;
-
-    return ret;
+    else
+    {
+      throw DeadlyImportError("Invalid .ply file: File corrupted");
+    }
+  }
+
+  bool ret = true;
+  switch (eType)
+  {
+  case EDT_UInt:
+    out->iUInt = (uint32_t)*((uint32_t*)pCur);
+    pCur += 4;
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
+    break;
+
+  case EDT_UShort:
+  {
+    uint16_t i = *((uint16_t*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap(&i);
+    out->iUInt = (uint32_t)i;
+    pCur += 2;
+    break;
+  }
+
+  case EDT_UChar:
+  {
+    out->iUInt = (uint32_t)(*((uint8_t*)pCur));
+    pCur++;
+    break;
+  }
+
+  case EDT_Int:
+    out->iInt = *((int32_t*)pCur);
+    pCur += 4;
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap(&out->iInt);
+    break;
+
+  case EDT_Short:
+  {
+    int16_t i = *((int16_t*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap(&i);
+    out->iInt = (int32_t)i;
+    pCur += 2;
+    break;
+  }
+
+  case EDT_Char:
+    out->iInt = (int32_t)*((int8_t*)pCur);
+    pCur++;
+    break;
+
+  case EDT_Float:
+  {
+    out->fFloat = *((float*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
+    pCur += 4;
+    break;
+  }
+  case EDT_Double:
+  {
+    out->fDouble = *((double*)pCur);
+
+    // Swap endianness
+    if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
+    pCur += 8;
+    break;
+  }
+  default:
+    ret = false;
+  }
+
+  bufferSize -= lsize;
+
+  return ret;
 }
 }
 
 
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

+ 39 - 56
code/PlyParser.h

@@ -3,7 +3,6 @@ Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
 Copyright (c) 2006-2017, assimp team
 Copyright (c) 2006-2017, assimp team
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -46,19 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 #include "ParsingUtils.h"
 #include "ParsingUtils.h"
+#include "IOStreamBuffer.h"
 #include <vector>
 #include <vector>
 
 
-
 namespace Assimp
 namespace Assimp
 {
 {
 
 
+//pre-declaration
+class PLYImporter;
+
 // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
 // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
 // http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
 // http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
 // http://www.okino.com/conv/exp_ply.htm
 // http://www.okino.com/conv/exp_ply.htm
 namespace PLY
 namespace PLY
 {
 {
 
 
-
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 /*
 /*
 name        type        number of bytes
 name        type        number of bytes
@@ -197,6 +198,9 @@ enum EElementSemantic
     //! The element is a material description
     //! The element is a material description
     EEST_Material,
     EEST_Material,
 
 
+    //! texture path
+    EEST_TextureFile,
+
     //! Marks invalid entries
     //! Marks invalid entries
     EEST_INVALID
     EEST_INVALID
 };
 };
@@ -238,16 +242,15 @@ public:
     //! string is either '\n', '\r' or '\0'. Return value is false
     //! string is either '\n', '\r' or '\0'. Return value is false
     //! if the input string is NOT a valid property (E.g. does
     //! if the input string is NOT a valid property (E.g. does
     //! not start with the "property" keyword)
     //! not start with the "property" keyword)
-    static bool ParseProperty (const char* pCur, const char** pCurOut,
-        Property* pOut);
+    static bool ParseProperty(std::vector<char> &buffer, Property* pOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a data type from a string
     //! Parse a data type from a string
-    static EDataType ParseDataType(const char* pCur,const char** pCurOut);
+    static EDataType ParseDataType(std::vector<char> &buffer);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a semantic from a string
     //! Parse a semantic from a string
-    static ESemantic ParseSemantic(const char* pCur,const char** pCurOut);
+    static ESemantic ParseSemantic(std::vector<char> &buffer);
 };
 };
 
 
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
@@ -285,13 +288,11 @@ public:
     //! Parse an element from a string.
     //! Parse an element from a string.
     //! The function will parse all properties contained in the
     //! The function will parse all properties contained in the
     //! element, too.
     //! element, too.
-    static bool ParseElement (const char* pCur, const char** pCurOut,
-        Element* pOut);
+    static bool ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, Element* pOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a semantic from a string
     //! Parse a semantic from a string
-    static EElementSemantic ParseSemantic(const char* pCur,
-        const char** pCurOut);
+    static EElementSemantic ParseSemantic(std::vector<char> &buffer);
 };
 };
 
 
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
@@ -331,13 +332,13 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a property instance
     //! Parse a property instance
-    static bool ParseInstance (const char* pCur,const char** pCurOut,
+    static bool ParseInstance(const char* &pCur,
         const Property* prop, PropertyInstance* p_pcOut);
         const Property* prop, PropertyInstance* p_pcOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a property instance in binary format
     //! Parse a property instance in binary format
-    static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
-        const Property* prop, PropertyInstance* p_pcOut,bool p_bBE);
+    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Get the default value for a given data type
     //! Get the default value for a given data type
@@ -345,13 +346,12 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a value
     //! Parse a value
-    static bool ParseValue(const char* pCur,const char** pCurOut,
-        EDataType eType,ValueUnion* out);
+    static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a binary value
     //! Parse a binary value
-    static bool ParseValueBinary(const char* pCur,const char** pCurOut,
-        EDataType eType,ValueUnion* out,bool p_bBE);
+    static bool ParseValueBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Convert a property value to a given type TYPE
     //! Convert a property value to a given type TYPE
@@ -375,13 +375,13 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse an element instance
     //! Parse an element instance
-    static bool ParseInstance (const char* pCur,const char** pCurOut,
+    static bool ParseInstance(const char* &pCur,
         const Element* pcElement, ElementInstance* p_pcOut);
         const Element* pcElement, ElementInstance* p_pcOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a binary element instance
     //! Parse a binary element instance
-    static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
-        const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE);
+    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE);
 };
 };
 
 
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
@@ -400,13 +400,13 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse an element instance list
     //! Parse an element instance list
-    static bool ParseInstanceList (const char* pCur,const char** pCurOut,
-        const Element* pcElement, ElementInstanceList* p_pcOut);
+    static bool ParseInstanceList(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a binary element instance list
     //! Parse a binary element instance list
-    static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut,
-        const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
+    static bool ParseInstanceListBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
+        const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE);
 };
 };
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 /** \brief Class to represent the document object model of an ASCII or binary
 /** \brief Class to represent the document object model of an ASCII or binary
@@ -428,50 +428,33 @@ public:
 
 
     //! Parse the DOM for a PLY file. The input string is assumed
     //! Parse the DOM for a PLY file. The input string is assumed
     //! to be terminated with zero
     //! to be terminated with zero
-    static bool ParseInstance (const char* pCur,DOM* p_pcOut);
-    static bool ParseInstanceBinary (const char* pCur,
-        DOM* p_pcOut,bool p_bBE);
+    static bool ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader);
+    static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE);
 
 
     //! Skip all comment lines after this
     //! Skip all comment lines after this
-    static bool SkipComments (const char* pCur,const char** pCurOut);
+    static bool SkipComments(std::vector<char> &buffer);
+
+    static bool SkipSpaces(std::vector<char> &buffer);
+
+    static bool SkipLine(std::vector<char> &buffer);
+
+    static bool TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len);
+
+    static bool SkipSpacesAndLineEnd(std::vector<char> &buffer);
 
 
 private:
 private:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Handle the file header and read all element descriptions
     //! Handle the file header and read all element descriptions
-    bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE);
+    bool ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool p_bBE);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Read in all element instance lists
     //! Read in all element instance lists
-    bool ParseElementInstanceLists (const char* pCur,const char** pCurOut);
+    bool ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Read in all element instance lists for a binary file format
     //! Read in all element instance lists for a binary file format
-    bool ParseElementInstanceListsBinary (const char* pCur,
-        const char** pCurOut,bool p_bBE);
-};
-
-// ---------------------------------------------------------------------------------
-/** \brief Helper class to represent a loaded PLY face
- */
-class Face
-{
-public:
-
-    Face()
-        : iMaterialIndex(0xFFFFFFFF)
-    {
-        // set all indices to zero by default
-        mIndices.resize(3,0);
-    }
-
-public:
-
-    //! List of vertex indices
-    std::vector<unsigned int> mIndices;
-
-    //! Material index
-    unsigned int iMaterialIndex;
+    bool ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE);
 };
 };
 
 
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------

+ 1 - 1
code/PretransformVertices.cpp

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "PretransformVertices.h"
 #include "PretransformVertices.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Exceptional.h"
 #include "Exceptional.h"
 
 
 using namespace Assimp;
 using namespace Assimp;

+ 22 - 9
code/SIBImporter.cpp

@@ -58,7 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
 #include "StreamReader.h"
 #include "StreamReader.h"
 #include "TinyFormatter.h"
 #include "TinyFormatter.h"
-#include "../contrib/ConvertUTF/ConvertUTF.h"
+//#include "../contrib/ConvertUTF/ConvertUTF.h"
+#include "../contrib/utf8cpp/source/utf8.h"
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
@@ -177,21 +178,33 @@ static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk)
 // Reads a UTF-16LE string and returns it at UTF-8.
 // Reads a UTF-16LE string and returns it at UTF-8.
 static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars)
 static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars)
 {
 {
+    if ( 0 == numWChars ) {
+        static const aiString empty;
+        return empty;
+    }
     // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
     // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
-    UTF16* temp = new UTF16[numWChars];
-    UTF8* str = new UTF8[numWChars * 4 + 1];
+    //UTF16* temp = new UTF16[numWChars];
+    std::vector<unsigned char> str;
+    str.reserve(numWChars * 4 + 1);
+    //unsigned char* str = new unsigned char[numWChars * 4 + 1];
+    uint16_t *temp = new uint16_t[numWChars];
     for (uint32_t n=0;n<numWChars;n++)
     for (uint32_t n=0;n<numWChars;n++)
         temp[n] = stream->GetU2();
         temp[n] = stream->GetU2();
 
 
     // Convert it and NUL-terminate.
     // Convert it and NUL-terminate.
-    const UTF16 *start = temp, *end = temp + numWChars;
-    UTF8 *dest = str, *limit = str + numWChars*4;
-    ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
-    *dest = '\0';
+    //const UTF16 *start = temp, *end = temp + numWChars;
+
+    const uint16_t *start = temp, *end = temp + numWChars;
+    utf8::utf16to8(start, end, back_inserter(str));
+
+    //UTF8 *dest = str, *limit = str + numWChars*4;
+    //ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
+    //*dest = '\0';
 
 
+    str[str.size()-1] = '\0';
     // Return the final string.
     // Return the final string.
-    aiString result = aiString((const char *)str);
-    delete[] str;
+    aiString result = aiString((const char *)&str[0]);
+    //delete[] str;
     delete[] temp;
     delete[] temp;
     return result;
     return result;
 }
 }

+ 25 - 32
code/STEPFileEncoding.cpp

@@ -40,18 +40,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** @file  STEPFileEncoding.cpp
 /** @file  STEPFileEncoding.cpp
- *  @brief STEP character handling, string unescaping
+ *  @brief STEP character handling, string un-escaping
  */
  */
 #include "STEPFileEncoding.h"
 #include "STEPFileEncoding.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
+#include <contrib/utf8cpp/source/utf8.h>
 
 
-#include "../contrib/ConvertUTF/ConvertUTF.h"
 #include <memory>
 #include <memory>
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
 // roman1 to utf16 table
 // roman1 to utf16 table
-static const UTF16 mac_codetable[] = {
+static const uint16_t mac_codetable[] = {
     // 0x20 unassig./nonprint. slots
     // 0x20 unassig./nonprint. slots
      0x0020 ,
      0x0020 ,
      0x0021 ,
      0x0021 ,
@@ -309,14 +309,12 @@ bool STEP::StringToUTF8(std::string& s)
 
 
                 ai_assert(sizeof(mac_codetable) / sizeof(mac_codetable[0]) == 0x100-0x20);
                 ai_assert(sizeof(mac_codetable) / sizeof(mac_codetable[0]) == 0x100-0x20);
 
 
-                const UTF32 unival = mac_codetable[macval - 0x20], *univalp = &unival;
+                const uint32_t unival = mac_codetable[macval - 0x20], *univalp = &unival;
 
 
-                UTF8 temp[5], *tempp = temp;
-                ai_assert(sizeof(UTF8) == 1);
+                unsigned char temp[5], *tempp = temp;
+                ai_assert(sizeof( unsigned char ) == 1);
 
 
-                if(ConvertUTF32toUTF8(&univalp, univalp+1, &tempp, tempp+sizeof(temp), lenientConversion) != conversionOK) {
-                    return false;
-                }
+                utf8::utf32to8( univalp, univalp + 1, tempp );
 
 
                 const size_t outcount = static_cast<size_t>(tempp-temp);
                 const size_t outcount = static_cast<size_t>(tempp-temp);
 
 
@@ -355,28 +353,26 @@ bool STEP::StringToUTF8(std::string& s)
                             }
                             }
 
 
                             const size_t count = (j-basei)/4;
                             const size_t count = (j-basei)/4;
-                            std::unique_ptr<UTF16[]> src(new UTF16[count]);
+                            std::unique_ptr<uint16_t[]> src(new uint16_t[count]);
 
 
                             const char* cur = s.c_str() + basei;
                             const char* cur = s.c_str() + basei;
                             for (size_t k = 0; k < count; ++k, cur += 4) {
                             for (size_t k = 0; k < count; ++k, cur += 4) {
-                                src[k] = (static_cast<UTF16>(HexOctetToDecimal(cur)) << 8u)  |
-                                     static_cast<UTF16>(HexOctetToDecimal(cur+2));
+                                src[k] = (static_cast<uint16_t>(HexOctetToDecimal(cur)) << 8u)  |
+                                     static_cast<uint16_t>(HexOctetToDecimal(cur+2));
                             }
                             }
 
 
                             const size_t dcount = count * 3; // this is enough to hold all possible outputs
                             const size_t dcount = count * 3; // this is enough to hold all possible outputs
-                            std::unique_ptr<UTF8[]> dest(new UTF8[dcount]);
+                            std::unique_ptr<unsigned char[]> dest(new unsigned char[dcount]);
 
 
-                            const UTF16* srct = src.get();
-                            UTF8* destt = dest.get();
-                            if(ConvertUTF16toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
-                                return false;
-                            }
+                            const uint16_t* srct = src.get();
+                            unsigned char* destt = dest.get();
+                            utf8::utf16to8( srct, srct + count, destt );
 
 
                             const size_t outcount = static_cast<size_t>(destt-dest.get());
                             const size_t outcount = static_cast<size_t>(destt-dest.get());
 
 
                             s.erase(i,(j+4-i));
                             s.erase(i,(j+4-i));
 
 
-                            ai_assert(sizeof(UTF8) == 1);
+                            ai_assert(sizeof(unsigned char) == 1);
                             s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
                             s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
 
 
                             i += outcount;
                             i += outcount;
@@ -388,37 +384,34 @@ bool STEP::StringToUTF8(std::string& s)
                             }
                             }
 
 
                             const size_t count = (j-basei)/8;
                             const size_t count = (j-basei)/8;
-                            std::unique_ptr<UTF32[]> src(new UTF32[count]);
+                            std::unique_ptr<uint32_t[]> src(new uint32_t[count]);
 
 
                             const char* cur = s.c_str() + basei;
                             const char* cur = s.c_str() + basei;
                             for (size_t k = 0; k < count; ++k, cur += 8) {
                             for (size_t k = 0; k < count; ++k, cur += 8) {
-                                src[k] = (static_cast<UTF32>(HexOctetToDecimal(cur  )) << 24u) |
-                                         (static_cast<UTF32>(HexOctetToDecimal(cur+2)) << 16u) |
-                                         (static_cast<UTF32>(HexOctetToDecimal(cur+4)) << 8u)  |
-                                         (static_cast<UTF32>(HexOctetToDecimal(cur+6)));
+                                src[k] = (static_cast<uint32_t>(HexOctetToDecimal(cur  )) << 24u) |
+                                         (static_cast<uint32_t>(HexOctetToDecimal(cur+2)) << 16u) |
+                                         (static_cast<uint32_t>(HexOctetToDecimal(cur+4)) << 8u)  |
+                                         (static_cast<uint32_t>(HexOctetToDecimal(cur+6)));
                             }
                             }
 
 
                             const size_t dcount = count * 5; // this is enough to hold all possible outputs
                             const size_t dcount = count * 5; // this is enough to hold all possible outputs
-                            std::unique_ptr<UTF8[]> dest(new UTF8[dcount]);
+                            std::unique_ptr<unsigned char[]> dest(new unsigned char[dcount]);
 
 
-                            const UTF32* srct = src.get();
-                            UTF8* destt = dest.get();
-                            if(ConvertUTF32toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
-                                return false;
-                            }
+                            const uint32_t* srct = src.get();
+                            unsigned char* destt = dest.get();
+                            utf8::utf32to8( srct, srct + count, destt );
 
 
                             const size_t outcount = static_cast<size_t>(destt-dest.get());
                             const size_t outcount = static_cast<size_t>(destt-dest.get());
 
 
                             s.erase(i,(j+4-i));
                             s.erase(i,(j+4-i));
 
 
-                            ai_assert(sizeof(UTF8) == 1);
+                            ai_assert(sizeof(unsigned char) == 1);
                             s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
                             s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
 
 
                             i += outcount;
                             i += outcount;
                             continue;
                             continue;
                         }
                         }
                     }
                     }
-
                     break;
                     break;
 
 
                     // TODO: other encoding patterns?
                     // TODO: other encoding patterns?

+ 3 - 3
code/STLLoader.cpp

@@ -211,20 +211,20 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
     for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
         pScene->mRootNode->mMeshes[i] = i;
         pScene->mRootNode->mMeshes[i] = i;
 
 
-    // create a single default material, using a light gray diffuse color for consistency with
+    // create a single default material, using a white diffuse color for consistency with
     // other geometric types (e.g., PLY).
     // other geometric types (e.g., PLY).
     aiMaterial* pcMat = new aiMaterial();
     aiMaterial* pcMat = new aiMaterial();
     aiString s;
     aiString s;
     s.Set(AI_DEFAULT_MATERIAL_NAME);
     s.Set(AI_DEFAULT_MATERIAL_NAME);
     pcMat->AddProperty(&s, AI_MATKEY_NAME);
     pcMat->AddProperty(&s, AI_MATKEY_NAME);
 
 
-    aiColor4D clrDiffuse(ai_real(0.6),ai_real(0.6),ai_real(0.6),ai_real(1.0));
+    aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0));
     if (bMatClr) {
     if (bMatClr) {
         clrDiffuse = clrColorDefault;
         clrDiffuse = clrColorDefault;
     }
     }
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
-    clrDiffuse = aiColor4D( ai_real( 0.05), ai_real( 0.05), ai_real( 0.05), ai_real( 1.0));
+    clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0));
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
     pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
 
 
     pScene->mNumMaterials = 1;
     pScene->mNumMaterials = 1;

+ 1 - 1
code/SceneCombiner.cpp

@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *       OptimizeGraph step.
   *       OptimizeGraph step.
   */
   */
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StringUtils.h"
 #include "StringUtils.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
 #include "Hash.h"
 #include "Hash.h"

+ 2 - 3
code/SpatialSort.cpp

@@ -126,9 +126,8 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
     const ai_real dist = pPosition * mPlaneNormal;
     const ai_real dist = pPosition * mPlaneNormal;
     const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
     const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
 
 
-    // clear the array in this strange fashion because a simple clear() would also deallocate
-    // the array which we want to avoid
-    poResults.erase( poResults.begin(), poResults.end());
+    // clear the array
+    poResults.clear();
 
 
     // quick check for positions outside the range
     // quick check for positions outside the range
     if( mPositions.size() == 0)
     if( mPositions.size() == 0)

+ 2 - 1
code/StepExporter.cpp

@@ -43,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
 #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+
 #include "StepExporter.h"
 #include "StepExporter.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include <iostream>
 #include <iostream>
 #include <ctime>
 #include <ctime>
 #include <set>
 #include <set>

+ 1 - 1
code/Subdivision.cpp

@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "Subdivision.h"
 #include "Subdivision.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "SpatialSort.h"
 #include "SpatialSort.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
 #include "Vertex.h"
 #include "Vertex.h"

+ 2 - 1
code/XFileExporter.cpp

@@ -43,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_X_EXPORTER
 #ifndef ASSIMP_BUILD_NO_X_EXPORTER
+
 #include "XFileExporter.h"
 #include "XFileExporter.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 #include "fast_atof.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>
 #include <ctime>
 #include <ctime>
 #include <set>
 #include <set>

+ 10 - 3
code/fast_atof.h

@@ -1,3 +1,5 @@
+#pragma once
+
 // Copyright (C) 2002-2007 Nikolaus Gebhardt
 // Copyright (C) 2002-2007 Nikolaus Gebhardt
 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
@@ -22,6 +24,7 @@
 #include <assimp/defs.h>
 #include <assimp/defs.h>
 
 
 #include "StringComparison.h"
 #include "StringComparison.h"
+#include <assimp/DefaultLogger.hpp>
 
 
 
 
 #ifdef _MSC_VER
 #ifdef _MSC_VER
@@ -192,7 +195,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
     uint64_t value = 0;
     uint64_t value = 0;
 
 
     if ( *in < '0' || *in > '9' )
     if ( *in < '0' || *in > '9' )
-            throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
+        throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
 
 
     bool running = true;
     bool running = true;
     while ( running )
     while ( running )
@@ -202,8 +205,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
 
 
         const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
         const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
 
 
-        if (new_value < value) /* numeric overflow, we rely on you */
-            throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow.");
+        // numeric overflow, we rely on you
+        if ( new_value < value ) {
+            DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." );
+            return 0;
+        }
+            //throw std::overflow_error();
 
 
         value = new_value;
         value = new_value;
 
 

+ 5 - 2
code/glTFExporter.cpp

@@ -48,8 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ByteSwapper.h"
 #include "ByteSwapper.h"
 
 
 #include "SplitLargeMeshes.h"
 #include "SplitLargeMeshes.h"
-#include "SceneCombiner.h"
 
 
+#include <assimp/SceneCombiner.h>
 #include <assimp/version.h>
 #include <assimp/version.h>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
@@ -185,8 +185,11 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     unsigned int bytesPerComp = ComponentTypeSize(compType);
     unsigned int bytesPerComp = ComponentTypeSize(compType);
 
 
     size_t offset = buffer->byteLength;
     size_t offset = buffer->byteLength;
+    // make sure offset is correctly byte-aligned, as required by spec
+    size_t padding = offset % bytesPerComp;
+    offset += padding;
     size_t length = count * numCompsOut * bytesPerComp;
     size_t length = count * numCompsOut * bytesPerComp;
-    buffer->Grow(length);
+    buffer->Grow(length + padding);
 
 
     // bufferView
     // bufferView
     Ref<BufferView> bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view"));
     Ref<BufferView> bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view"));

+ 0 - 539
contrib/ConvertUTF/ConvertUTF.c

@@ -1,539 +0,0 @@
-/*
- * Copyright 2001-2004 Unicode, Inc.
- * 
- * Disclaimer
- * 
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- * 
- * Limitations on Rights to Redistribute This Code
- * 
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
-
-/* ---------------------------------------------------------------------
-
-    Conversions between UTF32, UTF-16, and UTF-8. Source code file.
-    Author: Mark E. Davis, 1994.
-    Rev History: Rick McGowan, fixes & updates May 2001.
-    Sept 2001: fixed const & error conditions per
-	mods suggested by S. Parent & A. Lillich.
-    June 2002: Tim Dodd added detection and handling of incomplete
-	source sequences, enhanced error detection, added casts
-	to eliminate compiler warnings.
-    July 2003: slight mods to back out aggressive FFFE detection.
-    Jan 2004: updated switches in from-UTF8 conversions.
-    Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
-
-    See the header file "ConvertUTF.h" for complete documentation.
-
------------------------------------------------------------------------- */
-
-
-#include "ConvertUTF.h"
-#ifdef CVTUTF_DEBUG
-#include <stdio.h>
-#endif
-
-static const int halfShift  = 10; /* used for shifting by 10 bits */
-
-static const UTF32 halfBase = 0x0010000UL;
-static const UTF32 halfMask = 0x3FFUL;
-
-#define UNI_SUR_HIGH_START  (UTF32)0xD800
-#define UNI_SUR_HIGH_END    (UTF32)0xDBFF
-#define UNI_SUR_LOW_START   (UTF32)0xDC00
-#define UNI_SUR_LOW_END     (UTF32)0xDFFF
-#define false	   0
-#define true	    1
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF16 (
-	const UTF32** sourceStart, const UTF32* sourceEnd, 
-	UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
-    ConversionResult result = conversionOK;
-    const UTF32* source = *sourceStart;
-    UTF16* target = *targetStart;
-    while (source < sourceEnd) {
-	UTF32 ch;
-	if (target >= targetEnd) {
-	    result = targetExhausted; break;
-	}
-	ch = *source++;
-	if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
-	    /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
-	    if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
-		if (flags == strictConversion) {
-		    --source; /* return to the illegal value itself */
-		    result = sourceIllegal;
-		    break;
-		} else {
-		    *target++ = UNI_REPLACEMENT_CHAR;
-		}
-	    } else {
-		*target++ = (UTF16)ch; /* normal case */
-	    }
-	} else if (ch > UNI_MAX_LEGAL_UTF32) {
-	    if (flags == strictConversion) {
-		result = sourceIllegal;
-	    } else {
-		*target++ = UNI_REPLACEMENT_CHAR;
-	    }
-	} else {
-	    /* target is a character in range 0xFFFF - 0x10FFFF. */
-	    if (target + 1 >= targetEnd) {
-		--source; /* Back up source pointer! */
-		result = targetExhausted; break;
-	    }
-	    ch -= halfBase;
-	    *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
-	    *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
-	}
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF32 (
-	const UTF16** sourceStart, const UTF16* sourceEnd, 
-	UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
-    ConversionResult result = conversionOK;
-    const UTF16* source = *sourceStart;
-    UTF32* target = *targetStart;
-    UTF32 ch, ch2;
-    while (source < sourceEnd) {
-	const UTF16* oldSource = source; /*  In case we have to back up because of target overflow. */
-	ch = *source++;
-	/* If we have a surrogate pair, convert to UTF32 first. */
-	if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
-	    /* If the 16 bits following the high surrogate are in the source buffer... */
-	    if (source < sourceEnd) {
-		ch2 = *source;
-		/* If it's a low surrogate, convert to UTF32. */
-		if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
-		    ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
-			+ (ch2 - UNI_SUR_LOW_START) + halfBase;
-		    ++source;
-		} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
-		    --source; /* return to the illegal value itself */
-		    result = sourceIllegal;
-		    break;
-		}
-	    } else { /* We don't have the 16 bits following the high surrogate. */
-		--source; /* return to the high surrogate */
-		result = sourceExhausted;
-		break;
-	    }
-	} else if (flags == strictConversion) {
-	    /* UTF-16 surrogate values are illegal in UTF-32 */
-	    if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
-		--source; /* return to the illegal value itself */
-		result = sourceIllegal;
-		break;
-	    }
-	}
-	if (target >= targetEnd) {
-	    source = oldSource; /* Back up source pointer! */
-	    result = targetExhausted; break;
-	}
-	*target++ = ch;
-    }
-    *sourceStart = source;
-    *targetStart = target;
-#ifdef CVTUTF_DEBUG
-if (result == sourceIllegal) {
-    fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
-    fflush(stderr);
-}
-#endif
-    return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Index into the table below with the first byte of a UTF-8 sequence to
- * get the number of trailing bytes that are supposed to follow it.
- * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
- * left as-is for anyone who may want to do such conversion, which was
- * allowed in earlier algorithms.
- */
-static const char trailingBytesForUTF8[256] = {
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-
-/*
- * Magic values subtracted from a buffer value during UTF8 conversion.
- * This table contains as many values as there might be trailing bytes
- * in a UTF-8 sequence.
- */
-static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 
-		     0x03C82080UL, 0xFA082080UL, 0x82082080UL };
-
-/*
- * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
- * into the first byte, depending on how many bytes follow.  There are
- * as many entries in this table as there are UTF-8 sequence types.
- * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
- * for *legal* UTF-8 will be 4 or fewer bytes total.
- */
-static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-/* --------------------------------------------------------------------- */
-
-/* The interface converts a whole buffer to avoid function-call overhead.
- * Constants have been gathered. Loops & conditionals have been removed as
- * much as possible for efficiency, in favor of drop-through switches.
- * (See "Note A" at the bottom of the file for equivalent code.)
- * If your compiler supports it, the "isLegalUTF8" call can be turned
- * into an inline function.
- */
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF8 (
-	const UTF16** sourceStart, const UTF16* sourceEnd, 
-	UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
-    ConversionResult result = conversionOK;
-    const UTF16* source = *sourceStart;
-    UTF8* target = *targetStart;
-    while (source < sourceEnd) {
-	UTF32 ch;
-	unsigned short bytesToWrite = 0;
-	const UTF32 byteMask = 0xBF;
-	const UTF32 byteMark = 0x80; 
-	const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
-	ch = *source++;
-	/* If we have a surrogate pair, convert to UTF32 first. */
-	if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
-	    /* If the 16 bits following the high surrogate are in the source buffer... */
-	    if (source < sourceEnd) {
-		UTF32 ch2 = *source;
-		/* If it's a low surrogate, convert to UTF32. */
-		if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
-		    ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
-			+ (ch2 - UNI_SUR_LOW_START) + halfBase;
-		    ++source;
-		} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
-		    --source; /* return to the illegal value itself */
-		    result = sourceIllegal;
-		    break;
-		}
-	    } else { /* We don't have the 16 bits following the high surrogate. */
-		--source; /* return to the high surrogate */
-		result = sourceExhausted;
-		break;
-	    }
-	} else if (flags == strictConversion) {
-	    /* UTF-16 surrogate values are illegal in UTF-32 */
-	    if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
-		--source; /* return to the illegal value itself */
-		result = sourceIllegal;
-		break;
-	    }
-	}
-	/* Figure out how many bytes the result will require */
-	if (ch < (UTF32)0x80) {	     bytesToWrite = 1;
-	} else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
-	} else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
-	} else if (ch < (UTF32)0x110000) {  bytesToWrite = 4;
-	} else {			    bytesToWrite = 3;
-					    ch = UNI_REPLACEMENT_CHAR;
-	}
-
-	target += bytesToWrite;
-	if (target > targetEnd) {
-	    source = oldSource; /* Back up source pointer! */
-	    target -= bytesToWrite; result = targetExhausted; break;
-	}
-	switch (bytesToWrite) { /* note: everything falls through. */
-	    case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
-	    case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
-	    case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
-	    case 1: *--target =  (UTF8)(ch | firstByteMark[bytesToWrite]);
-	}
-	target += bytesToWrite;
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Utility routine to tell whether a sequence of bytes is legal UTF-8.
- * This must be called with the length pre-determined by the first byte.
- * If not calling this from ConvertUTF8to*, then the length can be set by:
- *  length = trailingBytesForUTF8[*source]+1;
- * and the sequence is illegal right away if there aren't that many bytes
- * available.
- * If presented with a length > 4, this returns false.  The Unicode
- * definition of UTF-8 goes up to 4-byte sequences.
- */
-
-static Boolean isLegalUTF8(const UTF8 *source, int length) {
-    UTF8 a;
-    const UTF8 *srcptr = source+length;
-    switch (length) {
-    default: return false;
-	/* Everything else falls through when "true"... */
-    case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-    case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-    case 2: if ((a = (*--srcptr)) > 0xBF) return false;
-
-	switch (*source) {
-	    /* no fall-through in this inner switch */
-	    case 0xE0: if (a < 0xA0) return false; break;
-	    case 0xED: if (a > 0x9F) return false; break;
-	    case 0xF0: if (a < 0x90) return false; break;
-	    case 0xF4: if (a > 0x8F) return false; break;
-	    default:   if (a < 0x80) return false;
-	}
-
-    case 1: if (*source >= 0x80 && *source < 0xC2) return false;
-    }
-    if (*source > 0xF4) return false;
-    return true;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return whether a UTF-8 sequence is legal or not.
- * This is not used here; it's just exported.
- */
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
-    int length = trailingBytesForUTF8[*source]+1;
-    if (source+length > sourceEnd) {
-	return false;
-    }
-    return isLegalUTF8(source, length);
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF16 (
-	const UTF8** sourceStart, const UTF8* sourceEnd, 
-	UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
-    ConversionResult result = conversionOK;
-    const UTF8* source = *sourceStart;
-    UTF16* target = *targetStart;
-    while (source < sourceEnd) {
-	UTF32 ch = 0;
-	unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
-	if (source + extraBytesToRead >= sourceEnd) {
-	    result = sourceExhausted; break;
-	}
-	/* Do this check whether lenient or strict */
-	if (! isLegalUTF8(source, extraBytesToRead+1)) {
-	    result = sourceIllegal;
-	    break;
-	}
-	/*
-	 * The cases all fall through. See "Note A" below.
-	 */
-	switch (extraBytesToRead) {
-	    case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
-	    case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
-	    case 3: ch += *source++; ch <<= 6;
-	    case 2: ch += *source++; ch <<= 6;
-	    case 1: ch += *source++; ch <<= 6;
-	    case 0: ch += *source++;
-	}
-	ch -= offsetsFromUTF8[extraBytesToRead];
-
-	if (target >= targetEnd) {
-	    source -= (extraBytesToRead+1); /* Back up source pointer! */
-	    result = targetExhausted; break;
-	}
-	if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
-	    /* UTF-16 surrogate values are illegal in UTF-32 */
-	    if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
-		if (flags == strictConversion) {
-		    source -= (extraBytesToRead+1); /* return to the illegal value itself */
-		    result = sourceIllegal;
-		    break;
-		} else {
-		    *target++ = UNI_REPLACEMENT_CHAR;
-		}
-	    } else {
-		*target++ = (UTF16)ch; /* normal case */
-	    }
-	} else if (ch > UNI_MAX_UTF16) {
-	    if (flags == strictConversion) {
-		result = sourceIllegal;
-		source -= (extraBytesToRead+1); /* return to the start */
-		break; /* Bail out; shouldn't continue */
-	    } else {
-		*target++ = UNI_REPLACEMENT_CHAR;
-	    }
-	} else {
-	    /* target is a character in range 0xFFFF - 0x10FFFF. */
-	    if (target + 1 >= targetEnd) {
-		source -= (extraBytesToRead+1); /* Back up source pointer! */
-		result = targetExhausted; break;
-	    }
-	    ch -= halfBase;
-	    *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
-	    *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
-	}
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF8 (
-	const UTF32** sourceStart, const UTF32* sourceEnd, 
-	UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
-    ConversionResult result = conversionOK;
-    const UTF32* source = *sourceStart;
-    UTF8* target = *targetStart;
-    while (source < sourceEnd) {
-	UTF32 ch;
-	unsigned short bytesToWrite = 0;
-	const UTF32 byteMask = 0xBF;
-	const UTF32 byteMark = 0x80; 
-	ch = *source++;
-	if (flags == strictConversion ) {
-	    /* UTF-16 surrogate values are illegal in UTF-32 */
-	    if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
-		--source; /* return to the illegal value itself */
-		result = sourceIllegal;
-		break;
-	    }
-	}
-	/*
-	 * Figure out how many bytes the result will require. Turn any
-	 * illegally large UTF32 things (> Plane 17) into replacement chars.
-	 */
-	if (ch < (UTF32)0x80) {	     bytesToWrite = 1;
-	} else if (ch < (UTF32)0x800) {     bytesToWrite = 2;
-	} else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;
-	} else if (ch <= UNI_MAX_LEGAL_UTF32) {  bytesToWrite = 4;
-	} else {			    bytesToWrite = 3;
-					    ch = UNI_REPLACEMENT_CHAR;
-					    result = sourceIllegal;
-	}
-	
-	target += bytesToWrite;
-	if (target > targetEnd) {
-	    --source; /* Back up source pointer! */
-	    target -= bytesToWrite; result = targetExhausted; break;
-	}
-	switch (bytesToWrite) { /* note: everything falls through. */
-	    case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
-	    case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
-	    case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
-	    case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
-	}
-	target += bytesToWrite;
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF32 (
-	const UTF8** sourceStart, const UTF8* sourceEnd, 
-	UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
-    ConversionResult result = conversionOK;
-    const UTF8* source = *sourceStart;
-    UTF32* target = *targetStart;
-    while (source < sourceEnd) {
-	UTF32 ch = 0;
-	unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
-	if (source + extraBytesToRead >= sourceEnd) {
-	    result = sourceExhausted; break;
-	}
-	/* Do this check whether lenient or strict */
-	if (! isLegalUTF8(source, extraBytesToRead+1)) {
-	    result = sourceIllegal;
-	    break;
-	}
-	/*
-	 * The cases all fall through. See "Note A" below.
-	 */
-	switch (extraBytesToRead) {
-	    case 5: ch += *source++; ch <<= 6;
-	    case 4: ch += *source++; ch <<= 6;
-	    case 3: ch += *source++; ch <<= 6;
-	    case 2: ch += *source++; ch <<= 6;
-	    case 1: ch += *source++; ch <<= 6;
-	    case 0: ch += *source++;
-	}
-	ch -= offsetsFromUTF8[extraBytesToRead];
-
-	if (target >= targetEnd) {
-	    source -= (extraBytesToRead+1); /* Back up the source pointer! */
-	    result = targetExhausted; break;
-	}
-	if (ch <= UNI_MAX_LEGAL_UTF32) {
-	    /*
-	     * UTF-16 surrogate values are illegal in UTF-32, and anything
-	     * over Plane 17 (> 0x10FFFF) is illegal.
-	     */
-	    if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
-		if (flags == strictConversion) {
-		    source -= (extraBytesToRead+1); /* return to the illegal value itself */
-		    result = sourceIllegal;
-		    break;
-		} else {
-		    *target++ = UNI_REPLACEMENT_CHAR;
-		}
-	    } else {
-		*target++ = ch;
-	    }
-	} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
-	    result = sourceIllegal;
-	    *target++ = UNI_REPLACEMENT_CHAR;
-	}
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
-/* ---------------------------------------------------------------------
-
-    Note A.
-    The fall-through switches in UTF-8 reading code save a
-    temp variable, some decrements & conditionals.  The switches
-    are equivalent to the following loop:
-	{
-	    int tmpBytesToRead = extraBytesToRead+1;
-	    do {
-		ch += *source++;
-		--tmpBytesToRead;
-		if (tmpBytesToRead) ch <<= 6;
-	    } while (tmpBytesToRead > 0);
-	}
-    In UTF-8 writing code, the switches on "bytesToWrite" are
-    similarly unrolled loops.
-
-   --------------------------------------------------------------------- */

+ 0 - 151
contrib/ConvertUTF/ConvertUTF.h

@@ -1,151 +0,0 @@
-/*
- * Copyright 2001-2004 Unicode, Inc.
- * 
- * Disclaimer
- * 
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
- * 
- * Limitations on Rights to Redistribute This Code
- * 
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
- */
-#ifndef CONVERTUTF_H
-#define CONVERTUTF_H
-/* ---------------------------------------------------------------------
-
-    Conversions between UTF32, UTF-16, and UTF-8.  Header file.
-
-    Several funtions are included here, forming a complete set of
-    conversions between the three formats.  UTF-7 is not included
-    here, but is handled in a separate source file.
-
-    Each of these routines takes pointers to input buffers and output
-    buffers.  The input buffers are const.
-
-    Each routine converts the text between *sourceStart and sourceEnd,
-    putting the result into the buffer between *targetStart and
-    targetEnd. Note: the end pointers are *after* the last item: e.g. 
-    *(sourceEnd - 1) is the last item.
-
-    The return result indicates whether the conversion was successful,
-    and if not, whether the problem was in the source or target buffers.
-    (Only the first encountered problem is indicated.)
-
-    After the conversion, *sourceStart and *targetStart are both
-    updated to point to the end of last text successfully converted in
-    the respective buffers.
-
-    Input parameters:
-	sourceStart - pointer to a pointer to the source buffer.
-		The contents of this are modified on return so that
-		it points at the next thing to be converted.
-	targetStart - similarly, pointer to pointer to the target buffer.
-	sourceEnd, targetEnd - respectively pointers to the ends of the
-		two buffers, for overflow checking only.
-
-    These conversion functions take a ConversionFlags argument. When this
-    flag is set to strict, both irregular sequences and isolated surrogates
-    will cause an error.  When the flag is set to lenient, both irregular
-    sequences and isolated surrogates are converted.
-
-    Whether the flag is strict or lenient, all illegal sequences will cause
-    an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
-    or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
-    must check for illegal sequences.
-
-    When the flag is set to lenient, characters over 0x10FFFF are converted
-    to the replacement character; otherwise (when the flag is set to strict)
-    they constitute an error.
-
-    Output parameters:
-	The value "sourceIllegal" is returned from some routines if the input
-	sequence is malformed.  When "sourceIllegal" is returned, the source
-	value will point to the illegal value that caused the problem. E.g.,
-	in UTF-8 when a sequence is malformed, it points to the start of the
-	malformed sequence.  
-
-    Author: Mark E. Davis, 1994.
-    Rev History: Rick McGowan, fixes & updates May 2001.
-		 Fixes & updates, Sept 2001.
-
------------------------------------------------------------------------- */
-
-/* ---------------------------------------------------------------------
-    The following 4 definitions are compiler-specific.
-    The C standard does not guarantee that wchar_t has at least
-    16 bits, so wchar_t is no less portable than unsigned short!
-    All should be unsigned values to avoid sign extension during
-    bit mask & shift operations.
------------------------------------------------------------------------- */
-
-typedef unsigned long	UTF32;	/* at least 32 bits */
-typedef unsigned short	UTF16;	/* at least 16 bits */
-typedef unsigned char	UTF8;	/* typically 8 bits */
-typedef unsigned char	Boolean; /* 0 or 1 */
-
-/* Some fundamental constants */
-#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
-#define UNI_MAX_BMP (UTF32)0x0000FFFF
-#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
-#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
-#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
-
-typedef enum {
-	conversionOK, 		/* conversion successful */
-	sourceExhausted,	/* partial character in source, but hit end */
-	targetExhausted,	/* insuff. room in target for conversion */
-	sourceIllegal		/* source sequence is illegal/malformed */
-} ConversionResult;
-
-typedef enum {
-	strictConversion = 0,
-	lenientConversion
-} ConversionFlags;
-
-/* This is for C++ and does no harm in C */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-ConversionResult ConvertUTF8toUTF16 (
-		const UTF8** sourceStart, const UTF8* sourceEnd, 
-		UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF16toUTF8 (
-		const UTF16** sourceStart, const UTF16* sourceEnd, 
-		UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-		
-ConversionResult ConvertUTF8toUTF32 (
-		const UTF8** sourceStart, const UTF8* sourceEnd, 
-		UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF32toUTF8 (
-		const UTF32** sourceStart, const UTF32* sourceEnd, 
-		UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-		
-ConversionResult ConvertUTF16toUTF32 (
-		const UTF16** sourceStart, const UTF16* sourceEnd, 
-		UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF32toUTF16 (
-		const UTF32** sourceStart, const UTF32* sourceEnd, 
-		UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
-
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-#endif  // CONVERTUTF_H

+ 0 - 43
contrib/ConvertUTF/readme.txt

@@ -1,43 +0,0 @@
-
-The accompanying C source code file "ConvertUTF.c" and the associated header
-file "ConvertUTF.h" provide for conversion between various transformation
-formats of Unicode characters.  The following conversions are supported:
-
-	UTF-32 to UTF-16
-	UTF-32 to UTF-8
-	UTF-16 to UTF-32
-	UTF-16 to UTF-8
-	UTF-8 to UTF-16
-	UTF-8 to UTF-32
-
-In addition, there is a test harness which runs various tests.
-
-The files "CVTUTF7.C" and "CVTUTF7.H" are for archival and historical purposes
-only. They have not been updated to Unicode 3.0 or later and should be
-considered obsolescent. "CVTUTF7.C" contains two functions that can convert
-between UCS2 (i.e., the BMP characters only) and UTF-7. Surrogates are
-not supported, the code has not been tested, and should be considered
-unsuitable for general purpose use.
-
-Please submit any bug reports about these programs here:
-
-	http://www.unicode.org/unicode/reporting.html
-
-Version 1.0: initial version.
-
-Version 1.1: corrected some minor problems; added stricter checks.
-
-Version 1.2: corrected switch statements associated with "extraBytesToRead"
-	in 4 & 5 byte cases, in functions for conversion from UTF8.
-	Note: formally, the 4 & 5 byte cases are illegal in the latest
-	UTF8, but the table and this code has always catered for those,
-	cases since at one time they were legal.
-
-Version 1.3: Updated UTF-8 legality check;
-	updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions
-	Updated UTF-8 legality tests in harness.c
- 
-
-Last update: October 19, 2004
-
-

+ 114 - 8
contrib/openddlparser/CMakeLists.txt

@@ -3,18 +3,40 @@ PROJECT( OpenDDL-Parser )
 SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
 SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
 SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
 SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
 SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
 SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
-SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
+SET ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} )
 SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
 SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
 
 
+option( DDL_USE_CPP11           "Set to ON to use C++11 features ( always on on windows )."                   ON )
+option( DDL_DEBUG_OUTPUT        "Set to ON to use output debug texts"                                         OFF )
+option( DDL_STATIC_LIBRARY		"Set to ON to build static libary of OpenDDL Parser."                         ON )
+option( COVERALLS               "Generate coveralls data"                                                     OFF )
+
+if ( DDL_USE_CPP11 )
+    if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+        set( OPENDDL_CXXFLAGS -std=c++0x )
+    elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+        set( OPENDDL_CXXFLAGS --std=c++11 )
+    endif()
+else( DDL_USE_CPP11 )
+    add_definitions( -DOPENDDL_NO_USE_CPP11 )
+endif( DDL_USE_CPP11)
+
 if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
 if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
     find_package(Threads)
     find_package(Threads)
 else()
 else()
     add_definitions( -D_CRT_SECURE_NO_WARNINGS )
     add_definitions( -D_CRT_SECURE_NO_WARNINGS )
 endif()
 endif()
 
 
+if ( DDL_STATIC_LIBRARY )
+	add_definitions( -DOPENDDL_STATIC_LIBARY )
+endif()
+
 add_definitions( -DOPENDDLPARSER_BUILD )
 add_definitions( -DOPENDDLPARSER_BUILD )
-add_definitions( -DOPENDDL_NO_USE_CPP11 )
 add_definitions( -D_VARIADIC_MAX=10 )
 add_definitions( -D_VARIADIC_MAX=10 )
+add_definitions( -DGTEST_HAS_PTHREAD=0 )
+if ( DDL_DEBUG_OUTPUT )
+    add_definitions( -DDDL_DEBUG_HEADER_NAME)
+endif()
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
     ./
     ./
@@ -24,9 +46,10 @@ INCLUDE_DIRECTORIES(
 )
 )
 
 
 link_directories(
 link_directories(
-    ./
+    ${CMAKE_HOME_DIRECTORY}/lib
 )
 )
 
 
+set( CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake )
 SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
 SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
 SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
@@ -40,18 +63,38 @@ if( WIN32 AND NOT CYGWIN )
   endif()
   endif()
 elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
 elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
   # Update if necessary
   # Update if necessary
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS}")
 elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
 elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS} -Wwrite-strings")
+endif()
+
+if (COVERALLS)
+    include(Coveralls)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
 endif()
 endif()
 
 
+# Include the doc component.
+FIND_PACKAGE( doxygen )
+IF ( DOXYGEN_FOUND )
+    CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY )
+    ADD_CUSTOM_TARGET( doc ALL ${DOXYGEN_EXECUTABLE} doc/doxygenfile
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        COMMENT "Generating API documentation with Doxygen" VERBATIM )
+ENDIF ( DOXYGEN_FOUND )
+
 SET ( openddl_parser_src
 SET ( openddl_parser_src
+    code/OpenDDLCommon.cpp
+    code/OpenDDLExport.cpp
     code/OpenDDLParser.cpp
     code/OpenDDLParser.cpp
+    code/OpenDDLStream.cpp
     code/DDLNode.cpp
     code/DDLNode.cpp
     code/Value.cpp
     code/Value.cpp
+    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/OpenDDLExport.h
     include/openddlparser/OpenDDLParser.h
     include/openddlparser/OpenDDLParser.h
     include/openddlparser/OpenDDLParserUtils.h
     include/openddlparser/OpenDDLParserUtils.h
-    include/openddlparser/OpenDDLCommon.h
+    include/openddlparser/OpenDDLStream.h
     include/openddlparser/DDLNode.h
     include/openddlparser/DDLNode.h
     include/openddlparser/Value.h
     include/openddlparser/Value.h
     README.md
     README.md
@@ -59,6 +102,69 @@ SET ( openddl_parser_src
  
  
 SOURCE_GROUP( code            FILES ${openddl_parser_src} )
 SOURCE_GROUP( code            FILES ${openddl_parser_src} )
 
 
-ADD_LIBRARY( openddl_parser SHARED
-    ${openddl_parser_src}
+if ( DDL_STATIC_LIBRARY )
+	ADD_LIBRARY( openddl_parser STATIC
+		${openddl_parser_src}
+	)
+else()
+	ADD_LIBRARY( openddl_parser SHARED
+		${openddl_parser_src}
+	)
+endif()
+
+SET ( GTEST_PATH contrib/gtest-1.7.0 )
+
+SET ( gtest_src
+    ${GTEST_PATH}/src/gtest-death-test.cc
+    ${GTEST_PATH}/src/gtest-filepath.cc
+    ${GTEST_PATH}/src/gtest-internal-inl.h
+    ${GTEST_PATH}/src/gtest-port.cc
+    ${GTEST_PATH}/src/gtest-printers.cc
+    ${GTEST_PATH}/src/gtest-test-part.cc
+    ${GTEST_PATH}/src/gtest-typed-test.cc
+    ${GTEST_PATH}/src/gtest.cc
+    ${GTEST_PATH}/src/gtest_main.cc
+)
+
+SET( openddl_parser_unittest_src  
+    test/UnitTestCommon.h
+    test/DDLNodeTest.cpp
+    test/OpenDDLCommonTest.cpp
+    test/OpenDDLExportTest.cpp
+    test/OpenDDLParserTest.cpp
+    test/OpenDDLParserUtilsTest.cpp
+    test/OpenDDLStreamTest.cpp
+    test/OpenDDLIntegrationTest.cpp
+    test/ValueTest.cpp
+    test/OpenDDLDefectsTest.cpp
+)
+
+SOURCE_GROUP( code  FILES ${openddl_parser_unittest_src} )
+SOURCE_GROUP( gtest FILES ${gtest_src} )
+
+ADD_EXECUTABLE( openddl_parser_unittest 
+    ${gtest_src}
+    ${openddl_parser_unittest_src}
+)
+
+target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} )
+
+SET( openddl_parser_demo_src  
+    demo/main.cpp 
 )
 )
+
+if (COVERALLS)
+    set(COVERAGE_SRCS     ${gtest_src} ${openddl_parser_unittest_src} )
+
+    # Create the coveralls target.
+    coveralls_setup(
+        "${COVERAGE_SRCS}" # The source files.
+        ON                 # If we should upload.
+        "${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path.
+endif()
+
+ADD_EXECUTABLE( openddl_parser_demo
+    ${openddl_parser_demo_src}
+) 
+
+target_link_libraries( openddl_parser_demo openddl_parser )

+ 3 - 0
contrib/openddlparser/CREDITS

@@ -12,5 +12,8 @@ Improvements value interface, serveral bugfixes.
 - Henry Read ( henrya2 ):
 - Henry Read ( henrya2 ):
 Static build option, Interface improvements
 Static build option, Interface improvements
 
 
+- (wise86-android)
+fix several mem-leaks
+
 - Paul Holland ( pkholland ):
 - Paul Holland ( pkholland ):
 Bugfixes.
 Bugfixes.

+ 2 - 2
contrib/openddlparser/README.md

@@ -11,7 +11,7 @@ Current coverity check status:
   <img alt="Coverity Scan Build Status"
   <img alt="Coverity Scan Build Status"
        src="https://scan.coverity.com/projects/5606/badge.svg"/>
        src="https://scan.coverity.com/projects/5606/badge.svg"/>
 </a>
 </a>
-
+Current test coverage:[![Coverage Status](https://coveralls.io/repos/github/kimkulling/openddl-parser/badge.svg?branch=master)](https://coveralls.io/github/kimkulling/openddl-parser?branch=cpp_coveralls)
 Get the source code
 Get the source code
 ===================
 ===================
 You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command:
 You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command:
@@ -25,7 +25,7 @@ After installing it you can open a console and enter:
 
 
 > cmake CMakeLists.txt
 > cmake CMakeLists.txt
 
 
-This command will generate a build environment for your installed build enrironment ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ).
+This command will generate a build environment for your preferred build tool ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ).
 When using an IDE open the IDE and run the build. When using GNU-make type in your console:
 When using an IDE open the IDE and run the build. When using GNU-make type in your console:
 
 
 > make
 > make

+ 14 - 6
contrib/openddlparser/code/DDLNode.cpp

@@ -68,8 +68,8 @@ DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx,
 }
 }
 
 
 DDLNode::~DDLNode() {
 DDLNode::~DDLNode() {
-    releaseDataType<Property>( m_properties );
-    releaseDataType<Value>( m_value );
+    delete m_properties;
+    delete m_value;
     releaseReferencedNames( m_references );
     releaseReferencedNames( m_references );
 
 
     delete m_dtArrayList;
     delete m_dtArrayList;
@@ -77,6 +77,9 @@ DDLNode::~DDLNode() {
     if( s_allocatedNodes[ m_idx ] == this ) {
     if( s_allocatedNodes[ m_idx ] == this ) {
         s_allocatedNodes[ m_idx ] = ddl_nullptr;
         s_allocatedNodes[ m_idx ] = ddl_nullptr;
     }
     }
+    for ( size_t i = 0; i<m_children.size(); i++ ){
+        delete m_children[ i ];
+    }
 }
 }
 
 
 void DDLNode::attachParent( DDLNode *parent ) {
 void DDLNode::attachParent( DDLNode *parent ) {
@@ -91,9 +94,8 @@ void DDLNode::attachParent( DDLNode *parent ) {
 }
 }
 
 
 void DDLNode::detachParent() {
 void DDLNode::detachParent() {
-    if( m_parent ) {
-        std::vector<DDLNode*>::iterator it;
-        it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
+    if( ddl_nullptr != m_parent ) {
+        DDLNodeIt it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this );
         if( m_parent->m_children.end() != it ) {
         if( m_parent->m_children.end() != it ) {
             m_parent->m_children.erase( it );
             m_parent->m_children.erase( it );
         }
         }
@@ -126,6 +128,8 @@ const std::string &DDLNode::getName() const {
 }
 }
 
 
 void DDLNode::setProperties( Property *prop ) {
 void DDLNode::setProperties( Property *prop ) {
+    if(m_properties!=ddl_nullptr)
+        delete m_properties;
     m_properties = prop;
     m_properties = prop;
 }
 }
 
 
@@ -187,6 +191,10 @@ Reference *DDLNode::getReferences() const {
     return m_references;
     return m_references;
 }
 }
 
 
+void DDLNode::dump(IOStreamBase &stream) {
+    // Todo!    
+}
+
 DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
 DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) {
     const size_t idx( s_allocatedNodes.size() );
     const size_t idx( s_allocatedNodes.size() );
     DDLNode *node = new DDLNode( type, name, idx, parent );
     DDLNode *node = new DDLNode( type, name, idx, parent );
@@ -197,7 +205,7 @@ DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLN
 
 
 void DDLNode::releaseNodes() {
 void DDLNode::releaseNodes() {
     if( s_allocatedNodes.size() > 0 ) {
     if( s_allocatedNodes.size() > 0 ) {
-        for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
+        for( DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
             if( *it ) {
             if( *it ) {
                 delete *it;
                 delete *it;
             }
             }

+ 35 - 9
contrib/openddlparser/code/OpenDDLCommon.cpp

@@ -22,6 +22,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------------------------*/
 -----------------------------------------------------------------------------------------------*/
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/DDLNode.h>
 #include <openddlparser/DDLNode.h>
+#include <openddlparser/Value.h>
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
@@ -84,7 +85,14 @@ Name::~Name() {
     m_id = ddl_nullptr;
     m_id = ddl_nullptr;
 }
 }
 
 
-Reference::Reference()
+Name::Name( const Name &name ){
+    m_type=name.m_type;
+    m_id=new Text(name.m_id->m_buffer,name.m_id->m_len);
+}
+
+
+
+    Reference::Reference()
 : m_numRefs( 0 )
 : m_numRefs( 0 )
 , m_referencedName( ddl_nullptr ) {
 , m_referencedName( ddl_nullptr ) {
     // empty
     // empty
@@ -96,8 +104,16 @@ Reference::Reference( size_t numrefs, Name **names )
     if ( numrefs > 0 ) {
     if ( numrefs > 0 ) {
         m_referencedName = new Name *[ numrefs ];
         m_referencedName = new Name *[ numrefs ];
         for ( size_t i = 0; i < numrefs; i++ ) {
         for ( size_t i = 0; i < numrefs; i++ ) {
-            Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id );
-            m_referencedName[ i ] = name;
+            m_referencedName[ i ] = names[i];
+        }
+    }
+}
+Reference::Reference(const Reference &ref) {
+    m_numRefs=ref.m_numRefs;
+    if(m_numRefs!=0){
+        m_referencedName = new Name*[m_numRefs];
+        for ( size_t i = 0; i < m_numRefs; i++ ) {
+            m_referencedName[i] = new Name(*ref.m_referencedName[i]);
         }
         }
     }
     }
 }
 }
@@ -107,6 +123,7 @@ Reference::~Reference() {
         delete m_referencedName[ i ];
         delete m_referencedName[ i ];
     }
     }
     m_numRefs = 0;
     m_numRefs = 0;
+    delete [] m_referencedName;
     m_referencedName = ddl_nullptr;
     m_referencedName = ddl_nullptr;
 }
 }
 
 
@@ -135,21 +152,30 @@ Property::Property( Text *id )
 }
 }
 
 
 Property::~Property() {
 Property::~Property() {
-    m_key = ddl_nullptr;
-    m_value = ddl_nullptr;
-    m_ref = ddl_nullptr;;
-    m_next = ddl_nullptr;;
+    delete m_key;
+    if(m_value!=ddl_nullptr)
+        delete m_value;
+    if(m_ref!=ddl_nullptr)
+        delete(m_ref);
+    if(m_next!=ddl_nullptr)
+        delete m_next;
 }
 }
 
 
 DataArrayList::DataArrayList()
 DataArrayList::DataArrayList()
 : m_numItems( 0 )
 : m_numItems( 0 )
 , m_dataList( ddl_nullptr )
 , m_dataList( ddl_nullptr )
-, m_next( ddl_nullptr ) {
+, m_next( ddl_nullptr )
+, m_refs(ddl_nullptr)
+, m_numRefs(0){
     // empty
     // empty
 }
 }
 
 
 DataArrayList::~DataArrayList() {
 DataArrayList::~DataArrayList() {
-    // empty
+    delete m_dataList;
+    if(m_next!=ddl_nullptr)
+        delete m_next;
+    if(m_refs!=ddl_nullptr)
+        delete m_refs;
 }
 }
 
 
 size_t DataArrayList::size() {
 size_t DataArrayList::size() {

+ 1 - 55
contrib/openddlparser/code/OpenDDLExport.cpp

@@ -29,60 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
-StreamFormatterBase::StreamFormatterBase() {
-
-}
-
-StreamFormatterBase::~StreamFormatterBase() {
-
-}
-
-std::string StreamFormatterBase::format( const std::string &statement ) {
-    std::string tmp( statement );
-    return tmp;
-}
-
-IOStreamBase::IOStreamBase( StreamFormatterBase *formatter )
-: m_formatter( formatter )
-, m_file( ddl_nullptr ) {
-    if (ddl_nullptr == m_formatter) {
-        m_formatter = new StreamFormatterBase;
-    }
-}
-
-IOStreamBase::~IOStreamBase() {
-    delete m_formatter;
-    m_formatter = ddl_nullptr;
-}
-
-bool IOStreamBase::open( const std::string &name ) {
-    m_file = ::fopen( name.c_str(), "a" );
-    if (m_file == ddl_nullptr) {
-        return false;
-    }
-    
-    return true;
-}
-
-bool IOStreamBase::close() {
-    if (ddl_nullptr == m_file) {
-        return false;
-    }
-
-    ::fclose( m_file );
-    m_file = ddl_nullptr;
-
-    return true;
-}
-
-size_t IOStreamBase::write( const std::string &statement ) {
-    if (ddl_nullptr == m_file) {
-        return 0;
-    }
-    std::string formatStatement = m_formatter->format( statement );
-    return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file );
-}
-
 struct DDLNodeIterator {
 struct DDLNodeIterator {
     const DDLNode::DllNodeList &m_childs;
     const DDLNode::DllNodeList &m_childs;
     size_t m_idx;
     size_t m_idx;
@@ -280,7 +226,7 @@ bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std:
         statement += "[";
         statement += "[";
         char buffer[ 256 ];
         char buffer[ 256 ];
         ::memset( buffer, '\0', 256 * sizeof( char ) );
         ::memset( buffer, '\0', 256 * sizeof( char ) );
-        sprintf( buffer, "%d", int(numItems) );
+        sprintf( buffer, "%d", static_cast<int>( numItems ) );
         statement += buffer;
         statement += buffer;
         statement += "]";
         statement += "]";
     }
     }

+ 80 - 65
contrib/openddlparser/code/OpenDDLParser.cpp

@@ -36,7 +36,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
-static const char *Version = "0.3.0";
+static const char *Version = "0.4.0";
 
 
 namespace Grammar {
 namespace Grammar {
     static const char *OpenBracketToken   = "{";
     static const char *OpenBracketToken   = "{";
@@ -49,7 +49,7 @@ namespace Grammar {
     static const char *BoolFalse          = "false";
     static const char *BoolFalse          = "false";
     static const char *CommaSeparator     = ",";
     static const char *CommaSeparator     = ",";
 
 
-    static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
+    static const char *PrimitiveTypeToken[ Value::ddl_types_max ] = {
         "bool",
         "bool",
         "int8",
         "int8",
         "int16",
         "int16",
@@ -74,8 +74,8 @@ const char *getTypeToken( Value::ValueType  type ) {
 static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
 static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) {
     std::stringstream stream;
     std::stringstream stream;
     stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl;
     stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl;
-    std::string full(in);
-    std::string part(full.substr(0,50));
+    std::string full( in );
+    std::string part( full.substr( 0, 50 ) );
     stream << part;
     stream << part;
     callback( ddl_error_msg, stream.str() );
     callback( ddl_error_msg, stream.str() );
 }
 }
@@ -85,6 +85,7 @@ static bool isIntegerType( Value::ValueType integerType ) {
             integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
             integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
         return false;
         return false;
     }
     }
+    
     return true;
     return true;
 }
 }
 
 
@@ -105,7 +106,7 @@ static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) {
     const std::string type( id->m_buffer );
     const std::string type( id->m_buffer );
     DDLNode *parent( parser->top() );
     DDLNode *parent( parser->top() );
     DDLNode *node = DDLNode::create( type, "", parent );
     DDLNode *node = DDLNode::create( type, "", parent );
-
+    
     return node;
     return node;
 }
 }
 
 
@@ -193,10 +194,11 @@ size_t OpenDDLParser::getBufferSize() const {
 void OpenDDLParser::clear() {
 void OpenDDLParser::clear() {
     m_buffer.resize( 0 );
     m_buffer.resize( 0 );
     if( ddl_nullptr != m_context ) {
     if( ddl_nullptr != m_context ) {
-        m_context->m_root = ddl_nullptr;
+        delete m_context;
+        m_context=ddl_nullptr;
     }
     }
 
 
-    DDLNode::releaseNodes();
+//    DDLNode::releaseNodes();
 }
 }
 
 
 bool OpenDDLParser::parse() {
 bool OpenDDLParser::parse() {
@@ -212,11 +214,11 @@ bool OpenDDLParser::parse() {
 
 
     // do the main parsing
     // do the main parsing
     char *current( &m_buffer[ 0 ] );
     char *current( &m_buffer[ 0 ] );
-    char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 );
+    char *end( &m_buffer[m_buffer.size() - 1 ] + 1 );
     size_t pos( current - &m_buffer[ 0 ] );
     size_t pos( current - &m_buffer[ 0 ] );
     while( pos < m_buffer.size() ) {
     while( pos < m_buffer.size() ) {
         current = parseNextNode( current, end );
         current = parseNextNode( current, end );
-        if(current==ddl_nullptr) {
+        if ( current == ddl_nullptr ) {
             return false;
             return false;
         }
         }
         pos = current - &m_buffer[ 0 ];
         pos = current - &m_buffer[ 0 ];
@@ -245,7 +247,7 @@ static void dumpId( Identifier *id ) {
     if( ddl_nullptr != id ) {
     if( ddl_nullptr != id ) {
         if ( ddl_nullptr != id->m_text.m_buffer ) {
         if ( ddl_nullptr != id->m_text.m_buffer ) {
             std::cout << id->m_text.m_buffer << std::endl;
             std::cout << id->m_text.m_buffer << std::endl;
-	}
+	    }
     }
     }
 }
 }
 #endif
 #endif
@@ -271,14 +273,17 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
         } else {
         } else {
             std::cerr << "nullptr returned by creating DDLNode." << std::endl;
             std::cerr << "nullptr returned by creating DDLNode." << std::endl;
         }
         }
+        delete id;
 
 
 		Name *name(ddl_nullptr);
 		Name *name(ddl_nullptr);
 		in = OpenDDLParser::parseName(in, end, &name);
 		in = OpenDDLParser::parseName(in, end, &name);
         if( ddl_nullptr != name && ddl_nullptr != node ) {
         if( ddl_nullptr != name && ddl_nullptr != node ) {
             const std::string nodeName( name->m_id->m_buffer );
             const std::string nodeName( name->m_id->m_buffer );
             node->setName( nodeName );
             node->setName( nodeName );
+            delete name;
         }
         }
 
 
+
 		Property *first(ddl_nullptr);
 		Property *first(ddl_nullptr);
 		in = lookForNextToken(in, end);
 		in = lookForNextToken(in, end);
 		if (*in == Grammar::OpenPropertyToken[0]) {
 		if (*in == Grammar::OpenPropertyToken[0]) {
@@ -303,7 +308,7 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
 					prev = prop;
 					prev = prop;
 				}
 				}
 			}
 			}
-			in++;
+			++in;
 		}
 		}
 
 
 		// set the properties
 		// set the properties
@@ -322,17 +327,17 @@ char *OpenDDLParser::parseStructure( char *in, char *end ) {
 
 
     bool error( false );
     bool error( false );
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
-    if( *in == '{' ) {
+    if( *in == *Grammar::OpenBracketToken) {
         // loop over all children ( data and nodes )
         // loop over all children ( data and nodes )
         do {
         do {
             in = parseStructureBody( in, end, error );
             in = parseStructureBody( in, end, error );
             if(in == ddl_nullptr){
             if(in == ddl_nullptr){
                 return ddl_nullptr;
                 return ddl_nullptr;
             }
             }
-        } while ( *in != '}' );
-        in++;
+        } while ( *in != *Grammar::CloseBracketToken);
+        ++in;
     } else {
     } else {
-        in++;
+        ++in;
         logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
         logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
         error = true;
         error = true;
         return ddl_nullptr;
         return ddl_nullptr;
@@ -373,7 +378,7 @@ static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayLi
 
 
 char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
 char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) {
     if( !isNumeric( *in ) && !isCharacter( *in ) ) {
     if( !isNumeric( *in ) && !isCharacter( *in ) ) {
-        in++;
+        ++in;
     }
     }
 
 
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
@@ -431,7 +436,6 @@ DDLNode *OpenDDLParser::popNode() {
 
 
     DDLNode *topNode( top() );
     DDLNode *topNode( top() );
     m_stack.pop_back();
     m_stack.pop_back();
-
     return topNode;
     return topNode;
 }
 }
 
 
@@ -467,7 +471,14 @@ void OpenDDLParser::normalizeBuffer( std::vector<char> &buffer) {
     for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
     for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
         char *c( &buffer[readIdx] );
         char *c( &buffer[readIdx] );
         // check for a comment
         // check for a comment
-        if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
+        if (isCommentOpenTag(c, end)) {
+            ++readIdx;
+            while (!isCommentCloseTag(&buffer[readIdx], end)) {
+                ++readIdx;
+            }
+            ++readIdx;
+            ++readIdx;
+        } else if( !isComment<char>( c, end ) && !isNewLine( *c ) ) {
             newBuffer.push_back( buffer[ readIdx ] );
             newBuffer.push_back( buffer[ readIdx ] );
         } else {
         } else {
             if( isComment<char>( c, end ) ) {
             if( isComment<char>( c, end ) ) {
@@ -529,14 +540,17 @@ char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) {
     // get size of id
     // get size of id
     size_t idLen( 0 );
     size_t idLen( 0 );
     char *start( in );
     char *start( in );
-    while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] && *in != '$' ) {
+    while( !isSeparator( *in ) && 
+            !isNewLine( *in ) && ( in != end ) && 
+            *in != Grammar::OpenPropertyToken[ 0 ] &&
+            *in != Grammar::ClosePropertyToken[ 0 ] && 
+            *in != '$' ) {
         ++in;
         ++in;
         ++idLen;
         ++idLen;
     }
     }
 
 
     const size_t len( idLen );
     const size_t len( idLen );
-    Text *newId = new Text( start, len );
-    *id = newId;
+    *id = new Text( start, len );
 
 
     return in;
     return in;
 }
 }
@@ -552,7 +566,7 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
     for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
     for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
         prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
         prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] );
         if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
         if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) {
-            type = ( Value::ValueType ) i;
+            type = static_cast<Value::ValueType>( i );
             break;
             break;
         }
         }
     }
     }
@@ -567,14 +581,14 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy
     bool ok( true );
     bool ok( true );
     if( *in == Grammar::OpenArrayToken[ 0 ] ) {
     if( *in == Grammar::OpenArrayToken[ 0 ] ) {
         ok = false;
         ok = false;
-        in++;
+        ++in;
         char *start( in );
         char *start( in );
         while ( in != end ) {
         while ( in != end ) {
-            in++;
+            ++in;
             if( *in == Grammar::CloseArrayToken[ 0 ] ) {
             if( *in == Grammar::CloseArrayToken[ 0 ] ) {
                 len = ::atoi( start );
                 len = ::atoi( start );
                 ok = true;
                 ok = true;
-                in++;
+                ++in;
                 break;
                 break;
             }
             }
         }
         }
@@ -623,10 +637,10 @@ char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean )
     char *start( in );
     char *start( in );
     size_t len( 0 );
     size_t len( 0 );
     while( !isSeparator( *in ) && in != end ) {
     while( !isSeparator( *in ) && in != end ) {
-        in++;
-        len++;
+        ++in;
+        ++len;
     }
     }
-    len++;
+    ++len;
     int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
     int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) );
     if( 0 != res ) {
     if( 0 != res ) {
         res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
         res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) );
@@ -657,7 +671,7 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer,
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     char *start( in );
     char *start( in );
     while( !isSeparator( *in ) && in != end ) {
     while( !isSeparator( *in ) && in != end ) {
-        in++;
+        ++in;
     }
     }
 
 
     if( isNumeric( *start ) ) {
     if( isNumeric( *start ) ) {
@@ -671,29 +685,29 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer,
         *integer = ValueAllocator::allocPrimData( integerType );
         *integer = ValueAllocator::allocPrimData( integerType );
         switch( integerType ) {
         switch( integerType ) {
             case Value::ddl_int8:
             case Value::ddl_int8:
-                    ( *integer )->setInt8( (int8) value );
-                    break;
+                ( *integer )->setInt8( (int8) value );
+                break;
             case Value::ddl_int16:
             case Value::ddl_int16:
-                    ( *integer )->setInt16( ( int16 ) value );
-                    break;
+                ( *integer )->setInt16( ( int16 ) value );
+                break;
             case Value::ddl_int32:
             case Value::ddl_int32:
-                    ( *integer )->setInt32( ( int32 ) value );
-                    break;
+                ( *integer )->setInt32( ( int32 ) value );
+                break;
             case Value::ddl_int64:
             case Value::ddl_int64:
-                    ( *integer )->setInt64( ( int64 ) value );
-                    break;
+                ( *integer )->setInt64( ( int64 ) value );
+                break;
             case Value::ddl_unsigned_int8:
             case Value::ddl_unsigned_int8:
-                    ( *integer )->setUnsignedInt8( (uint8) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt8( (uint8) uvalue );
+                break;
             case Value::ddl_unsigned_int16:
             case Value::ddl_unsigned_int16:
-                    ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt16( ( uint16 ) uvalue );
+                break;
             case Value::ddl_unsigned_int32:
             case Value::ddl_unsigned_int32:
-                    ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt32( ( uint32 ) uvalue );
+                break;
             case Value::ddl_unsigned_int64:
             case Value::ddl_unsigned_int64:
-                    ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
-                    break;
+                ( *integer )->setUnsignedInt64( ( uint64 ) uvalue );
+                break;
             default:
             default:
                 break;
                 break;
         }
         }
@@ -711,7 +725,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     char *start( in );
     char *start( in );
     while( !isSeparator( *in ) && in != end ) {
     while( !isSeparator( *in ) && in != end ) {
-        in++;
+        ++in;
     }
     }
 
 
     // parse the float value
     // parse the float value
@@ -732,8 +746,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating
     }
     }
 
 
     if( ok ) {
     if( ok ) {
-        if(floatType == Value::ddl_double)
-        {
+        if ( floatType == Value::ddl_double ) {
             const double value( atof( start ) );
             const double value( atof( start ) );
             *floating = ValueAllocator::allocPrimData( Value::ddl_double );
             *floating = ValueAllocator::allocPrimData( Value::ddl_double );
             ( *floating )->setDouble( value );
             ( *floating )->setDouble( value );
@@ -757,17 +770,17 @@ char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData
     size_t len( 0 );
     size_t len( 0 );
     char *start( in );
     char *start( in );
     if( *start == '\"' ) {
     if( *start == '\"' ) {
-        start++;
-        in++;
+        ++start;
+        ++in;
         while( *in != '\"' && in != end ) {
         while( *in != '\"' && in != end ) {
-            in++;
-            len++;
+            ++in;
+            ++len;
         }
         }
 
 
         *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
         *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len );
         ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
         ::strncpy( ( char* ) ( *stringData )->m_data, start, len );
         ( *stringData )->m_data[len] = '\0';
         ( *stringData )->m_data[len] = '\0';
-        in++;
+        ++in;
     }
     }
 
 
     return in;
     return in;
@@ -791,12 +804,12 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
         return in;
         return in;
     }
     }
 
 
-    in++;
+    ++in;
     if( *in != 'x' && *in != 'X' ) {
     if( *in != 'x' && *in != 'X' ) {
         return in;
         return in;
     }
     }
 
 
-    in++;
+    ++in;
     bool ok( true );
     bool ok( true );
     char *start( in );
     char *start( in );
     int pos( 0 );
     int pos( 0 );
@@ -805,8 +818,8 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
             ok = false;
             ok = false;
             break;
             break;
         }
         }
-        pos++;
-        in++;
+        ++pos;
+        ++in;
     }
     }
 
 
     if( !ok ) {
     if( !ok ) {
@@ -816,9 +829,9 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
     int value( 0 );
     int value( 0 );
     while( pos > 0 ) {
     while( pos > 0 ) {
         int v = hex2Decimal( *start );
         int v = hex2Decimal( *start );
-        pos--;
+        --pos;
         value = ( value << 4 ) | v;
         value = ( value << 4 ) | v;
-        start++;
+        ++start;
     }
     }
 
 
     *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
     *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 );
@@ -841,7 +854,7 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
     if( ddl_nullptr != id ) {
     if( ddl_nullptr != id ) {
         in = lookForNextToken( in, end );
         in = lookForNextToken( in, end );
         if( *in == '=' ) {
         if( *in == '=' ) {
-            in++;
+            ++in;
             in = getNextToken( in, end );
             in = getNextToken( in, end );
             Value *primData( ddl_nullptr );
             Value *primData( ddl_nullptr );
             if( isInteger( in, end ) ) {
             if( isInteger( in, end ) ) {
@@ -862,6 +875,8 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
                     ( *prop )->m_ref = ref;
                     ( *prop )->m_ref = ref;
                 }
                 }
             }
             }
+        } else {
+            delete id;
         }
         }
     }
     }
 
 
@@ -878,7 +893,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
 
 
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     if( *in == '{' ) {
     if( *in == '{' ) {
-        in++;
+        ++in;
         Value *current( ddl_nullptr ), *prev( ddl_nullptr );
         Value *current( ddl_nullptr ), *prev( ddl_nullptr );
         while( '}' != *in ) {
         while( '}' != *in ) {
             current = ddl_nullptr;
             current = ddl_nullptr;
@@ -934,7 +949,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
                     prev->setNext( current );
                     prev->setNext( current );
                     prev = current;
                     prev = current;
                 }
                 }
-                numValues++;
+                ++numValues;
             }
             }
 
 
             in = getNextSeparator( in, end );
             in = getNextSeparator( in, end );
@@ -942,7 +957,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type,
                 break;
                 break;
             }
             }
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     return in;
     return in;
@@ -972,7 +987,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty
 
 
     in = lookForNextToken( in, end );
     in = lookForNextToken( in, end );
     if( *in == Grammar::OpenBracketToken[ 0 ] ) {
     if( *in == Grammar::OpenBracketToken[ 0 ] ) {
-        in++;
+        ++in;
         Value *currentValue( ddl_nullptr );
         Value *currentValue( ddl_nullptr );
         Reference *refs( ddl_nullptr );
         Reference *refs( ddl_nullptr );
         DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
         DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr );
@@ -995,7 +1010,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty
             }
             }
         } while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
         } while( Grammar::CommaSeparator[ 0 ] == *in && in != end );
         in = lookForNextToken( in, end );
         in = lookForNextToken( in, end );
-        in++;
+        ++in;
     }
     }
 
 
     return in;
     return in;

+ 96 - 0
contrib/openddlparser/code/OpenDDLStream.cpp

@@ -0,0 +1,96 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#include <openddlparser/OpenDDLStream.h>
+
+BEGIN_ODDLPARSER_NS
+
+StreamFormatterBase::StreamFormatterBase() {
+    // empty
+}
+
+StreamFormatterBase::~StreamFormatterBase() {
+    // empty
+}
+
+std::string StreamFormatterBase::format(const std::string &statement) {
+    std::string tmp(statement);
+    return tmp;
+}
+
+IOStreamBase::IOStreamBase(StreamFormatterBase *formatter)
+    : m_formatter(formatter)
+    , m_file(ddl_nullptr) {
+    if (ddl_nullptr == m_formatter) {
+        m_formatter = new StreamFormatterBase;
+    }
+}
+
+IOStreamBase::~IOStreamBase() {
+    delete m_formatter;
+    m_formatter = ddl_nullptr;
+}
+
+bool IOStreamBase::open(const std::string &name) {
+    m_file = ::fopen(name.c_str(), "a");
+    if (m_file == ddl_nullptr) {
+        return false;
+    }
+
+    return true;
+}
+
+bool IOStreamBase::close() {
+    if (ddl_nullptr == m_file) {
+        return false;
+    }
+
+    ::fclose(m_file);
+    m_file = ddl_nullptr;
+
+    return true;
+}
+
+bool IOStreamBase::isOpen() const {
+    return ( ddl_nullptr != m_file );
+}
+
+size_t IOStreamBase::read( size_t sizeToRead, std::string &statement ) {
+    if (ddl_nullptr == m_file) {
+        return 0;
+    }
+    
+    statement.resize(sizeToRead);
+    const size_t readBytes = ::fread( &statement[0], 1, sizeToRead, m_file );
+
+    return readBytes;
+}
+
+size_t IOStreamBase::write(const std::string &statement) {
+    if (ddl_nullptr == m_file) {
+        return 0;
+    }
+    std::string formatStatement = m_formatter->format(statement);
+    return ::fwrite(formatStatement.c_str(), sizeof(char), formatStatement.size(), m_file);
+}
+
+END_ODDLPARSER_NS

+ 17 - 18
contrib/openddlparser/code/Value.cpp

@@ -110,7 +110,17 @@ Value::Value( ValueType type )
 }
 }
 
 
 Value::~Value() {
 Value::~Value() {
-    // empty
+    if(m_data!=ddl_nullptr) {
+        if (m_type == ddl_ref ) {
+            Reference *tmp = (Reference *) m_data;
+            if (tmp != ddl_nullptr)
+                delete tmp;
+        }else
+            delete[] m_data;
+
+    }
+    if(m_next!=ddl_nullptr)
+        delete m_next;
 }
 }
 
 
 void Value::setBool( bool value ) {
 void Value::setBool( bool value ) {
@@ -273,13 +283,7 @@ void Value::setRef( Reference *ref ) {
                 delete [] m_data;
                 delete [] m_data;
             }
             }
 
 
-            m_data = new unsigned char[ sizeof( Reference ) ];
-            Reference *myRef = ( Reference * ) m_data;
-            myRef->m_numRefs = ref->m_numRefs;
-            myRef->m_referencedName =  new Name *[ myRef->m_numRefs ];
-            for ( size_t i = 0; i < myRef->m_numRefs; i++ ) {
-                myRef->m_referencedName[ i ] = new Name( ref->m_referencedName[ i ]->m_type, ref->m_referencedName[ i ]->m_id );
-            }
+            m_data = (unsigned char*) new Reference(*ref);
         }
         }
     }
     }
 }
 }
@@ -290,7 +294,7 @@ Reference *Value::getRef() const {
     return (Reference*) m_data;
     return (Reference*) m_data;
 }
 }
 
 
-void Value::dump() {
+void Value::dump( IOStreamBase &stream ) {
     switch( m_type ) {
     switch( m_type ) {
         case ddl_none:
         case ddl_none:
             std::cout << "None" << std::endl;
             std::cout << "None" << std::endl;
@@ -350,7 +354,7 @@ Value *Value::getNext() const {
     return m_next;
     return m_next;
 }
 }
 
 
-size_t Value::size(){
+size_t Value::size() const{
     size_t result=1;
     size_t result=1;
     Value *n=m_next;
     Value *n=m_next;
     while( n!=ddl_nullptr) {
     while( n!=ddl_nullptr) {
@@ -366,7 +370,6 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
     }
     }
 
 
     Value *data = new Value( type );
     Value *data = new Value( type );
-    data->m_type = type;
     switch( type ) {
     switch( type ) {
         case Value::ddl_bool:
         case Value::ddl_bool:
             data->m_size = sizeof( bool );
             data->m_size = sizeof( bool );
@@ -405,10 +408,10 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
             data->m_size = sizeof( double );
             data->m_size = sizeof( double );
             break;
             break;
         case Value::ddl_string:
         case Value::ddl_string:
-            data->m_size = sizeof( char );
+            data->m_size = sizeof( char )*(len+1);
             break;
             break;
         case Value::ddl_ref:
         case Value::ddl_ref:
-            data->m_size = sizeof( char );
+            data->m_size = 0;
             break;
             break;
         case Value::ddl_none:
         case Value::ddl_none:
         case Value::ddl_types_max:
         case Value::ddl_types_max:
@@ -417,12 +420,8 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
     }
     }
 
 
     if( data->m_size ) {
     if( data->m_size ) {
-        size_t len1( len );
-        if( Value::ddl_string == type ) {
-            len1++;
-        }
-        data->m_size *= len1;
         data->m_data = new unsigned char[ data->m_size ];
         data->m_data = new unsigned char[ data->m_size ];
+        ::memset(data->m_data,0,data->m_size);
     }
     }
 
 
     return data;
     return data;

+ 19 - 10
contrib/openddlparser/include/openddlparser/DDLNode.h

@@ -29,6 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
+// Forward declarations
+class IOStreamBase;
 class Value;
 class Value;
 class OpenDDLParser;
 class OpenDDLParser;
 
 
@@ -53,6 +55,9 @@ public:
     /// @brief  The child-node-list type.
     /// @brief  The child-node-list type.
     typedef std::vector<DDLNode*> DllNodeList;
     typedef std::vector<DDLNode*> DllNodeList;
 
 
+    /// @brief  The child-node-list iterator.
+    typedef std::vector<DDLNode*>::iterator DDLNodeIt;
+
 public:
 public:
     ///	@brief  The class destructor.
     ///	@brief  The class destructor.
     ~DDLNode();
     ~DDLNode();
@@ -81,7 +86,7 @@ public:
     const std::string &getType() const;
     const std::string &getType() const;
 
 
     /// Set the name of the DDLNode instance.
     /// Set the name of the DDLNode instance.
-    /// @param  type    [in] The name.
+    /// @param  name        [in] The name.
     void setName( const std::string &name );
     void setName( const std::string &name );
 
 
     /// @brief  Returns the name of the DDLNode instance.
     /// @brief  Returns the name of the DDLNode instance.
@@ -89,7 +94,7 @@ public:
     const std::string &getName() const;
     const std::string &getName() const;
 
 
     /// @brief  Set a new property set.
     /// @brief  Set a new property set.
-    ///	@param  prop    [in] The first element of the property set.
+    ///	@param  prop        [in] The first element of the property set.
     void setProperties( Property *prop );
     void setProperties( Property *prop );
 
 
     ///	@brief  Returns the first element of the assigned property set.
     ///	@brief  Returns the first element of the assigned property set.
@@ -97,7 +102,7 @@ public:
     Property *getProperties() const;
     Property *getProperties() const;
 
 
     ///	@brief  Looks for a given property.
     ///	@brief  Looks for a given property.
-    /// @param  name    [in] The name for the property to look for.
+    /// @param  name        [in] The name for the property to look for.
     /// @return true, if a corresponding property is assigned to the node, false if not.
     /// @return true, if a corresponding property is assigned to the node, false if not.
     bool hasProperty( const std::string &name );
     bool hasProperty( const std::string &name );
 
 
@@ -106,12 +111,12 @@ public:
     bool hasProperties() const;
     bool hasProperties() const;
 
 
     ///	@brief  Search for a given property and returns it. Will return ddl_nullptr if no property was found.
     ///	@brief  Search for a given property and returns it. Will return ddl_nullptr if no property was found.
-    /// @param  name    [in] The name for the property to look for.
+    /// @param  name        [in] The name for the property to look for.
     /// @return The property or ddl_nullptr if no property was found.
     /// @return The property or ddl_nullptr if no property was found.
     Property *findPropertyByName( const std::string &name );
     Property *findPropertyByName( const std::string &name );
     
     
     /// @brief  Set a new value set.
     /// @brief  Set a new value set.
-    /// @param  val     [in] The first value instance of the value set.
+    /// @param  val         [in] The first value instance of the value set.
     void setValue( Value *val );
     void setValue( Value *val );
 
 
     ///	@brief  Returns the first element of the assigned value set.
     ///	@brief  Returns the first element of the assigned value set.
@@ -119,7 +124,7 @@ public:
     Value *getValue() const;
     Value *getValue() const;
 
 
     /// @brief  Set a new DataArrayList.
     /// @brief  Set a new DataArrayList.
-    /// @param  val     [in] The DataArrayList instance.
+    /// @param  dtArrayList [in] The DataArrayList instance.
     void setDataArrayList( DataArrayList *dtArrayList );
     void setDataArrayList( DataArrayList *dtArrayList );
 
 
     ///	@brief  Returns the DataArrayList.
     ///	@brief  Returns the DataArrayList.
@@ -127,17 +132,21 @@ public:
     DataArrayList *getDataArrayList() const;
     DataArrayList *getDataArrayList() const;
 
 
     /// @brief  Set a new Reference set.
     /// @brief  Set a new Reference set.
-    /// @param  val     [in] The first value instance of the Reference set.
+    /// @param  refs        [in] The first value instance of the Reference set.
     void setReferences( Reference  *refs );
     void setReferences( Reference  *refs );
 
 
     ///	@brief  Returns the first element of the assigned Reference set.
     ///	@brief  Returns the first element of the assigned Reference set.
     ///	@return The first property of the assigned Reference set.
     ///	@return The first property of the assigned Reference set.
     Reference *getReferences() const;
     Reference *getReferences() const;
 
 
+    /// @brief  Will dump the node into the stream.
+    /// @param  stream      [in] The stream to write to.
+    void dump(IOStreamBase &stream);
+
     ///	@brief  The creation method.
     ///	@brief  The creation method.
-    /// @param  type    [in] The DDLNode type.
-    ///	@param  name    [in] The name for the new DDLNode instance.
-    /// @param  parent  [in] The parent node instance or ddl_nullptr if no parent node is there.
+    /// @param  type        [in] The DDLNode type.
+    ///	@param  name        [in] The name for the new DDLNode instance.
+    /// @param  parent      [in] The parent node instance or ddl_nullptr if no parent node is there.
     /// @return The new created node instance.
     /// @return The new created node instance.
     static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
     static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr );
 
 

+ 3 - 4
contrib/openddlparser/include/openddlparser/OpenDDLCommon.h

@@ -148,12 +148,12 @@ struct DLL_ODDLPARSER_EXPORT Name {
     ///	@param  type    [in] The name type.
     ///	@param  type    [in] The name type.
     ///	@param  id      [in] The id.
     ///	@param  id      [in] The id.
     Name( NameType type, Text *id );
     Name( NameType type, Text *id );
-
+    Name( const Name &name );
     ///	@brief  The destructor.
     ///	@brief  The destructor.
     ~Name();
     ~Name();
 
 
 private:
 private:
-    Name( const Name & ) ddl_no_copy;
+
     Name &operator = ( const Name& ) ddl_no_copy;
     Name &operator = ( const Name& ) ddl_no_copy;
 };
 };
 
 
@@ -164,7 +164,7 @@ struct DLL_ODDLPARSER_EXPORT Reference {
 
 
     ///	@brief  The default constructor.
     ///	@brief  The default constructor.
     Reference();
     Reference();
-
+    Reference( const Reference &ref );
     ///	@brief  The constructor with an array of ref names.
     ///	@brief  The constructor with an array of ref names.
     /// @param  numrefs     [in] The number of ref names.
     /// @param  numrefs     [in] The number of ref names.
     /// @param  names       [in] The ref names.
     /// @param  names       [in] The ref names.
@@ -178,7 +178,6 @@ struct DLL_ODDLPARSER_EXPORT Reference {
     size_t sizeInBytes();
     size_t sizeInBytes();
 
 
 private:
 private:
-    Reference( const Reference & ) ddl_no_copy;
     Reference &operator = ( const Reference & ) ddl_no_copy;
     Reference &operator = ( const Reference & ) ddl_no_copy;
 };
 };
 
 

+ 3 - 27
contrib/openddlparser/include/openddlparser/OpenDDLExport.h

@@ -23,37 +23,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 #pragma once
 
 
 #include <openddlparser/OpenDDLCommon.h>
 #include <openddlparser/OpenDDLCommon.h>
+#include <openddlparser/OpenDDLStream.h>
 #include <openddlparser/Value.h>
 #include <openddlparser/Value.h>
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
-//-------------------------------------------------------------------------------------------------
-/// @ingroup    IOStreamBase
-///	@brief      This class represents the stream to write out.
-//-------------------------------------------------------------------------------------------------
-class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
-public:
-    StreamFormatterBase();
-    virtual ~StreamFormatterBase();
-    virtual std::string format( const std::string &statement );
-};
-
-//-------------------------------------------------------------------------------------------------
-/// @ingroup    IOStreamBase
-///	@brief      This class represents the stream to write out.
-//-------------------------------------------------------------------------------------------------
-class DLL_ODDLPARSER_EXPORT IOStreamBase {
-public:
-    IOStreamBase( StreamFormatterBase *formatter = ddl_nullptr );
-    virtual ~IOStreamBase();
-    virtual bool open( const std::string &anme );
-    virtual bool close();
-    virtual size_t write( const std::string &statement );
-
-private:
-    StreamFormatterBase *m_formatter;
-    FILE *m_file;
-};
+// Forward declarations
+class IOStreamBase;
 
 
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 ///
 ///

+ 11 - 1
contrib/openddlparser/include/openddlparser/OpenDDLParser.h

@@ -39,6 +39,16 @@ struct Identifier;
 struct Reference;
 struct Reference;
 struct Property;
 struct Property;
 
 
+template<class T>
+inline
+bool isEmbeddedCommentOpenTag( T *in, T *end ) {
+    if ( in == '/' && in+1 == '*' ) {
+        return true;
+    }
+
+    return false;
+}
+
 ///	@brief  Utility function to search for the next token or the end of the buffer.
 ///	@brief  Utility function to search for the next token or the end of the buffer.
 /// @param  in      [in] The start position in the buffer.
 /// @param  in      [in] The start position in the buffer.
 /// @param  end     [in] The end position in the buffer.
 /// @param  end     [in] The end position in the buffer.
@@ -47,7 +57,7 @@ struct Property;
 template<class T>
 template<class T>
 inline
 inline
 T *lookForNextToken( T *in, T *end ) {
 T *lookForNextToken( T *in, T *end ) {
-    while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) {
+    while( ( in != end ) && ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) ) {
         in++;
         in++;
     }
     }
     return in;
     return in;

+ 36 - 8
contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h

@@ -84,7 +84,7 @@ static const unsigned char chartype_table[ 256 ] = {
 template<class T>
 template<class T>
 inline
 inline
 bool isNumeric( const T in ) {
 bool isNumeric( const T in ) {
-	return ( chartype_table[ static_cast<int>( in ) ] == 1 );
+    return ( chartype_table[ static_cast<size_t>( in ) ] == 1 );
 }
 }
 
 
 template<class T>
 template<class T>
@@ -98,7 +98,7 @@ inline
 bool isInteger( T *in, T *end ) {
 bool isInteger( T *in, T *end ) {
     if( in != end ) {
     if( in != end ) {
         if( *in == '-' ) {
         if( *in == '-' ) {
-            in++;
+            ++in;
         }
         }
     }
     }
 
 
@@ -108,7 +108,7 @@ bool isInteger( T *in, T *end ) {
         if( !result ) {
         if( !result ) {
             break;
             break;
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     return result;
     return result;
@@ -119,7 +119,7 @@ inline
 bool isFloat( T *in, T *end ) {
 bool isFloat( T *in, T *end ) {
     if( in != end ) {
     if( in != end ) {
         if( *in == '-' ) {
         if( *in == '-' ) {
-            in++;
+            ++in;
         }
         }
     }
     }
 
 
@@ -134,12 +134,12 @@ bool isFloat( T *in, T *end ) {
         if( !result ) {
         if( !result ) {
             return false;
             return false;
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     // check for 1<.>0f
     // check for 1<.>0f
     if( *in == '.' ) {
     if( *in == '.' ) {
-        in++;
+        ++in;
     } else {
     } else {
         return false;
         return false;
     }
     }
@@ -150,7 +150,7 @@ bool isFloat( T *in, T *end ) {
         if( !result ) {
         if( !result ) {
             return false;
             return false;
         }
         }
-        in++;
+        ++in;
     }
     }
 
 
     return result;
     return result;
@@ -208,7 +208,7 @@ template<class T>
 inline
 inline
 static T *getNextSeparator( T *in, T *end ) {
 static T *getNextSeparator( T *in, T *end ) {
     while( !isSeparator( *in ) || in == end ) {
     while( !isSeparator( *in ) || in == end ) {
-        in++;
+        ++in;
     }
     }
     return in;
     return in;
 }
 }
@@ -250,5 +250,33 @@ bool isComment( T *in, T *end ) {
     return false;
     return false;
 }
 }
 
 
+template<class T>
+inline
+bool isCommentOpenTag(T *in, T *end ) {
+    if (*in == '/') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '*') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+template<class T>
+inline
+bool isCommentCloseTag(T *in, T *end) {
+    if (*in == '*') {
+        if (in + 1 != end) {
+            if (*(in + 1) == '/') {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
 END_ODDLPARSER_NS
 END_ODDLPARSER_NS
 
 

+ 89 - 0
contrib/openddlparser/include/openddlparser/OpenDDLStream.h

@@ -0,0 +1,89 @@
+/*-----------------------------------------------------------------------------------------------
+The MIT License (MIT)
+
+Copyright (c) 2014-2015 Kim Kulling
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-----------------------------------------------------------------------------------------------*/
+#pragma once
+
+#include <openddlparser/OpenDDLCommon.h>
+
+BEGIN_ODDLPARSER_NS
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup    IOStreamBase
+///	@brief      This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT StreamFormatterBase {
+public:
+    /// @brief  The class constructor.
+    StreamFormatterBase();
+
+    /// @brief  The class destructor, virtual.
+    virtual ~StreamFormatterBase();
+
+    /// @brief  Will format the sring and return the new formatted result.
+    /// @param  statement   [in] The string to reformat.
+    /// @return The reformatted result.
+    virtual std::string format(const std::string &statement);
+};
+
+//-------------------------------------------------------------------------------------------------
+/// @ingroup    IOStreamBase
+///	@brief      This class represents the stream to write out.
+//-------------------------------------------------------------------------------------------------
+class DLL_ODDLPARSER_EXPORT IOStreamBase {
+public:
+    /// @brief  The class constructor with the formatter.
+    /// @param  formatter   [in] The formatter to use.
+    explicit IOStreamBase(StreamFormatterBase *formatter = ddl_nullptr);
+
+    /// @brief  The class destructor, virtual.
+    virtual ~IOStreamBase();
+
+    /// @brief  Will open the stream.
+    /// @param  name        [in] The name for the stream.
+    /// @return true, if the stream was opened successfully, false if not.
+    virtual bool open(const std::string &name);
+
+    /// @brief  Will close the stream.
+    /// @return true, if the stream was closed successfully, false if not.
+    virtual bool close();
+
+    /// @brief  Returns true, if the stream is open.
+    /// @return true, if the stream is open, false if not.
+    virtual bool isOpen() const;
+
+    /// @brief  Will read a string from the stream.
+    /// @param  sizeToRead  [in] The size to read in bytes.
+    /// @param  statement   [out] The read statements.
+    /// @return The bytes read from the stream.
+    virtual size_t read( size_t sizeToRead, std::string &statement );
+
+    /// @brief  Will write a string into the stream.
+    /// @param  statement  [in] The string to write.
+    /// @return The bytes written into the stream.
+    virtual size_t write(const std::string &statement);
+
+private:
+    StreamFormatterBase *m_formatter;
+    FILE *m_file;
+};
+
+END_ODDLPARSER_NS

+ 7 - 3
contrib/openddlparser/include/openddlparser/Value.h

@@ -28,8 +28,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 BEGIN_ODDLPARSER_NS
 BEGIN_ODDLPARSER_NS
 
 
+// Forward declarations
 struct ValueAllocator;
 struct ValueAllocator;
 
 
+class IOStreamBase;
+
 ///------------------------------------------------------------------------------------------------
 ///------------------------------------------------------------------------------------------------
 ///	@brief  This class implements a value.
 ///	@brief  This class implements a value.
 ///
 ///
@@ -213,7 +216,7 @@ public:
     double getDouble() const;
     double getDouble() const;
 
 
     ///	@brief  Assigns a std::string to the value.
     ///	@brief  Assigns a std::string to the value.
-    /// @param  value       [in] The value.
+    /// @param  str         [in] The value.
     void setString( const std::string &str );
     void setString( const std::string &str );
 
 
     ///	@brief  Returns the std::string value.
     ///	@brief  Returns the std::string value.
@@ -229,7 +232,8 @@ public:
     Reference *getRef() const;
     Reference *getRef() const;
 
 
     ///	@brief  Dumps the value.
     ///	@brief  Dumps the value.
-    void dump();
+    /// @param  stream  [in] The stream to write in.
+    void dump( IOStreamBase &stream );
 
 
     ///	@brief  Assigns the next value.
     ///	@brief  Assigns the next value.
     ///	@param  next        [n] The next value.
     ///	@param  next        [n] The next value.
@@ -241,7 +245,7 @@ public:
 
 
     /// @brief  Gets the length of the array.
     /// @brief  Gets the length of the array.
     /// @return The number of items in the array.
     /// @return The number of items in the array.
-    size_t size();
+    size_t size() const;
 
 
     ValueType m_type;
     ValueType m_type;
     size_t m_size;
     size_t m_size;

+ 23 - 31
contrib/poly2tri/poly2tri/common/shapes.cc

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -88,7 +88,7 @@ void Triangle::Clear()
     points_[0]=points_[1]=points_[2] = NULL;
     points_[0]=points_[1]=points_[2] = NULL;
 }
 }
 
 
-void Triangle::ClearNeighbor(Triangle *triangle )
+void Triangle::ClearNeighbor(const Triangle *triangle )
 {
 {
     if( neighbors_[0] == triangle )
     if( neighbors_[0] == triangle )
     {
     {
@@ -96,14 +96,14 @@ void Triangle::ClearNeighbor(Triangle *triangle )
     }
     }
     else if( neighbors_[1] == triangle )
     else if( neighbors_[1] == triangle )
     {
     {
-        neighbors_[1] = NULL;            
+        neighbors_[1] = NULL;
     }
     }
     else
     else
     {
     {
         neighbors_[2] = NULL;
         neighbors_[2] = NULL;
     }
     }
 }
 }
-    
+
 void Triangle::ClearNeighbors()
 void Triangle::ClearNeighbors()
 {
 {
   neighbors_[0] = NULL;
   neighbors_[0] = NULL;
@@ -116,13 +116,9 @@ void Triangle::ClearDelunayEdges()
   delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
   delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
 }
 }
 
 
-Point* Triangle::OppositePoint(Triangle& t, Point& p)
+Point* Triangle::OppositePoint(Triangle& t, const Point& p)
 {
 {
   Point *cw = t.PointCW(p);
   Point *cw = t.PointCW(p);
-  //double x = cw->x;
-  //double y = cw->y;
-  //x = p.x;
-  //y = p.y;
   return PointCW(*cw);
   return PointCW(*cw);
 }
 }
 
 
@@ -164,8 +160,7 @@ int Triangle::Index(const Point* p)
     return 2;
     return 2;
   }
   }
   assert(0);
   assert(0);
-
-  return 0;
+  return -1;
 }
 }
 
 
 int Triangle::EdgeIndex(const Point* p1, const Point* p2)
 int Triangle::EdgeIndex(const Point* p1, const Point* p2)
@@ -192,7 +187,7 @@ int Triangle::EdgeIndex(const Point* p1, const Point* p2)
   return -1;
   return -1;
 }
 }
 
 
-void Triangle::MarkConstrainedEdge(const int index)
+void Triangle::MarkConstrainedEdge(int index)
 {
 {
   constrained_edge[index] = true;
   constrained_edge[index] = true;
 }
 }
@@ -215,7 +210,7 @@ void Triangle::MarkConstrainedEdge(Point* p, Point* q)
 }
 }
 
 
 // The point counter-clockwise to given point
 // The point counter-clockwise to given point
-Point* Triangle::PointCW(Point& point)
+Point* Triangle::PointCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return points_[2];
     return points_[2];
@@ -225,12 +220,11 @@ Point* Triangle::PointCW(Point& point)
     return points_[1];
     return points_[1];
   }
   }
   assert(0);
   assert(0);
-
-  return 0;
+  return NULL;
 }
 }
 
 
 // The point counter-clockwise to given point
 // The point counter-clockwise to given point
-Point* Triangle::PointCCW(Point& point)
+Point* Triangle::PointCCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return points_[1];
     return points_[1];
@@ -240,12 +234,11 @@ Point* Triangle::PointCCW(Point& point)
     return points_[0];
     return points_[0];
   }
   }
   assert(0);
   assert(0);
-
-  return 0;
+  return NULL;
 }
 }
 
 
 // The neighbor clockwise to given point
 // The neighbor clockwise to given point
-Triangle* Triangle::NeighborCW(Point& point)
+Triangle* Triangle::NeighborCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return neighbors_[1];
     return neighbors_[1];
@@ -256,7 +249,7 @@ Triangle* Triangle::NeighborCW(Point& point)
 }
 }
 
 
 // The neighbor counter-clockwise to given point
 // The neighbor counter-clockwise to given point
-Triangle* Triangle::NeighborCCW(Point& point)
+Triangle* Triangle::NeighborCCW(const Point& point)
 {
 {
   if (&point == points_[0]) {
   if (&point == points_[0]) {
     return neighbors_[2];
     return neighbors_[2];
@@ -266,7 +259,7 @@ Triangle* Triangle::NeighborCCW(Point& point)
   return neighbors_[1];
   return neighbors_[1];
 }
 }
 
 
-bool Triangle::GetConstrainedEdgeCCW(Point& p)
+bool Triangle::GetConstrainedEdgeCCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return constrained_edge[2];
     return constrained_edge[2];
@@ -276,7 +269,7 @@ bool Triangle::GetConstrainedEdgeCCW(Point& p)
   return constrained_edge[1];
   return constrained_edge[1];
 }
 }
 
 
-bool Triangle::GetConstrainedEdgeCW(Point& p)
+bool Triangle::GetConstrainedEdgeCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return constrained_edge[1];
     return constrained_edge[1];
@@ -286,7 +279,7 @@ bool Triangle::GetConstrainedEdgeCW(Point& p)
   return constrained_edge[0];
   return constrained_edge[0];
 }
 }
 
 
-void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     constrained_edge[2] = ce;
     constrained_edge[2] = ce;
@@ -297,7 +290,7 @@ void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
   }
   }
 }
 }
 
 
-void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
+void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     constrained_edge[1] = ce;
     constrained_edge[1] = ce;
@@ -308,7 +301,7 @@ void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
   }
   }
 }
 }
 
 
-bool Triangle::GetDelunayEdgeCCW(Point& p)
+bool Triangle::GetDelunayEdgeCCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return delaunay_edge[2];
     return delaunay_edge[2];
@@ -318,7 +311,7 @@ bool Triangle::GetDelunayEdgeCCW(Point& p)
   return delaunay_edge[1];
   return delaunay_edge[1];
 }
 }
 
 
-bool Triangle::GetDelunayEdgeCW(Point& p)
+bool Triangle::GetDelunayEdgeCW(const Point& p)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     return delaunay_edge[1];
     return delaunay_edge[1];
@@ -328,7 +321,7 @@ bool Triangle::GetDelunayEdgeCW(Point& p)
   return delaunay_edge[0];
   return delaunay_edge[0];
 }
 }
 
 
-void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCCW(const Point& p, bool e)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     delaunay_edge[2] = e;
     delaunay_edge[2] = e;
@@ -339,7 +332,7 @@ void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
   }
   }
 }
 }
 
 
-void Triangle::SetDelunayEdgeCW(Point& p, bool e)
+void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
 {
 {
   if (&p == points_[0]) {
   if (&p == points_[0]) {
     delaunay_edge[1] = e;
     delaunay_edge[1] = e;
@@ -351,7 +344,7 @@ void Triangle::SetDelunayEdgeCW(Point& p, bool e)
 }
 }
 
 
 // The neighbor across to given point
 // The neighbor across to given point
-Triangle& Triangle::NeighborAcross(Point& opoint)
+Triangle& Triangle::NeighborAcross(const Point& opoint)
 {
 {
   if (&opoint == points_[0]) {
   if (&opoint == points_[0]) {
     return *neighbors_[0];
     return *neighbors_[0];
@@ -369,5 +362,4 @@ void Triangle::DebugPrint()
   cout << points_[2]->x << "," << points_[2]->y << endl;
   cout << points_[2]->x << "," << points_[2]->y << endl;
 }
 }
 
 
-}
-
+}

+ 29 - 31
contrib/poly2tri/poly2tri/common/shapes.h

@@ -113,7 +113,7 @@ struct Point {
   /// Convert this point into a unit point. Returns the Length.
   /// Convert this point into a unit point. Returns the Length.
   double Normalize()
   double Normalize()
   {
   {
-    double len = Length();
+    const double len = Length();
     x /= len;
     x /= len;
     y /= len;
     y /= len;
     return len;
     return len;
@@ -162,50 +162,50 @@ bool constrained_edge[3];
 /// Flags to determine if an edge is a Delauney edge
 /// Flags to determine if an edge is a Delauney edge
 bool delaunay_edge[3];
 bool delaunay_edge[3];
 
 
-Point* GetPoint(const int& index);
-Point* PointCW(Point& point);
-Point* PointCCW(Point& point);
-Point* OppositePoint(Triangle& t, Point& p);
+Point* GetPoint(int index);
+Point* PointCW(const Point& point);
+Point* PointCCW(const Point& point);
+Point* OppositePoint(Triangle& t, const Point& p);
 
 
-Triangle* GetNeighbor(const int& index);
+Triangle* GetNeighbor(int index);
 void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
 void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
 void MarkNeighbor(Triangle& t);
 void MarkNeighbor(Triangle& t);
 
 
-void MarkConstrainedEdge(const int index);
+void MarkConstrainedEdge(int index);
 void MarkConstrainedEdge(Edge& edge);
 void MarkConstrainedEdge(Edge& edge);
 void MarkConstrainedEdge(Point* p, Point* q);
 void MarkConstrainedEdge(Point* p, Point* q);
 
 
 int Index(const Point* p);
 int Index(const Point* p);
 int EdgeIndex(const Point* p1, const Point* p2);
 int EdgeIndex(const Point* p1, const Point* p2);
 
 
-Triangle* NeighborCW(Point& point);
-Triangle* NeighborCCW(Point& point);
-bool GetConstrainedEdgeCCW(Point& p);
-bool GetConstrainedEdgeCW(Point& p);
-void SetConstrainedEdgeCCW(Point& p, bool ce);
-void SetConstrainedEdgeCW(Point& p, bool ce);
-bool GetDelunayEdgeCCW(Point& p);
-bool GetDelunayEdgeCW(Point& p);
-void SetDelunayEdgeCCW(Point& p, bool e);
-void SetDelunayEdgeCW(Point& p, bool e);
-
-bool Contains(Point* p);
+Triangle* NeighborCW(const Point& point);
+Triangle* NeighborCCW(const Point& point);
+bool GetConstrainedEdgeCCW(const Point& p);
+bool GetConstrainedEdgeCW(const Point& p);
+void SetConstrainedEdgeCCW(const Point& p, bool ce);
+void SetConstrainedEdgeCW(const Point& p, bool ce);
+bool GetDelunayEdgeCCW(const Point& p);
+bool GetDelunayEdgeCW(const Point& p);
+void SetDelunayEdgeCCW(const Point& p, bool e);
+void SetDelunayEdgeCW(const Point& p, bool e);
+
+bool Contains(const Point* p);
 bool Contains(const Edge& e);
 bool Contains(const Edge& e);
-bool Contains(Point* p, Point* q);
+bool Contains(const Point* p, const Point* q);
 void Legalize(Point& point);
 void Legalize(Point& point);
 void Legalize(Point& opoint, Point& npoint);
 void Legalize(Point& opoint, Point& npoint);
 /**
 /**
  * Clears all references to all other triangles and points
  * Clears all references to all other triangles and points
  */
  */
 void Clear();
 void Clear();
-void ClearNeighbor(Triangle *triangle );
+void ClearNeighbor(const Triangle *triangle);
 void ClearNeighbors();
 void ClearNeighbors();
 void ClearDelunayEdges();
 void ClearDelunayEdges();
 
 
 inline bool IsInterior();
 inline bool IsInterior();
 inline void IsInterior(bool b);
 inline void IsInterior(bool b);
 
 
-Triangle& NeighborAcross(Point& opoint);
+Triangle& NeighborAcross(const Point& opoint);
 
 
 void DebugPrint();
 void DebugPrint();
 
 
@@ -258,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
 
 
 inline bool operator !=(const Point& a, const Point& b)
 inline bool operator !=(const Point& a, const Point& b)
 {
 {
-  return a.x != b.x || a.y != b.y;
+  return !(a.x == b.x) && !(a.y == b.y);
 }
 }
 
 
 /// Peform the dot product on two vectors.
 /// Peform the dot product on two vectors.
@@ -282,22 +282,22 @@ inline Point Cross(const Point& a, double s)
 
 
 /// Perform the cross product on a scalar and a point. In 2D this produces
 /// Perform the cross product on a scalar and a point. In 2D this produces
 /// a point.
 /// a point.
-inline Point Cross(const double s, const Point& a)
+inline Point Cross(double s, const Point& a)
 {
 {
   return Point(-s * a.y, s * a.x);
   return Point(-s * a.y, s * a.x);
 }
 }
 
 
-inline Point* Triangle::GetPoint(const int& index)
+inline Point* Triangle::GetPoint(int index)
 {
 {
   return points_[index];
   return points_[index];
 }
 }
 
 
-inline Triangle* Triangle::GetNeighbor(const int& index)
+inline Triangle* Triangle::GetNeighbor(int index)
 {
 {
   return neighbors_[index];
   return neighbors_[index];
 }
 }
 
 
-inline bool Triangle::Contains(Point* p)
+inline bool Triangle::Contains(const Point* p)
 {
 {
   return p == points_[0] || p == points_[1] || p == points_[2];
   return p == points_[0] || p == points_[1] || p == points_[2];
 }
 }
@@ -307,7 +307,7 @@ inline bool Triangle::Contains(const Edge& e)
   return Contains(e.p) && Contains(e.q);
   return Contains(e.p) && Contains(e.q);
 }
 }
 
 
-inline bool Triangle::Contains(Point* p, Point* q)
+inline bool Triangle::Contains(const Point* p, const Point* q)
 {
 {
   return Contains(p) && Contains(q);
   return Contains(p) && Contains(q);
 }
 }
@@ -324,6 +324,4 @@ inline void Triangle::IsInterior(bool b)
 
 
 }
 }
 
 
-#endif
-
-
+#endif

+ 32 - 8
contrib/poly2tri/poly2tri/common/utils.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -28,18 +28,26 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
- 
+
 #ifndef UTILS_H
 #ifndef UTILS_H
 #define UTILS_H
 #define UTILS_H
 
 
+// Otherwise #defines like M_PI are undeclared under Visual Studio
+#define _USE_MATH_DEFINES
+
 #include <exception>
 #include <exception>
+#include <math.h>
+
+// C99 removes M_PI from math.h
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327
+#endif
 
 
 namespace p2t {
 namespace p2t {
 
 
-const double PI = 3.1415926535897932384626433832795029;
-const double PI_2 = 2 * PI;
-const double PI_3div4 = 3 * PI / 4;
-const double EPSILON = 1e-15;
+const double PI_3div4 = 3 * M_PI / 4;
+const double PI_div2 = 1.57079632679489661923;
+const double EPSILON = 1e-12;
 
 
 enum Orientation { CW, CCW, COLLINEAR };
 enum Orientation { CW, CCW, COLLINEAR };
 
 
@@ -53,7 +61,7 @@ enum Orientation { CW, CCW, COLLINEAR };
  *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
  *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
  * </pre>
  * </pre>
  */
  */
-Orientation Orient2d(Point& pa, Point& pb, Point& pc)
+Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
 {
 {
   double detleft = (pa.x - pc.x) * (pb.y - pc.y);
   double detleft = (pa.x - pc.x) * (pb.y - pc.y);
   double detright = (pa.y - pc.y) * (pb.x - pc.x);
   double detright = (pa.y - pc.y) * (pb.x - pc.x);
@@ -66,6 +74,7 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc)
   return CW;
   return CW;
 }
 }
 
 
+/*
 bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
 bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
 {
 {
   double pdx = pd.x;
   double pdx = pd.x;
@@ -97,7 +106,22 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
   return true;
   return true;
 }
 }
 
 
+*/
+
+bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point& pd)
+{
+  double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);
+  if (oadb >= -EPSILON) {
+    return false;
+  }
+
+  double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);
+  if (oadc <= EPSILON) {
+    return false;
+  }
+  return true;
 }
 }
 
 
-#endif
+}
 
 
+#endif

+ 2 - 3
contrib/poly2tri/poly2tri/poly2tri.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -35,5 +35,4 @@
 #include "common/shapes.h"
 #include "common/shapes.h"
 #include "sweep/cdt.h"
 #include "sweep/cdt.h"
 
 
-#endif
-
+#endif

+ 3 - 4
contrib/poly2tri/poly2tri/sweep/advancing_front.cc

@@ -39,7 +39,7 @@ AdvancingFront::AdvancingFront(Node& head, Node& tail)
   search_node_ = &head;
   search_node_ = &head;
 }
 }
 
 
-Node* AdvancingFront::LocateNode(const double& x)
+Node* AdvancingFront::LocateNode(double x)
 {
 {
   Node* node = search_node_;
   Node* node = search_node_;
 
 
@@ -61,7 +61,7 @@ Node* AdvancingFront::LocateNode(const double& x)
   return NULL;
   return NULL;
 }
 }
 
 
-Node* AdvancingFront::FindSearchNode(const double& x)
+Node* AdvancingFront::FindSearchNode(double x)
 {
 {
   (void)x; // suppress compiler warnings "unused parameter 'x'"
   (void)x; // suppress compiler warnings "unused parameter 'x'"
   // TODO: implement BST index
   // TODO: implement BST index
@@ -105,5 +105,4 @@ AdvancingFront::~AdvancingFront()
 {
 {
 }
 }
 
 
-}
-
+}

+ 3 - 3
contrib/poly2tri/poly2tri/sweep/advancing_front.h

@@ -74,7 +74,7 @@ Node* search();
 void set_search(Node* node);
 void set_search(Node* node);
 
 
 /// Locate insertion point along advancing front
 /// Locate insertion point along advancing front
-Node* LocateNode(const double& x);
+Node* LocateNode(double x);
 
 
 Node* LocatePoint(const Point* point);
 Node* LocatePoint(const Point* point);
 
 
@@ -82,7 +82,7 @@ private:
 
 
 Node* head_, *tail_, *search_node_;
 Node* head_, *tail_, *search_node_;
 
 
-Node* FindSearchNode(const double& x);
+Node* FindSearchNode(double x);
 };
 };
 
 
 inline Node* AdvancingFront::head()
 inline Node* AdvancingFront::head()
@@ -115,4 +115,4 @@ inline void AdvancingFront::set_search(Node* node)
 
 
 }
 }
 
 
-#endif
+#endif

+ 4 - 5
contrib/poly2tri/poly2tri/sweep/cdt.cc

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -32,13 +32,13 @@
 
 
 namespace p2t {
 namespace p2t {
 
 
-CDT::CDT(std::vector<Point*> polyline)
+CDT::CDT(const std::vector<Point*>& polyline)
 {
 {
   sweep_context_ = new SweepContext(polyline);
   sweep_context_ = new SweepContext(polyline);
   sweep_ = new Sweep;
   sweep_ = new Sweep;
 }
 }
 
 
-void CDT::AddHole(std::vector<Point*> polyline)
+void CDT::AddHole(const std::vector<Point*>& polyline)
 {
 {
   sweep_context_->AddHole(polyline);
   sweep_context_->AddHole(polyline);
 }
 }
@@ -68,5 +68,4 @@ CDT::~CDT()
   delete sweep_;
   delete sweep_;
 }
 }
 
 
-}
-
+}

+ 17 - 17
contrib/poly2tri/poly2tri/sweep/cdt.h

@@ -1,4 +1,4 @@
-/* 
+/*
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
  * http://code.google.com/p/poly2tri/
  * http://code.google.com/p/poly2tri/
  *
  *
@@ -28,7 +28,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
- 
+
 #ifndef CDT_H
 #ifndef CDT_H
 #define CDT_H
 #define CDT_H
 
 
@@ -37,11 +37,11 @@
 #include "sweep.h"
 #include "sweep.h"
 
 
 /**
 /**
- * 
+ *
  * @author Mason Green <[email protected]>
  * @author Mason Green <[email protected]>
  *
  *
  */
  */
- 
+
 namespace p2t {
 namespace p2t {
 
 
 class CDT
 class CDT
@@ -50,40 +50,40 @@ public:
 
 
   /**
   /**
    * Constructor - add polyline with non repeating points
    * Constructor - add polyline with non repeating points
-   * 
+   *
    * @param polyline
    * @param polyline
    */
    */
-  CDT(std::vector<Point*> polyline);
-  
+  CDT(const std::vector<Point*>& polyline);
+
    /**
    /**
    * Destructor - clean up memory
    * Destructor - clean up memory
    */
    */
   ~CDT();
   ~CDT();
-  
+
   /**
   /**
    * Add a hole
    * Add a hole
-   * 
+   *
    * @param polyline
    * @param polyline
    */
    */
-  void AddHole(std::vector<Point*> polyline);
-  
+  void AddHole(const std::vector<Point*>& polyline);
+
   /**
   /**
    * Add a steiner point
    * Add a steiner point
-   * 
+   *
    * @param point
    * @param point
    */
    */
   void AddPoint(Point* point);
   void AddPoint(Point* point);
-  
+
   /**
   /**
    * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
    * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
    */
    */
   void Triangulate();
   void Triangulate();
-  
+
   /**
   /**
    * Get CDT triangles
    * Get CDT triangles
    */
    */
   std::vector<Triangle*> GetTriangles();
   std::vector<Triangle*> GetTriangles();
-  
+
   /**
   /**
    * Get triangle map
    * Get triangle map
    */
    */
@@ -94,7 +94,7 @@ public:
   /**
   /**
    * Internals
    * Internals
    */
    */
-   
+
   SweepContext* sweep_context_;
   SweepContext* sweep_context_;
   Sweep* sweep_;
   Sweep* sweep_;
 
 
@@ -102,4 +102,4 @@ public:
 
 
 }
 }
 
 
-#endif
+#endif

+ 91 - 42
contrib/poly2tri/poly2tri/sweep/sweep.cc

@@ -49,7 +49,7 @@ void Sweep::Triangulate(SweepContext& tcx)
 
 
 void Sweep::SweepPoints(SweepContext& tcx)
 void Sweep::SweepPoints(SweepContext& tcx)
 {
 {
-  for (int i = 1; i < tcx.point_count(); i++) {
+  for (size_t i = 1; i < tcx.point_count(); i++) {
     Point& point = *tcx.GetPoint(i);
     Point& point = *tcx.GetPoint(i);
     Node* node = &PointEvent(tcx, point);
     Node* node = &PointEvent(tcx, point);
     for (unsigned int i = 0; i < point.edge_list.size(); i++) {
     for (unsigned int i = 0; i < point.edge_list.size(); i++) {
@@ -117,7 +117,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
 	  throw std::runtime_error("EdgeEvent - collinear points not supported");
 	  throw std::runtime_error("EdgeEvent - collinear points not supported");
     if( triangle->Contains(&eq, p1)) {
     if( triangle->Contains(&eq, p1)) {
       triangle->MarkConstrainedEdge(&eq, p1 );
       triangle->MarkConstrainedEdge(&eq, p1 );
-      // We are modifying the constraint maybe it would be better to 
+      // We are modifying the constraint maybe it would be better to
       // not change the given constraint and just keep a variable for the new constraint
       // not change the given constraint and just keep a variable for the new constraint
       tcx.edge_event.constrained_edge->q = p1;
       tcx.edge_event.constrained_edge->q = p1;
       triangle = &triangle->NeighborAcross(point);
       triangle = &triangle->NeighborAcross(point);
@@ -137,7 +137,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
 
 
     if( triangle->Contains(&eq, p2)) {
     if( triangle->Contains(&eq, p2)) {
       triangle->MarkConstrainedEdge(&eq, p2 );
       triangle->MarkConstrainedEdge(&eq, p2 );
-      // We are modifying the constraint maybe it would be better to 
+      // We are modifying the constraint maybe it would be better to
       // not change the given constraint and just keep a variable for the new constraint
       // not change the given constraint and just keep a variable for the new constraint
       tcx.edge_event.constrained_edge->q = p2;
       tcx.edge_event.constrained_edge->q = p2;
       triangle = &triangle->NeighborAcross(point);
       triangle = &triangle->NeighborAcross(point);
@@ -166,7 +166,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
 
 
 bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
 bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
 {
 {
-  int index = triangle.EdgeIndex(&ep, &eq);
+  const int index = triangle.EdgeIndex(&ep, &eq);
 
 
   if (index != -1) {
   if (index != -1) {
     triangle.MarkConstrainedEdge(index);
     triangle.MarkConstrainedEdge(index);
@@ -230,8 +230,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
   Node* node = n.next;
   Node* node = n.next;
 
 
   while (node->next) {
   while (node->next) {
-    double angle = HoleAngle(*node);
-    if (angle > PI_2 || angle < -PI_2) break;
+    // if HoleAngle exceeds 90 degrees then break.
+    if (LargeHole_DontFill(node)) break;
     Fill(tcx, *node);
     Fill(tcx, *node);
     node = node->next;
     node = node->next;
   }
   }
@@ -240,29 +240,81 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
   node = n.prev;
   node = n.prev;
 
 
   while (node->prev) {
   while (node->prev) {
-    double angle = HoleAngle(*node);
-    if (angle > PI_2 || angle < -PI_2) break;
+    // if HoleAngle exceeds 90 degrees then break.
+    if (LargeHole_DontFill(node)) break;
     Fill(tcx, *node);
     Fill(tcx, *node);
     node = node->prev;
     node = node->prev;
   }
   }
 
 
   // Fill right basins
   // Fill right basins
   if (n.next && n.next->next) {
   if (n.next && n.next->next) {
-    double angle = BasinAngle(n);
+    const double angle = BasinAngle(n);
     if (angle < PI_3div4) {
     if (angle < PI_3div4) {
       FillBasin(tcx, n);
       FillBasin(tcx, n);
     }
     }
   }
   }
 }
 }
 
 
-double Sweep::BasinAngle(Node& node)
+// True if HoleAngle exceeds 90 degrees.
+bool Sweep::LargeHole_DontFill(const Node* node) const {
+
+  const Node* nextNode = node->next;
+  const Node* prevNode = node->prev;
+  if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
+          return false;
+
+  // Check additional points on front.
+  const Node* next2Node = nextNode->next;
+  // "..Plus.." because only want angles on same side as point being added.
+  if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
+          return false;
+
+  const Node* prev2Node = prevNode->prev;
+  // "..Plus.." because only want angles on same side as point being added.
+  if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
+          return false;
+
+  return true;
+}
+
+bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const {
+  const double angle = Angle(origin, pa, pb);
+  return ((angle > PI_div2) || (angle < -PI_div2));
+}
+
+bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const {
+  const double angle = Angle(origin, pa, pb);
+  return (angle > PI_div2) || (angle < 0);
+}
+
+double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const {
+  /* Complex plane
+   * ab = cosA +i*sinA
+   * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+   * atan2(y,x) computes the principal value of the argument function
+   * applied to the complex number x+iy
+   * Where x = ax*bx + ay*by
+   *       y = ax*by - ay*bx
+   */
+  const double px = origin->x;
+  const double py = origin->y;
+  const double ax = pa->x- px;
+  const double ay = pa->y - py;
+  const double bx = pb->x - px;
+  const double by = pb->y - py;
+  const double x = ax * by - ay * bx;
+  const double y = ax * bx + ay * by;
+  return atan2(x, y);
+}
+
+double Sweep::BasinAngle(const Node& node) const
 {
 {
-  double ax = node.point->x - node.next->next->point->x;
-  double ay = node.point->y - node.next->next->point->y;
+  const double ax = node.point->x - node.next->next->point->x;
+  const double ay = node.point->y - node.next->next->point->y;
   return atan2(ay, ax);
   return atan2(ay, ax);
 }
 }
 
 
-double Sweep::HoleAngle(Node& node)
+double Sweep::HoleAngle(const Node& node) const
 {
 {
   /* Complex plane
   /* Complex plane
    * ab = cosA +i*sinA
    * ab = cosA +i*sinA
@@ -272,10 +324,10 @@ double Sweep::HoleAngle(Node& node)
    * Where x = ax*bx + ay*by
    * Where x = ax*bx + ay*by
    *       y = ax*by - ay*bx
    *       y = ax*by - ay*bx
    */
    */
-  double ax = node.next->point->x - node.point->x;
-  double ay = node.next->point->y - node.point->y;
-  double bx = node.prev->point->x - node.point->x;
-  double by = node.prev->point->y - node.point->y;
+  const double ax = node.next->point->x - node.point->x;
+  const double ay = node.next->point->y - node.point->y;
+  const double bx = node.prev->point->x - node.point->x;
+  const double by = node.prev->point->y - node.point->y;
   return atan2(ax * by - ay * bx, ax * bx + ay * by);
   return atan2(ax * by - ay * bx, ax * bx + ay * by);
 }
 }
 
 
@@ -340,43 +392,43 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
   return false;
   return false;
 }
 }
 
 
-bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd)
+bool Sweep::Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const
 {
 {
-  double adx = pa.x - pd.x;
-  double ady = pa.y - pd.y;
-  double bdx = pb.x - pd.x;
-  double bdy = pb.y - pd.y;
+  const double adx = pa.x - pd.x;
+  const double ady = pa.y - pd.y;
+  const double bdx = pb.x - pd.x;
+  const double bdy = pb.y - pd.y;
 
 
-  double adxbdy = adx * bdy;
-  double bdxady = bdx * ady;
-  double oabd = adxbdy - bdxady;
+  const double adxbdy = adx * bdy;
+  const double bdxady = bdx * ady;
+  const double oabd = adxbdy - bdxady;
 
 
   if (oabd <= 0)
   if (oabd <= 0)
     return false;
     return false;
 
 
-  double cdx = pc.x - pd.x;
-  double cdy = pc.y - pd.y;
+  const double cdx = pc.x - pd.x;
+  const double cdy = pc.y - pd.y;
 
 
-  double cdxady = cdx * ady;
-  double adxcdy = adx * cdy;
-  double ocad = cdxady - adxcdy;
+  const double cdxady = cdx * ady;
+  const double adxcdy = adx * cdy;
+  const double ocad = cdxady - adxcdy;
 
 
   if (ocad <= 0)
   if (ocad <= 0)
     return false;
     return false;
 
 
-  double bdxcdy = bdx * cdy;
-  double cdxbdy = cdx * bdy;
+  const double bdxcdy = bdx * cdy;
+  const double cdxbdy = cdx * bdy;
 
 
-  double alift = adx * adx + ady * ady;
-  double blift = bdx * bdx + bdy * bdy;
-  double clift = cdx * cdx + cdy * cdy;
+  const double alift = adx * adx + ady * ady;
+  const double blift = bdx * bdx + bdy * bdy;
+  const double clift = cdx * cdx + cdy * cdy;
 
 
-  double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
+  const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
 
 
   return det > 0;
   return det > 0;
 }
 }
 
 
-void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op)
+void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const
 {
 {
   Triangle* n1, *n2, *n3, *n4;
   Triangle* n1, *n2, *n3, *n4;
   n1 = t.NeighborCCW(p);
   n1 = t.NeighborCCW(p);
@@ -708,11 +760,8 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
   } else if (o2d == CCW) {
   } else if (o2d == CCW) {
     // Left
     // Left
     return *ot.PointCW(op);
     return *ot.PointCW(op);
-  } else{
-    //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
-	  // ASSIMP_CHANGE (aramis_acg)
-	  throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
   }
   }
+  throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
 }
 }
 
 
 void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
 void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
@@ -740,7 +789,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
 Sweep::~Sweep() {
 Sweep::~Sweep() {
 
 
     // Clean up memory
     // Clean up memory
-    for(unsigned int i = 0; i < nodes_.size(); i++) {
+    for(size_t i = 0; i < nodes_.size(); i++) {
         delete nodes_[i];
         delete nodes_[i];
     }
     }
 
 

+ 28 - 21
contrib/poly2tri/poly2tri/sweep/sweep.h

@@ -33,7 +33,7 @@
  * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
  * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
  * International Journal of Geographical Information Science
  * International Journal of Geographical Information Science
  *
  *
- * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, [email protected]
+ * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, [email protected]
  */
  */
 
 
 #ifndef SWEEP_H
 #ifndef SWEEP_H
@@ -49,17 +49,17 @@ struct Point;
 struct Edge;
 struct Edge;
 class Triangle;
 class Triangle;
 
 
-class Sweep 
+class Sweep
 {
 {
 public:
 public:
 
 
   /**
   /**
    * Triangulate
    * Triangulate
-   * 
+   *
    * @param tcx
    * @param tcx
    */
    */
   void Triangulate(SweepContext& tcx);
   void Triangulate(SweepContext& tcx);
-  
+
   /**
   /**
    * Destructor - clean up memory
    * Destructor - clean up memory
    */
    */
@@ -69,7 +69,7 @@ private:
 
 
   /**
   /**
    * Start sweeping the Y-sorted point set from bottom to top
    * Start sweeping the Y-sorted point set from bottom to top
-   * 
+   *
    * @param tcx
    * @param tcx
    */
    */
   void SweepPoints(SweepContext& tcx);
   void SweepPoints(SweepContext& tcx);
@@ -86,8 +86,8 @@ private:
   Node& PointEvent(SweepContext& tcx, Point& point);
   Node& PointEvent(SweepContext& tcx, Point& point);
 
 
    /**
    /**
-     * 
-     * 
+     *
+     *
      * @param tcx
      * @param tcx
      * @param edge
      * @param edge
      * @param node
      * @param node
@@ -98,7 +98,7 @@ private:
 
 
   /**
   /**
    * Creates a new front triangle and legalize it
    * Creates a new front triangle and legalize it
-   * 
+   *
    * @param tcx
    * @param tcx
    * @param point
    * @param point
    * @param node
    * @param node
@@ -142,7 +142,7 @@ private:
    * @param d - point opposite a
    * @param d - point opposite a
    * @return true if d is inside circle, false if on circle edge
    * @return true if d is inside circle, false if on circle edge
    */
    */
-  bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);
+  bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const;
 
 
   /**
   /**
    * Rotates a triangle pair one vertex CW
    * Rotates a triangle pair one vertex CW
@@ -158,7 +158,7 @@ private:
    *       n4                    n4
    *       n4                    n4
    * </pre>
    * </pre>
    */
    */
-  void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);
+  void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const;
 
 
   /**
   /**
    * Fills holes in the Advancing Front
    * Fills holes in the Advancing Front
@@ -169,17 +169,24 @@ private:
    */
    */
   void FillAdvancingFront(SweepContext& tcx, Node& n);
   void FillAdvancingFront(SweepContext& tcx, Node& n);
 
 
+  // Decision-making about when to Fill hole.
+  // Contributed by ToolmakerSteve2
+  bool LargeHole_DontFill(const Node* node) const;
+  bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
+  bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
+  double Angle(const Point* origin, const Point* pa, const Point* pb) const;
+
   /**
   /**
    *
    *
    * @param node - middle node
    * @param node - middle node
    * @return the angle between 3 front nodes
    * @return the angle between 3 front nodes
    */
    */
-  double HoleAngle(Node& node);
+  double HoleAngle(const Node& node) const;
 
 
   /**
   /**
    * The basin angle is decided against the horizontal line [1,0]
    * The basin angle is decided against the horizontal line [1,0]
    */
    */
-  double BasinAngle(Node& node);
+  double BasinAngle(const Node& node) const;
 
 
   /**
   /**
    * Fills a basin that has formed on the Advancing Front to the right
    * Fills a basin that has formed on the Advancing Front to the right
@@ -228,22 +235,22 @@ private:
   /**
   /**
    * After a flip we have two triangles and know that only one will still be
    * After a flip we have two triangles and know that only one will still be
    * intersecting the edge. So decide which to contiune with and legalize the other
    * intersecting the edge. So decide which to contiune with and legalize the other
-   * 
+   *
    * @param tcx
    * @param tcx
    * @param o - should be the result of an orient2d( eq, op, ep )
    * @param o - should be the result of an orient2d( eq, op, ep )
    * @param t - triangle 1
    * @param t - triangle 1
    * @param ot - triangle 2
    * @param ot - triangle 2
-   * @param p - a point shared by both triangles 
+   * @param p - a point shared by both triangles
    * @param op - another point shared by both triangles
    * @param op - another point shared by both triangles
    * @return returns the triangle still intersecting the edge
    * @return returns the triangle still intersecting the edge
    */
    */
   Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle&  t, Triangle& ot, Point& p, Point& op);
   Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle&  t, Triangle& ot, Point& p, Point& op);
 
 
    /**
    /**
-     * When we need to traverse from one triangle to the next we need 
+     * When we need to traverse from one triangle to the next we need
      * the point in current triangle that is the opposite point to the next
      * the point in current triangle that is the opposite point to the next
-     * triangle. 
-     * 
+     * triangle.
+     *
      * @param ep
      * @param ep
      * @param eq
      * @param eq
      * @param ot
      * @param ot
@@ -254,10 +261,10 @@ private:
 
 
    /**
    /**
      * Scan part of the FlipScan algorithm<br>
      * Scan part of the FlipScan algorithm<br>
-     * When a triangle pair isn't flippable we will scan for the next 
-     * point that is inside the flip triangle scan area. When found 
+     * When a triangle pair isn't flippable we will scan for the next
+     * point that is inside the flip triangle scan area. When found
      * we generate a new flipEdgeEvent
      * we generate a new flipEdgeEvent
-     * 
+     *
      * @param tcx
      * @param tcx
      * @param ep - last point on the edge we are traversing
      * @param ep - last point on the edge we are traversing
      * @param eq - first point on the edge we are traversing
      * @param eq - first point on the edge we are traversing
@@ -275,4 +282,4 @@ private:
 
 
 }
 }
 
 
-#endif
+#endif

+ 31 - 22
contrib/poly2tri/poly2tri/sweep/sweep_context.cc

@@ -34,17 +34,18 @@
 
 
 namespace p2t {
 namespace p2t {
 
 
-SweepContext::SweepContext(std::vector<Point*> polyline)
+SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyline),
+  front_(0),
+  head_(0),
+  tail_(0),
+  af_head_(0),
+  af_middle_(0),
+  af_tail_(0)
 {
 {
-  basin = Basin();
-  edge_event = EdgeEvent();
-
-  points_ = polyline;
-
   InitEdges(points_);
   InitEdges(points_);
 }
 }
 
 
-void SweepContext::AddHole(std::vector<Point*> polyline)
+void SweepContext::AddHole(const std::vector<Point*>& polyline)
 {
 {
   InitEdges(polyline);
   InitEdges(polyline);
   for(unsigned int i = 0; i < polyline.size(); i++) {
   for(unsigned int i = 0; i < polyline.size(); i++) {
@@ -56,12 +57,12 @@ void SweepContext::AddPoint(Point* point) {
   points_.push_back(point);
   points_.push_back(point);
 }
 }
 
 
-std::vector<Triangle*> SweepContext::GetTriangles()
+std::vector<Triangle*> &SweepContext::GetTriangles()
 {
 {
   return triangles_;
   return triangles_;
 }
 }
 
 
-std::list<Triangle*> SweepContext::GetMap()
+std::list<Triangle*> &SweepContext::GetMap()
 {
 {
   return map_;
   return map_;
 }
 }
@@ -94,16 +95,16 @@ void SweepContext::InitTriangulation()
 
 
 }
 }
 
 
-void SweepContext::InitEdges(std::vector<Point*> polyline)
+void SweepContext::InitEdges(const std::vector<Point*>& polyline)
 {
 {
-  int num_points = static_cast<int>(polyline.size());
-  for (int i = 0; i < num_points; i++) {
-    int j = i < num_points - 1 ? i + 1 : 0;
+  size_t num_points = polyline.size();
+  for (size_t i = 0; i < num_points; i++) {
+    size_t j = i < num_points - 1 ? i + 1 : 0;
     edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
     edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
   }
   }
 }
 }
 
 
-Point* SweepContext::GetPoint(const int& index)
+Point* SweepContext::GetPoint(size_t index)
 {
 {
   return points_[index];
   return points_[index];
 }
 }
@@ -113,13 +114,13 @@ void SweepContext::AddToMap(Triangle* triangle)
   map_.push_back(triangle);
   map_.push_back(triangle);
 }
 }
 
 
-Node& SweepContext::LocateNode(Point& point)
+Node& SweepContext::LocateNode(const Point& point)
 {
 {
   // TODO implement search tree
   // TODO implement search tree
   return *front_->LocateNode(point.x);
   return *front_->LocateNode(point.x);
 }
 }
 
 
-void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)
+void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
 {
 {
 
 
   (void) nodes;
   (void) nodes;
@@ -164,12 +165,20 @@ void SweepContext::RemoveFromMap(Triangle* triangle)
 
 
 void SweepContext::MeshClean(Triangle& triangle)
 void SweepContext::MeshClean(Triangle& triangle)
 {
 {
-  if (!triangle.IsInterior()) {
-    triangle.IsInterior(true);
-    triangles_.push_back(&triangle);
-    for (int i = 0; i < 3; i++) {
-      if (!triangle.constrained_edge[i])
-        MeshClean(*triangle.GetNeighbor(i));
+  std::vector<Triangle *> triangles;
+  triangles.push_back(&triangle);
+
+  while(!triangles.empty()){
+	Triangle *t = triangles.back();
+	triangles.pop_back();
+
+    if (t != NULL && !t->IsInterior()) {
+      t->IsInterior(true);
+      triangles_.push_back(t);
+      for (int i = 0; i < 3; i++) {
+        if (!t->constrained_edge[i])
+          triangles.push_back(t->GetNeighbor(i));
+      }
     }
     }
   }
   }
 }
 }

+ 17 - 17
contrib/poly2tri/poly2tri/sweep/sweep_context.h

@@ -52,47 +52,47 @@ class SweepContext {
 public:
 public:
 
 
 /// Constructor
 /// Constructor
-SweepContext(std::vector<Point*> polyline);
+SweepContext(const std::vector<Point*>& polyline);
 /// Destructor
 /// Destructor
 ~SweepContext();
 ~SweepContext();
 
 
 void set_head(Point* p1);
 void set_head(Point* p1);
 
 
-Point* head();
+Point* head() const;
 
 
 void set_tail(Point* p1);
 void set_tail(Point* p1);
 
 
-Point* tail();
+Point* tail() const;
 
 
-int point_count();
+size_t point_count() const;
 
 
-Node& LocateNode(Point& point);
+Node& LocateNode(const Point& point);
 
 
 void RemoveNode(Node* node);
 void RemoveNode(Node* node);
 
 
-void CreateAdvancingFront(std::vector<Node*> nodes);
+void CreateAdvancingFront(const std::vector<Node*>& nodes);
 
 
 /// Try to map a node to all sides of this triangle that don't have a neighbor
 /// Try to map a node to all sides of this triangle that don't have a neighbor
 void MapTriangleToNodes(Triangle& t);
 void MapTriangleToNodes(Triangle& t);
 
 
 void AddToMap(Triangle* triangle);
 void AddToMap(Triangle* triangle);
 
 
-Point* GetPoint(const int& index);
+Point* GetPoint(size_t index);
 
 
 Point* GetPoints();
 Point* GetPoints();
 
 
 void RemoveFromMap(Triangle* triangle);
 void RemoveFromMap(Triangle* triangle);
 
 
-void AddHole(std::vector<Point*> polyline);
+void AddHole(const std::vector<Point*>& polyline);
 
 
 void AddPoint(Point* point);
 void AddPoint(Point* point);
 
 
-AdvancingFront* front();
+AdvancingFront* front() const;
 
 
 void MeshClean(Triangle& triangle);
 void MeshClean(Triangle& triangle);
 
 
-std::vector<Triangle*> GetTriangles();
-std::list<Triangle*> GetMap();
+std::vector<Triangle*> &GetTriangles();
+std::list<Triangle*> &GetMap();
 
 
 std::vector<Edge*> edge_list;
 std::vector<Edge*> edge_list;
 
 
@@ -147,18 +147,18 @@ Point* tail_;
 Node *af_head_, *af_middle_, *af_tail_;
 Node *af_head_, *af_middle_, *af_tail_;
 
 
 void InitTriangulation();
 void InitTriangulation();
-void InitEdges(std::vector<Point*> polyline);
+void InitEdges(const std::vector<Point*>& polyline);
 
 
 };
 };
 
 
-inline AdvancingFront* SweepContext::front()
+inline AdvancingFront* SweepContext::front() const
 {
 {
   return front_;
   return front_;
 }
 }
 
 
-inline int SweepContext::point_count()
+inline size_t SweepContext::point_count() const
 {
 {
-  return static_cast<int>(points_.size());
+  return points_.size();
 }
 }
 
 
 inline void SweepContext::set_head(Point* p1)
 inline void SweepContext::set_head(Point* p1)
@@ -166,7 +166,7 @@ inline void SweepContext::set_head(Point* p1)
   head_ = p1;
   head_ = p1;
 }
 }
 
 
-inline Point* SweepContext::head()
+inline Point* SweepContext::head() const
 {
 {
   return head_;
   return head_;
 }
 }
@@ -176,7 +176,7 @@ inline void SweepContext::set_tail(Point* p1)
   tail_ = p1;
   tail_ = p1;
 }
 }
 
 
-inline Point* SweepContext::tail()
+inline Point* SweepContext::tail() const
 {
 {
   return tail_;
   return tail_;
 }
 }

+ 12 - 0
contrib/utf8cpp/doc/ReleaseNotes

@@ -0,0 +1,12 @@
+utf8 cpp library
+Release 2.3.4
+
+A minor bug fix release. Thanks to all who reported bugs. 
+
+Note: Version 2.3.3 contained a regression, and therefore was removed.
+
+Changes from version 2.3.2
+- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';'
+- Bug fix [36]: replace_invalid() only works with back_inserter
+
+Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes

+ 1789 - 0
contrib/utf8cpp/doc/utf8cpp.html

@@ -0,0 +1,1789 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <meta name="generator" content=
+    "HTML Tidy for Linux/x86 (vers 1st November 2002), see www.w3.org">
+    <meta name="description" content=
+    "A simple, portable and lightweigt C++ library for easy handling of UTF-8 encoded strings">
+    <meta name="keywords" content="UTF-8 C++ portable utf8 unicode generic templates">
+    <meta name="author" content="Nemanja Trifunovic">
+    <title>
+      UTF8-CPP: UTF-8 with C++ in a Portable Way
+    </title>
+    <style type="text/css">
+    <!--
+    span.return_value {
+      color: brown;
+    }
+    span.keyword {
+      color: blue;
+    }
+    span.preprocessor {
+      color: navy;
+    }
+    span.literal {
+      color: olive;
+    }
+    span.comment {
+      color: green;
+    }
+    code {
+      font-weight: bold; 
+    }
+    ul.toc {
+      list-style-type: none;
+    }
+    p.version {
+      font-size: small;
+      font-style: italic;
+    }
+    -->
+        </style>
+  </head>
+  <body>
+    <h1>
+      UTF8-CPP: UTF-8 with C++ in a Portable Way
+    </h1>
+    <p>
+      <a href="https://sourceforge.net/projects/utfcpp">The Sourceforge project page</a>
+    </p>
+    <div id="toc">
+      <h2>
+        Table of Contents
+      </h2>
+      <ul class="toc">
+        <li>
+          <a href="#introduction">Introduction</a>
+        </li>
+        <li>
+          <a href="#examples">Examples of Use</a>
+          <ul class="toc">
+            <li>
+              <a href=#introsample>Introductionary Sample </a>
+            </li>
+            <li>
+              <a href=#validfile>Checking if a file contains valid UTF-8 text</a>
+            </li>
+            <li>
+              <a href=#fixinvalid>Ensure that a string contains valid UTF-8 text</a>
+            </li>
+          </ul>
+        <li>
+          <a href="#reference">Reference</a>
+          <ul class="toc">
+            <li>
+              <a href="#funutf8">Functions From utf8 Namespace </a>
+            </li>
+            <li>
+              <a href="#typesutf8">Types From utf8 Namespace </a>
+            </li>
+            <li>
+              <a href="#fununchecked">Functions From utf8::unchecked Namespace </a>
+            </li>
+            <li>
+              <a href="#typesunchecked">Types From utf8::unchecked Namespace </a>
+            </li>
+          </ul>
+        </li>
+        <li>
+          <a href="#points">Points of Interest</a>
+        </li>
+        <li>
+          <a href="#links">Links</a>
+        </li>
+      </ul>
+    </div>
+    <h2 id="introduction">
+      Introduction
+    </h2>
+    <p>
+      Many C++ developers miss an easy and portable way of handling Unicode encoded
+      strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic.
+      C++11 provides some support for Unicode on core language and library level:
+      u8, u, and U character and string literals, char16_t and char32_t character types,
+      u16string and u32string library classes, and codecvt support for conversions 
+      between Unicode encoding forms.
+      In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply
+      roll out their own solutions.
+    </p>
+    <p>
+      In order to easily handle UTF-8 encoded Unicode strings, I came up with a small
+      generic library. For anybody used to work with STL algorithms and iterators, it should be
+      easy and natural to use. The code is freely available for any purpose - check out
+      the license at the beginning of the utf8.h file. If you run into
+      bugs or performance issues, please let me know and I'll do my best to address them.
+    </p>
+    <p>
+      The purpose of this article is not to offer an introduction to Unicode in general,
+      and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out
+      <a href="http://www.unicode.org/">Unicode Home Page</a> or some other source of
+      information for Unicode. Also, it is not my aim to advocate the use of UTF-8
+      encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from
+      C++, I am sure you have good reasons for it.
+    </p>
+    <h2 id="examples">
+      Examples of use
+    </h2>
+    <h3 id="introsample">
+      Introductionary Sample
+    </h3>
+    <p>
+      To illustrate the use of the library, let's start with a small but complete program 
+      that opens a file containing UTF-8 encoded text, reads it line by line, checks each line
+      for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
+    </p>
+<pre>
+<span class="preprocessor">#include &lt;fstream&gt;</span>
+<span class="preprocessor">#include &lt;iostream&gt;</span>
+<span class="preprocessor">#include &lt;string&gt;</span>
+<span class="preprocessor">#include &lt;vector&gt;</span>
+<span class="preprocessor">#include "utf8.h"</span>
+<span class="keyword">using namespace</span> std;
+<span class="keyword">int</span> main(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)
+{
+    <span class="keyword">if</span> (argc != <span class="literal">2</span>) {
+        cout &lt;&lt; <span class="literal">"\nUsage: docsample filename\n"</span>;
+        <span class="keyword">return</span> <span class="literal">0</span>;
+    }
+
+    <span class="keyword">const char</span>* test_file_path = argv[1];
+    <span class="comment">// Open the test file (contains UTF-8 encoded text)</span>
+    ifstream fs8(test_file_path);
+    <span class="keyword">if</span> (!fs8.is_open()) {
+    cout &lt;&lt; <span class=
+"literal">"Could not open "</span> &lt;&lt; test_file_path &lt;&lt; endl;
+    <span class="keyword">return</span> <span class="literal">0</span>;
+    }
+
+    <span class="keyword">unsigned</span> line_count = <span class="literal">1</span>;
+    string line;
+    <span class="comment">// Play with all the lines in the file</span>
+    <span class="keyword">while</span> (getline(fs8, line)) {
+       <span class="comment">// check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)</span>
+        string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+        <span class="keyword">if</span> (end_it != line.end()) {
+            cout &lt;&lt; <span class=
+"literal">"Invalid UTF-8 encoding detected at line "</span> &lt;&lt; line_count &lt;&lt; <span
+ class="literal">"\n"</span>;
+            cout &lt;&lt; <span class=
+"literal">"This part is fine: "</span> &lt;&lt; string(line.begin(), end_it) &lt;&lt; <span
+ class="literal">"\n"</span>;
+        }
+
+        <span class="comment">// Get the line length (at least for the valid part)</span>
+        <span class="keyword">int</span> length = utf8::distance(line.begin(), end_it);
+        cout &lt;&lt; <span class=
+"literal">"Length of line "</span> &lt;&lt; line_count &lt;&lt; <span class=
+"literal">" is "</span> &lt;&lt; length &lt;&lt;  <span class="literal">"\n"</span>;
+
+        <span class="comment">// Convert it to utf-16</span>
+        vector&lt;unsigned short&gt; utf16line;
+        utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+
+        <span class="comment">// And back to utf-8</span>
+        string utf8line; 
+        utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+
+        <span class="comment">// Confirm that the conversion went OK:</span>
+        <span class="keyword">if</span> (utf8line != string(line.begin(), end_it))
+            cout &lt;&lt; <span class=
+"literal">"Error in UTF-16 conversion at line: "</span> &lt;&lt; line_count &lt;&lt; <span
+ class="literal">"\n"</span>;        
+
+        line_count++;
+    }
+    <span class="keyword">return</span> <span class="literal">0</span>;
+}
+</pre>
+    <p>
+      In the previous code sample, for each line we performed
+      a detection of invalid UTF-8 sequences with <code>find_invalid</code>; the number
+      of characters (more precisely - the number of Unicode code points, including the end
+      of line and even BOM if there is one) in each line was
+      determined with a use of <code>utf8::distance</code>; finally, we have converted
+      each line to UTF-16 encoding with <code>utf8to16</code> and back to UTF-8 with
+      <code>utf16to8</code>.
+    </p>
+    <h3 id="validfile">Checking if a file contains valid UTF-8 text</h3>
+<p>
+Here is a function that checks whether the content of a file is valid UTF-8 encoded text without
+reading the content into the memory:
+</p>
+<pre>    
+<span class="keyword">bool</span> valid_utf8_file(i<span class="keyword">const char</span>* file_name)
+{
+    ifstream ifs(file_name);
+    <span class="keyword">if</span> (!ifs)
+        <span class="keyword">return false</span>; <span class="comment">// even better, throw here</span>
+
+    istreambuf_iterator&lt;<span class="keyword">char</span>&gt; it(ifs.rdbuf());
+    istreambuf_iterator&lt;<span class="keyword">char</span>&gt; eos;
+
+    <span class="keyword">return</span> utf8::is_valid(it, eos);
+}
+</pre>
+<p>
+Because the function <code>utf8::is_valid()</code> works with input iterators, we were able
+to pass an <code>istreambuf_iterator</code> to it and read the content of the file directly 
+without loading it to the memory first.</p>
+<p>
+Note that other functions that take input iterator arguments can be used in a similar way. For
+instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just 
+do something like:
+</p>
+<pre>
+    utf8::utf8to16(it, eos, back_inserter(u16string));
+</pre>
+    <h3 id="fixinvalid">Ensure that a string contains valid UTF-8 text</h3>
+<p>
+If we have some text that "probably" contains UTF-8 encoded text and we want to
+replace any invalid UTF-8 sequence with a replacement character, something like 
+the following function may be used:
+</p>
+<pre>
+<span class="keyword">void</span> fix_utf8_string(std::string&amp; str)
+{
+    std::string temp;
+    utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
+    str = temp;
+}
+</pre>
+<p>The function will replace any invalid UTF-8 sequence with a Unicode replacement character. 
+There is an overloaded function that enables the caller to supply their own replacement character.
+</p>
+    <h2 id="reference">
+      Reference
+    </h2>
+    <h3 id="funutf8">
+      Functions From utf8 Namespace
+    </h3>
+    <h4>
+      utf8::append
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
+      to a UTF-8 string.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator append(uint32_t cp, octet_iterator result);
+   
+</pre>
+    <p>
+	  <code>octet_iterator</code>: an output iterator.<br>
+      <code>cp</code>: a 32 bit integer representing a code point to append to the
+      sequence.<br>
+       <code>result</code>: an output iterator to the place in the sequence where to
+      append the code point.<br>
+       <span class="return_value">Return value</span>: an iterator pointing to the place
+      after the newly appended sequence.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
+class="literal">0</span>,<span class="literal">0</span>,<span class=
+"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
+<span class="keyword">unsigned char</span>* end = append(<span class=
+"literal">0x0448</span>, u);
+assert (u[<span class="literal">0</span>] == <span class=
+"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
+"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
+"literal">0</span>);
+</pre>
+    <p>
+      Note that <code>append</code> does not allocate any memory - it is the burden of
+      the caller to make sure there is enough memory allocated for the operation. To make
+      things more interesting, <code>append</code> can add anywhere between 1 and 4
+      octets to the sequence. In practice, you would most often want to use
+      <code>std::back_inserter</code> to ensure that the necessary memory is allocated.
+    </p>
+    <p>
+      In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
+      is thrown.
+    </p>
+    <h4>
+      utf8::next
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Given the iterator to the beginning of the UTF-8 sequence, it returns the code
+      point and moves the iterator to the next position.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+uint32_t next(octet_iterator&amp; it, octet_iterator end);
+   
+</pre>
+    <p>
+	  <code>octet_iterator</code>: an input iterator.<br>
+      <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+      encoded code point. After the function returns, it is incremented to point to the
+      beginning of the next code point.<br>
+       <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+      gets equal to <code>end</code> during the extraction of a code point, an
+      <code>utf8::not_enough_room</code> exception is thrown.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      processed UTF-8 code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = next(w, twochars + <span class="literal">6</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars + <span class="literal">3</span>);
+</pre>
+    <p>
+      This function is typically used to iterate through a UTF-8 encoded string.
+    </p>
+    <p>
+      In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+      thrown.
+    </p>
+    <h4>
+      utf8::peek_next
+    </h4>
+    <p class="version">
+    Available in version 2.1 and later.
+    </p>
+    <p>
+      Given the iterator to the beginning of the UTF-8 sequence, it returns the code
+      point for the following sequence without changing the value of the iterator. 
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+   
+</pre>
+    <p>
+	  <code>octet_iterator</code>: an input iterator.<br>
+      <code>it</code>: an iterator pointing to the beginning of an UTF-8
+      encoded code point.<br>
+       <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+      gets equal to <code>end</code> during the extraction of a code point, an
+      <code>utf8::not_enough_room</code> exception is thrown.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      processed UTF-8 code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = peek_next(w, twochars + <span class="literal">6</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+    <p>
+      In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+      thrown.
+    </p>
+    <h4>
+      utf8::prior
+    </h4>
+    <p class="version">
+    Available in version 1.02 and later.
+    </p>
+    <p>
+      Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it
+      decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+      code point and returns the 32 bits representation of the code point.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+uint32_t prior(octet_iterator&amp; it, octet_iterator start);
+   
+</pre>
+    <p>
+	  <code>octet_iterator</code>: a bidirectional iterator.<br>
+      <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+      After the function returns, it is decremented to point to the beginning of the
+      previous code point.<br>
+       <code>start</code>: an iterator to the beginning of the sequence where the search
+      for the beginning of a code point is performed. It is a
+      safety measure to prevent passing the beginning of the string in the search for a
+      UTF-8 lead octet.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      previous code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars + <span class=
+"literal">3</span>;
+<span class="keyword">int</span> cp = prior (w, twochars);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+    <p> 
+      This function has two purposes: one is two iterate backwards through a UTF-8
+      encoded string. Note that it is usually a better idea to iterate forward instead,
+      since <code>utf8::next</code> is faster. The second purpose is to find a beginning
+      of a UTF-8 sequence if we have a random position within a string. Note that in that
+      case <code>utf8::prior</code> may not detect an invalid UTF-8 sequence in some scenarios:
+      for instance if there are superfluous trail octets, it will just skip them.
+    </p> 
+    <p>
+      <code>it</code> will typically point to the beginning of
+      a code point, and <code>start</code> will point to the
+      beginning of the string to ensure we don't go backwards too far. <code>it</code> is
+      decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
+      beginning with that octet is decoded to a 32 bit representation and returned.
+    </p>
+    <p>
+      In case <code>start</code> is reached before a UTF-8 lead octet is hit, or if an
+      invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
+      exception is thrown.
+    </p>
+    <p>In case <code>start</code> equals <code>it</code>, a <code>not_enough_room</code>
+      exception is thrown.
+    <h4>
+      utf8::previous
+    </h4>
+    <p class="version">
+    Deprecated in version 1.02 and later.
+    </p>
+    <p>
+      Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+      decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+      code point and returns the 32 bits representation of the code point.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+uint32_t previous(octet_iterator&amp; it, octet_iterator pass_start);
+   
+</pre>
+    <p>
+	  <code>octet_iterator</code>: a random access iterator.<br>
+      <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+      After the function returns, it is decremented to point to the beginning of the
+      previous code point.<br>
+       <code>pass_start</code>: an iterator to the point in the sequence where the search
+      for the beginning of a code point is aborted if no result was reached. It is a
+      safety measure to prevent passing the beginning of the string in the search for a
+      UTF-8 lead octet.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      previous code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars + <span class=
+"literal">3</span>;
+<span class="keyword">int</span> cp = previous (w, twochars - <span class=
+"literal">1</span>);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+    <p>
+      <code>utf8::previous</code> is deprecated, and <code>utf8::prior</code> should
+      be used instead, although the existing code can continue using this function.
+      The problem is the parameter <code>pass_start</code> that points to the position
+      just before the beginning of the sequence. Standard containers don't have the 
+      concept of "pass start" and the function can not be used with their iterators.
+    </p>
+    <p>
+      <code>it</code> will typically point to the beginning of
+      a code point, and <code>pass_start</code> will point to the octet just before the
+      beginning of the string to ensure we don't go backwards too far. <code>it</code> is
+      decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
+      beginning with that octet is decoded to a 32 bit representation and returned.
+    </p>
+    <p>
+      In case <code>pass_start</code> is reached before a UTF-8 lead octet is hit, or if an
+      invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
+      exception is thrown
+    </p>
+    <h4>
+      utf8::advance
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Advances an iterator by the specified number of code points within an UTF-8
+      sequence.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename distance_type&gt; 
+<span class=
+"keyword">void</span> advance (octet_iterator&amp; it, distance_type n, octet_iterator end);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>distance_type</code>: an integral type convertible to <code>octet_iterator</code>'s difference type.<br>
+      <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+      encoded code point. After the function returns, it is incremented to point to the
+      nth following code point.<br>
+       <code>n</code>: a positive integer that shows how many code points we want to
+      advance.<br>
+       <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
+      gets equal to <code>end</code> during the extraction of a code point, an
+      <code>utf8::not_enough_room</code> exception is thrown.<br>
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">unsigned char</span>* w = twochars;
+advance (w, <span class="literal">2</span>, twochars + <span class="literal">6</span>);
+assert (w == twochars + <span class="literal">5</span>);
+</pre>
+    <p>
+      This function works only "forward". In case of a negative <code>n</code>, there is
+      no effect.
+    </p>
+    <p>
+      In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
+      is thrown.
+    </p>
+    <h4>
+      utf8::distance
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Given the iterators to two UTF-8 encoded code points in a seqence, returns the
+      number of code points between them.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+<span class=
+"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
+      <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
+      point in the sequence we are trying to determine the length. It can be the
+      beginning of a new code point, or not.<br>
+       <span class="return_value">Return value</span> the distance between the iterators,
+      in code points.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+size_t dist = utf8::distance(twochars, twochars + <span class="literal">5</span>);
+assert (dist == <span class="literal">2</span>);
+</pre>
+    <p>
+      This function is used to find the length (in code points) of a UTF-8 encoded
+      string. The reason it is called <em>distance</em>, rather than, say,
+      <em>length</em> is mainly because developers are used that <em>length</em> is an
+      O(1) function. Computing the length of an UTF-8 string is a linear operation, and
+      it looked better to model it after <code>std::distance</code> algorithm.
+    </p>
+    <p>
+      In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+      thrown. If <code>last</code> does not point to the past-of-end of a UTF-8 seqence,
+      a <code>utf8::not_enough_room</code> exception is thrown.
+    </p>
+    <h4>
+      utf8::utf16to8
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts a UTF-16 encoded string to UTF-8.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, <span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+   
+</pre>
+    <p>
+      <code>u16bit_iterator</code>: an input iterator.<br>
+      <code>octet_iterator</code>: an output iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
+      string to convert.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
+      string to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-8 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-8 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">unsigned short</span> utf16string[] = {<span class=
+"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
+"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
+"literal">0xdd1e</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf16to8(utf16string, utf16string + <span class=
+"literal">5</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">10</span>);    
+</pre>
+    <p>
+      In case of invalid UTF-16 sequence, a <code>utf8::invalid_utf16</code> exception is
+      thrown.
+    </p>
+    <h4>
+      utf8::utf8to16
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts an UTF-8 encoded string to UTF-16
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>u16bit_iterator</code>: an output iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+      string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
+      pass-the-end of the UTF-8 encoded string to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-16 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-16 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
+vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
+"literal">9</span>, back_inserter(utf16result));
+assert (utf16result.size() == <span class="literal">4</span>);
+assert (utf16result[<span class="literal">2</span>] == <span class=
+"literal">0xd834</span>);
+assert (utf16result[<span class="literal">3</span>] == <span class=
+"literal">0xdd1e</span>);
+</pre>
+    <p>
+      In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+      thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
+      <code>utf8::not_enough_room</code> exception is thrown.
+    </p>
+    <h4>
+      utf8::utf32to8
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts a UTF-32 encoded string to UTF-8.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an output iterator.<br>
+      <code>u32bit_iterator</code>: an input iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
+      string to convert.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
+      string to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-8 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-8 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">int</span> utf32string[] = {<span class=
+"literal">0x448</span>, <span class="literal">0x65E5</span>, <span class=
+"literal">0x10346</span>, <span class="literal">0</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf32to8(utf32string, utf32string + <span class=
+"literal">3</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">9</span>);
+</pre>
+    <p>
+      In case of invalid UTF-32 string, a <code>utf8::invalid_code_point</code> exception
+      is thrown.
+    </p>
+    <h4>
+      utf8::utf8to32
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts a UTF-8 encoded string to UTF-32.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> u32bit_iterator&gt;
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>u32bit_iterator</code>: an output iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+      string to convert.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
+      to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-32 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-32 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+vector&lt;<span class="keyword">int</span>&gt; utf32result;
+utf8to32(twochars, twochars + <span class=
+"literal">5</span>, back_inserter(utf32result));
+assert (utf32result.size() == <span class="literal">2</span>);
+</pre>
+    <p>
+      In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
+      thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
+      <code>utf8::not_enough_room</code> exception is thrown.
+    </p>
+    <h4>
+      utf8::find_invalid
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Detects an invalid sequence within a UTF-8 string.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+      test for validity.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
+      for validity.<br>
+       <span class="return_value">Return value</span>: an iterator pointing to the first
+      invalid octet in the UTF-8 string. In case none were found, equals
+      <code>end</code>.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span> utf_invalid[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
+<span class=
+"keyword">char</span>* invalid = find_invalid(utf_invalid, utf_invalid + <span class=
+"literal">6</span>);
+assert (invalid == utf_invalid + <span class="literal">5</span>);
+</pre>
+    <p>
+      This function is typically used to make sure a UTF-8 string is valid before
+      processing it with other functions. It is especially important to call it if before
+      doing any of the <em>unchecked</em> operations on it.
+    </p>
+    <h4>
+      utf8::is_valid
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Checks whether a sequence of octets is a valid UTF-8 string.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+<span class="keyword">bool</span> is_valid(octet_iterator start, octet_iterator end);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+      test for validity.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
+      for validity.<br>
+       <span class="return_value">Return value</span>: <code>true</code> if the sequence
+      is a valid UTF-8 string; <code>false</code> if not.
+    </p>
+    Example of use: 
+<pre>
+<span class="keyword">char</span> utf_invalid[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
+<span class="keyword">bool</span> bvalid = is_valid(utf_invalid, utf_invalid + <span
+class="literal">6</span>);
+assert (bvalid == false);
+</pre>
+    <p>
+      <code>is_valid</code> is a shorthand for <code>find_invalid(start, end) ==
+      end;</code>. You may want to use it to make sure that a byte seqence is a valid
+      UTF-8 string without the need to know where it fails if it is not valid.
+    </p>
+    <h4>
+      utf8::replace_invalid
+    </h4>
+    <p class="version">
+    Available in version 2.0 and later.
+    </p>
+    <p>
+      Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> output_iterator&gt;
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> output_iterator&gt;
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+   
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>output_iterator</code>: an output iterator.<br>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
+      look for invalid UTF-8 sequences.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to look
+      for invalid UTF-8 sequences.<br>
+       <code>out</code>: An output iterator to the range where the result of replacement
+      is stored.<br>
+       <code>replacement</code>: A Unicode code point for the replacement marker. The
+      version without this parameter assumes the value <code>0xfffd</code><br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the UTF-8 string with replaced invalid sequences.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span> invalid_sequence[] = <span class=
+"literal">"a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z"</span>;
+vector&lt;<span class="keyword">char</span>&gt; replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), <span
+ class="literal">'?'</span>);
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+<span class="keyword">char</span>* fixed_invalid_sequence = <span class=
+"literal">"a????z"</span>;
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+</pre>
+    <p>
+      <code>replace_invalid</code> does not perform in-place replacement of invalid
+      sequences. Rather, it produces a copy of the original string with the invalid
+      sequences replaced with a replacement marker. Therefore, <code>out</code> must not
+      be in the <code>[start, end]</code> range.
+    </p>
+    <p>
+      If <code>end</code> does not point to the past-of-end of a UTF-8 sequence, a
+      <code>utf8::not_enough_room</code> exception is thrown.
+    </p>
+    <h4>
+      utf8::starts_with_bom
+    </h4>
+    <p class="version">
+    Available in version 2.3 and later. Relaces deprecated <code>is_bom()</code> function.
+    </p>
+    <p>
+      Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+<span class="keyword">bool</span> starts_with_bom (octet_iterator it, octet_iterator end);
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>it</code>: beginning of the octet sequence to check<br>
+      <code>end</code>: pass-end of the sequence to check<br>
+       <span class="return_value">Return value</span>: <code>true</code> if the sequence
+      starts with a UTF-8 byte order mark; <code>false</code> if not.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
+"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
+"literal">0xbf</span>};
+<span class="keyword">bool</span> bbom = starts_with_bom(byte_order_mark, byte_order_mark + <span class="keyword">sizeof</span>(byte_order_mark));
+assert (bbom == <span class="literal">true</span>);
+</pre>
+    <p>
+      The typical use of this function is to check the first three bytes of a file. If
+      they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
+      encoded text.
+    </p>
+    <h4>
+      utf8::is_bom
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later. Deprecated in version 2.3. <code>starts_with_bom()</code> should be used
+    instead.
+    </p>
+    <p>
+      Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM)
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt; 
+<span class="keyword">bool</span> is_bom (octet_iterator it); <span class="comment"> // Deprecated</span>
+</pre>
+    <p>
+      <code>octet_iterator</code>: an input iterator.<br>
+      <code>it</code>: beginning of the 3-octet sequence to check<br>
+       <span class="return_value">Return value</span>: <code>true</code> if the sequence
+      is UTF-8 byte order mark; <code>false</code> if not.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
+"literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
+"literal">0xbf</span>};
+<span class="keyword">bool</span> bbom = is_bom(byte_order_mark);
+assert (bbom == <span class="literal">true</span>);
+</pre>
+    <p>
+      The typical use of this function is to check the first three bytes of a file. If
+      they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
+      encoded text.
+    </p>
+    <p>
+      If a sequence is 
+      shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated
+      in favor of <code>starts_with_bom()</code>that takes the end of sequence as an argument.
+    </p>
+    <h3 id="typesutf8">
+      Types From utf8 Namespace
+    </h3>
+    <h4>utf8::exception
+    </h4>
+    <p class="version">
+    Available in version 2.3 and later.
+    </p>
+    <p>
+    Base class for the exceptions thrown by UTF CPP library functions.
+    </p>
+<pre>
+<span class="keyword">class</span> exception : <span class="keyword">public</span> std::exception {};
+</pre>
+    <p>
+    Example of use:
+    </p>
+<pre>
+<span class="keyword">try</span> {
+  code_that_uses_utf_cpp_library();
+}
+<span class="keyword">catch</span>(<span class="keyword">const</span> utf8::exception&amp; utfcpp_ex) {
+  cerr &lt;&lt; utfcpp_ex.what();
+}
+</pre>
+    
+    <h4>utf8::invalid_code_point
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+    Thrown by UTF8 CPP functions such as <code>advance</code> and <code>next</code> if an UTF-8 sequence represents and invalid code point.
+    </p>
+
+<pre>
+<span class="keyword">class</span> invalid_code_point : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>: 
+    uint32_t code_point() <span class="keyword">const</span>;
+};
+
+</pre>
+    <p>
+    Member function <code>code_point()</code> can be used to determine the invalid code point that
+    caused the exception to be thrown.
+    </p>
+    <h4>utf8::invalid_utf8
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+    Thrown by UTF8 CPP functions such as <code>next</code> and <code>prior</code> if an invalid UTF-8 sequence
+    is detected during decoding.
+    </p>
+
+<pre>
+<span class="keyword">class</span> invalid_utf8 : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>: 
+    uint8_t utf8_octet() <span class="keyword">const</span>;
+};
+</pre>
+
+    <p>
+    Member function <code>utf8_octet()</code> can be used to determine the beginning of the byte 
+    sequence that caused the exception to be thrown.
+    </p>
+</pre>
+    <h4>utf8::invalid_utf16
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+    Thrown by UTF8 CPP function <code>utf16to8</code> if an invalid UTF-16 sequence
+    is detected during decoding.
+    </p>
+
+<pre>
+<span class="keyword">class</span> invalid_utf16 : <span class="keyword">public</span> exception {
+<span class="keyword">public</span>: 
+    uint16_t utf16_word() <span class="keyword">const</span>;
+};
+</pre>
+
+    <p>
+    Member function <code>utf16_word()</code> can be used to determine the UTF-16 code unit 
+    that caused the exception to be thrown.
+    </p>
+    <h4>utf8::not_enough_room
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+    Thrown by UTF8 CPP functions such as <code>next</code> if the end of the decoded UTF-8 sequence
+    was reached before the code point was decoded.
+    </p>
+
+<pre>
+<span class="keyword">class</span> not_enough_room : <span class="keyword">public</span> exception {};
+</pre>
+    <h4>
+      utf8::iterator
+    </h4>
+    <p class="version">
+    Available in version 2.0 and later.
+    </p>
+    <p>
+      Adapts the underlying octet iterator to iterate over the sequence of code points,
+      rather than raw octets.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
+<span class="keyword">class</span> iterator;
+</pre>
+    
+    <h5>Member functions</h5>
+      <dl>
+      <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
+      constructed with its default constructor.
+      <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it, 
+                         const octet_iterator&amp; range_start,
+                         const octet_iterator&amp; range_end);</code> <dd> a constructor 
+      that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
+      and sets the range in which the iterator is considered valid.
+      <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the 
+      underlying <code>octet_iterator</code>.
+      <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
+      the underlying <code>octet_iterator</code> is pointing to and returns the code point.
+      <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
+      <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+      if the two underlaying iterators are equal.
+      <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
+      <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+      if the two underlaying iterators are not equal.
+      <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
+      the iterator to the next UTF-8 encoded code point.
+      <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
+      the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+      <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
+      the iterator to the previous UTF-8 encoded code point.
+      <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
+      the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+      </dl>
+      <p>
+      Example of use:
+      </p>
+<pre>
+<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; it(threechars, threechars, threechars + <span class="literal">9</span>);
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; it2 = it;
+assert (it2 == it);
+assert (*it == <span class="literal">0x10346</span>);
+assert (*(++it) == <span class="literal">0x65e5</span>);
+assert ((*it++) == <span class="literal">0x65e5</span>);
+assert (*it == <span class="literal">0x0448</span>);
+assert (it != it2);
+utf8::iterator&lt;<span class="keyword">char</span>*&gt; endit (threechars + <span class="literal">9</span>, threechars, threechars + <span class="literal">9</span>);  
+assert (++it == endit);
+assert (*(--it) == <span class="literal">0x0448</span>);
+assert ((*it--) == <span class="literal">0x0448</span>);
+assert (*it == <span class="literal">0x65e5</span>);
+assert (--it == utf8::iterator&lt;<span class="keyword">char</span>*&gt;(threechars, threechars, threechars + <span class="literal">9</span>));
+assert (*it == <span class="literal">0x10346</span>);
+</pre>
+      <p>
+      The purpose of <code>utf8::iterator</code> adapter is to enable easy iteration as well as the use of STL
+      algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of 
+      <code>utf8::next()</code> and <code>utf8::prior()</code> functions. 
+      </p>
+      <p>
+      Note that <code>utf8::iterator</code> adapter is a checked iterator. It operates on the range specified in
+      the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators
+      require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically,
+      the range will be determined by sequence container functions <code>begin</code> and <code>end</code>, i.e.:
+      </p>
+<pre>
+std::string s = <span class="literal">"example"</span>;
+utf8::iterator i (s.begin(), s.begin(), s.end());
+</pre>
+    <h3 id="fununchecked">
+      Functions From utf8::unchecked Namespace
+    </h3>
+    <h4>
+      utf8::unchecked::append
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
+      to a UTF-8 string.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator append(uint32_t cp, octet_iterator result);
+   
+</pre>
+    <p>
+      <code>cp</code>: A 32 bit integer representing a code point to append to the
+      sequence.<br>
+       <code>result</code>: An output iterator to the place in the sequence where to
+      append the code point.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the newly appended sequence.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
+class="literal">0</span>,<span class="literal">0</span>,<span class=
+"literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
+<span class="keyword">unsigned char</span>* end = unchecked::append(<span class=
+"literal">0x0448</span>, u);
+assert (u[<span class="literal">0</span>] == <span class=
+"literal">0xd1</span> &amp;&amp; u[<span class="literal">1</span>] == <span class=
+"literal">0x88</span> &amp;&amp; u[<span class="literal">2</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">3</span>] == <span class=
+"literal">0</span> &amp;&amp; u[<span class="literal">4</span>] == <span class=
+"literal">0</span>);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::append</code>. It does not
+      check for validity of the supplied code point, and may produce an invalid UTF-8
+      sequence.
+    </p>
+    <h4>
+      utf8::unchecked::next
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Given the iterator to the beginning of a UTF-8 sequence, it returns the code point
+      and moves the iterator to the next position.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t next(octet_iterator&amp; it);
+   
+</pre>
+    <p>
+      <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+      encoded code point. After the function returns, it is incremented to point to the
+      beginning of the next code point.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      processed UTF-8 code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = unchecked::next(w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars + <span class="literal">3</span>);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::next</code>. It does not
+      check for validity of the supplied UTF-8 sequence.
+    </p>
+    <h4>
+      utf8::unchecked::peek_next
+    </h4>
+    <p class="version">
+    Available in version 2.1 and later.
+    </p>
+    <p>
+      Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t peek_next(octet_iterator it);
+   
+</pre>
+    <p>
+      <code>it</code>: an iterator pointing to the beginning of an UTF-8
+      encoded code point.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      processed UTF-8 code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+<span class="keyword">int</span> cp = unchecked::peek_next(w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::peek_next</code>. It does not
+      check for validity of the supplied UTF-8 sequence.
+    </p>
+    <h4>
+      utf8::unchecked::prior
+    </h4>
+    <p class="version">
+    Available in version 1.02 and later.
+    </p>
+    <p>
+      Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+      decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+      code point and returns the 32 bits representation of the code point.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t prior(octet_iterator&amp; it);
+   
+</pre>
+    <p>
+      <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+      After the function returns, it is decremented to point to the beginning of the
+      previous code point.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      previous code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
+<span class="keyword">int</span> cp = unchecked::prior (w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::prior</code>. It does not
+      check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+    </p>
+    <h4>
+      utf8::unchecked::previous (deprecated, see utf8::unchecked::prior)
+    </h4>
+    <p class="version">
+    Deprecated in version 1.02 and later.
+    </p>
+    <p>
+      Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
+      decreases the iterator until it hits the beginning of the previous UTF-8 encoded
+      code point and returns the 32 bits representation of the code point.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+uint32_t previous(octet_iterator&amp; it);
+   
+</pre>
+    <p>
+      <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
+      After the function returns, it is decremented to point to the beginning of the
+      previous code point.<br>
+       <span class="return_value">Return value</span>: the 32 bit representation of the
+      previous code point.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
+<span class="keyword">int</span> cp = unchecked::previous (w);
+assert (cp == <span class="literal">0x65e5</span>);
+assert (w == twochars);
+</pre>
+    <p>
+     The reason this function is deprecated is just the consistency with the "checked"
+     versions, where <code>prior</code> should be used instead of <code>previous</code>.
+     In fact, <code>unchecked::previous</code> behaves exactly the same as <code>
+     unchecked::prior</code>
+    </p>
+    <p>
+      This is a faster but less safe version of <code>utf8::previous</code>. It does not
+      check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+    </p>
+    <h4>
+      utf8::unchecked::advance
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Advances an iterator by the specified number of code points within an UTF-8
+      sequence.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename distance_type&gt;
+<span class="keyword">void</span> advance (octet_iterator&amp; it, distance_type n);
+   
+</pre>
+    <p>
+      <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
+      encoded code point. After the function returns, it is incremented to point to the
+      nth following code point.<br>
+       <code>n</code>: a positive integer that shows how many code points we want to
+      advance.<br>
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+<span class="keyword">char</span>* w = twochars;
+unchecked::advance (w, <span class="literal">2</span>);
+assert (w == twochars + <span class="literal">5</span>);
+</pre>
+    <p>
+      This function works only "forward". In case of a negative <code>n</code>, there is
+      no effect.
+    </p>
+    <p>
+      This is a faster but less safe version of <code>utf8::advance</code>. It does not
+      check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+    </p>
+    <h4>
+      utf8::unchecked::distance
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Given the iterators to two UTF-8 encoded code points in a seqence, returns the
+      number of code points between them.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator&gt;
+<span class=
+"keyword">typename</span> std::iterator_traits&lt;octet_iterator&gt;::difference_type distance (octet_iterator first, octet_iterator last);
+</pre>
+    <p>
+      <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
+       <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
+      point in the sequence we are trying to determine the length. It can be the
+      beginning of a new code point, or not.<br>
+       <span class="return_value">Return value</span> the distance between the iterators,
+      in code points.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+size_t dist = utf8::unchecked::distance(twochars, twochars + <span class=
+"literal">5</span>);
+assert (dist == <span class="literal">2</span>);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::distance</code>. It does not
+      check for validity of the supplied UTF-8 sequence.
+    </p>
+    <h4>
+      utf8::unchecked::utf16to8
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts a UTF-16 encoded string to UTF-8.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, <span class=
+"keyword">typename</span> octet_iterator&gt;
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+   
+</pre>
+    <p>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
+      string to convert.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
+      string to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-8 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-8 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">unsigned short</span> utf16string[] = {<span class=
+"literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
+"literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
+"literal">0xdd1e</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+unchecked::utf16to8(utf16string, utf16string + <span class=
+"literal">5</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">10</span>);    
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::utf16to8</code>. It does not
+      check for validity of the supplied UTF-16 sequence.
+    </p>
+    <h4>
+      utf8::unchecked::utf8to16
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts an UTF-8 encoded string to UTF-16
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> u16bit_iterator, typename octet_iterator&gt;
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+   
+</pre>
+    <p>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+      string to convert. &lt; br /&gt; <code>end</code>: an iterator pointing to
+      pass-the-end of the UTF-8 encoded string to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-16 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-16 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span> utf8_with_surrogates[] = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
+vector &lt;<span class="keyword">unsigned short</span>&gt; utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
+"literal">9</span>, back_inserter(utf16result));
+assert (utf16result.size() == <span class="literal">4</span>);
+assert (utf16result[<span class="literal">2</span>] == <span class=
+"literal">0xd834</span>);
+assert (utf16result[<span class="literal">3</span>] == <span class=
+"literal">0xdd1e</span>);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::utf8to16</code>. It does not
+      check for validity of the supplied UTF-8 sequence.
+    </p>
+    <h4>
+      utf8::unchecked::utf32to8
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts a UTF-32 encoded string to UTF-8.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, <span class=
+"keyword">typename</span> u32bit_iterator&gt;
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+   
+</pre>
+    <p>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
+      string to convert.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
+      string to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-8 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-8 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">int</span> utf32string[] = {<span class=
+"literal">0x448</span>, <span class="literal">0x65e5</span>, <span class=
+"literal">0x10346</span>, <span class="literal">0</span>};
+vector&lt;<span class="keyword">unsigned char</span>&gt; utf8result;
+utf32to8(utf32string, utf32string + <span class=
+"literal">3</span>, back_inserter(utf8result));
+assert (utf8result.size() == <span class="literal">9</span>);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::utf32to8</code>. It does not
+      check for validity of the supplied UTF-32 sequence.
+    </p>
+    <h4>
+      utf8::unchecked::utf8to32
+    </h4>
+    <p class="version">
+    Available in version 1.0 and later.
+    </p>
+    <p>
+      Converts a UTF-8 encoded string to UTF-32.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class=
+"keyword">typename</span> octet_iterator, typename u32bit_iterator&gt;
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+   
+</pre>
+    <p>
+      <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
+      string to convert.<br>
+       <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
+      to convert.<br>
+       <code>result</code>: an output iterator to the place in the UTF-32 string where to
+      append the result of conversion.<br>
+       <span class="return_value">Return value</span>: An iterator pointing to the place
+      after the appended UTF-32 string.
+    </p>
+    <p>
+      Example of use:
+    </p>
+<pre>
+<span class="keyword">char</span>* twochars = <span class=
+"literal">"\xe6\x97\xa5\xd1\x88"</span>;
+vector&lt;<span class="keyword">int</span>&gt; utf32result;
+unchecked::utf8to32(twochars, twochars + <span class=
+"literal">5</span>, back_inserter(utf32result));
+assert (utf32result.size() == <span class="literal">2</span>);
+</pre>
+    <p>
+      This is a faster but less safe version of <code>utf8::utf8to32</code>. It does not
+      check for validity of the supplied UTF-8 sequence.
+    </p>
+    <h3 id="typesunchecked">
+      Types From utf8::unchecked Namespace
+    </h3>
+    <h4>
+      utf8::iterator
+    </h4>
+    <p class="version">
+    Available in version 2.0 and later.
+    </p>
+    <p>
+      Adapts the underlying octet iterator to iterate over the sequence of code points,
+      rather than raw octets.
+    </p>
+<pre>
+<span class="keyword">template</span> &lt;<span class="keyword">typename</span> octet_iterator&gt;
+<span class="keyword">class</span> iterator;
+</pre>
+    
+    <h5>Member functions</h5>
+      <dl>
+      <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
+      constructed with its default constructor.
+      <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator&amp; octet_it); 
+                         </code> <dd> a constructor 
+      that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
+      <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the 
+      underlying <code>octet_iterator</code>.
+      <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
+      the underlying <code>octet_iterator</code> is pointing to and returns the code point.
+      <dt><code><span class="keyword">bool operator</span> == (const iterator&amp; rhs)
+      <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+      if the two underlaying iterators are equal.
+      <dt><code><span class="keyword">bool operator</span> != (const iterator&amp; rhs)
+      <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
+      if the two underlaying iterators are not equal.
+      <dt><code>iterator&amp; <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
+      the iterator to the next UTF-8 encoded code point.
+      <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
+      the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+      <dt><code>iterator&amp; <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
+      the iterator to the previous UTF-8 encoded code point.
+      <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
+      the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+      </dl>
+      <p>
+      Example of use:
+      </p>
+<pre>
+<span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
+utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it(threechars);
+utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == <span class="literal">0x10346</span>);
+assert (*(++un_it) == <span class="literal">0x65e5</span>);
+assert ((*un_it++) == <span class="literal">0x65e5</span>);
+assert (*un_it == <span class="literal">0x0448</span>);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator&lt;<span class="keyword">char</span>*&gt; un_endit (threechars + <span class="literal">9</span>);  
+assert (++un_it == un_endit);
+assert (*(--un_it) == <span class="literal">0x0448</span>);
+assert ((*un_it--) == <span class="literal">0x0448</span>);
+assert (*un_it == <span class="literal">0x65e5</span>);
+assert (--un_it == utf8::unchecked::iterator&lt;<span class="keyword">char</span>*&gt;(threechars));
+assert (*un_it == <span class="literal">0x10346</span>);
+</pre>
+      <p>
+      This is an unchecked version of <code>utf8::iterator</code>. It is faster in many cases, but offers
+      no validity or range checks.
+      </p>
+    <h2 id="points">
+      Points of interest
+    </h2>
+    <h4>
+      Design goals and decisions
+    </h4>
+    <p>
+      The library was designed to be:
+    </p>
+    <ol>
+      <li>
+        Generic: for better or worse, there are many C++ string classes out there, and
+        the library should work with as many of them as possible.
+      </li>
+      <li>
+        Portable: the library should be portable both accross different platforms and
+        compilers. The only non-portable code is a small section that declares unsigned
+        integers of different sizes: three typedefs. They can be changed by the users of
+        the library if they don't match their platform. The default setting should work
+        for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives.
+      </li>
+      <li>
+        Lightweight: follow the "pay only for what you use" guideline.
+      </li>
+      <li>
+        Unintrusive: avoid forcing any particular design or even programming style on the
+        user. This is a library, not a framework.
+      </li>
+    </ol>
+    <h4>
+      Alternatives
+    </h4>
+    <p>
+      In case you want to look into other means of working with UTF-8 strings from C++,
+      here is the list of solutions I am aware of:
+    </p>
+    <ol>
+      <li>
+        <a href="http://icu.sourceforge.net/">ICU Library</a>. It is very powerful,
+        complete, feature-rich, mature, and widely used. Also big, intrusive,
+        non-generic, and doesn't play well with the Standard Library. I definitelly
+        recommend looking at ICU even if you don't plan to use it.
+      </li>
+      <li>
+        C++11 language and library features. Still far from complete, and not widely
+        supported by compiler vendors. 
+      </li>
+      <li>
+        <a href=
+        "http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html">Glib::ustring</a>.
+        A class specifically made to work with UTF-8 strings, and also feel like
+        <code>std::string</code>. If you prefer to have yet another string class in your
+        code, it may be worth a look. Be aware of the licensing issues, though.
+      </li>
+      <li>
+        Platform dependent solutions: Windows and POSIX have functions to convert strings
+        from one encoding to another. That is only a subset of what my library offers,
+        but if that is all you need it may be good enough.
+      </li>
+    </ol>
+    <h2 id="links">
+      Links
+    </h2>
+    <ol>
+      <li>
+        <a href="http://www.unicode.org/">The Unicode Consortium</a>.
+      </li>
+      <li>
+        <a href="http://icu.sourceforge.net/">ICU Library</a>.
+      </li>
+      <li>
+        <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8 at Wikipedia</a>
+      </li>
+      <li>
+        <a href="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ for
+        Unix/Linux</a>
+      </li>
+    </ol>
+  </body>
+</html>

+ 34 - 0
contrib/utf8cpp/source/utf8.h

@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard

+ 327 - 0
contrib/utf8cpp/source/utf8/checked.h

@@ -0,0 +1,327 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+    // Base for the exceptions that may be thrown from the library
+    class exception : public ::std::exception {
+    };
+
+    // Exceptions that may be thrown from the library functions.
+    class invalid_code_point : public exception {
+        uint32_t cp;
+    public:
+        invalid_code_point(uint32_t cp) : cp(cp) {}
+        virtual const char* what() const throw() { return "Invalid code point"; }
+        uint32_t code_point() const {return cp;}
+    };
+
+    class invalid_utf8 : public exception {
+        uint8_t u8;
+    public:
+        invalid_utf8 (uint8_t u) : u8(u) {}
+        virtual const char* what() const throw() { return "Invalid UTF-8"; }
+        uint8_t utf8_octet() const {return u8;}
+    };
+
+    class invalid_utf16 : public exception {
+        uint16_t u16;
+    public:
+        invalid_utf16 (uint16_t u) : u16(u) {}
+        virtual const char* what() const throw() { return "Invalid UTF-16"; }
+        uint16_t utf16_word() const {return u16;}
+    };
+
+    class not_enough_room : public exception {
+    public:
+        virtual const char* what() const throw() { return "Not enough space"; }
+    };
+
+    /// The library API - functions intended to be called by the users
+
+    template <typename octet_iterator>
+    octet_iterator append(uint32_t cp, octet_iterator result)
+    {
+        if (!utf8::internal::is_code_point_valid(cp))
+            throw invalid_code_point(cp);
+
+        if (cp < 0x80)                        // one octet
+            *(result++) = static_cast<uint8_t>(cp);
+        else if (cp < 0x800) {                // two octets
+            *(result++) = static_cast<uint8_t>((cp >> 6)            | 0xc0);
+            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80);
+        }
+        else if (cp < 0x10000) {              // three octets
+            *(result++) = static_cast<uint8_t>((cp >> 12)           | 0xe0);
+            *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f)   | 0x80);
+            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80);
+        }
+        else {                                // four octets
+            *(result++) = static_cast<uint8_t>((cp >> 18)           | 0xf0);
+            *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)  | 0x80);
+            *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f)   | 0x80);
+            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80);
+        }
+        return result;
+    }
+
+    template <typename octet_iterator, typename output_iterator>
+    output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+    {
+        while (start != end) {
+            octet_iterator sequence_start = start;
+            internal::utf_error err_code = utf8::internal::validate_next(start, end);
+            switch (err_code) {
+                case internal::UTF8_OK :
+                    for (octet_iterator it = sequence_start; it != start; ++it)
+                        *out++ = *it;
+                    break;
+                case internal::NOT_ENOUGH_ROOM:
+                    throw not_enough_room();
+                case internal::INVALID_LEAD:
+                    out = utf8::append (replacement, out);
+                    ++start;
+                    break;
+                case internal::INCOMPLETE_SEQUENCE:
+                case internal::OVERLONG_SEQUENCE:
+                case internal::INVALID_CODE_POINT:
+                    out = utf8::append (replacement, out);
+                    ++start;
+                    // just one replacement mark for the sequence
+                    while (start != end && utf8::internal::is_trail(*start))
+                        ++start;
+                    break;
+            }
+        }
+        return out;
+    }
+
+    template <typename octet_iterator, typename output_iterator>
+    inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+    {
+        static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+        return utf8::replace_invalid(start, end, out, replacement_marker);
+    }
+
+    template <typename octet_iterator>
+    uint32_t next(octet_iterator& it, octet_iterator end)
+    {
+        uint32_t cp = 0;
+        internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+        switch (err_code) {
+            case internal::UTF8_OK :
+                break;
+            case internal::NOT_ENOUGH_ROOM :
+                throw not_enough_room();
+            case internal::INVALID_LEAD :
+            case internal::INCOMPLETE_SEQUENCE :
+            case internal::OVERLONG_SEQUENCE :
+                throw invalid_utf8(*it);
+            case internal::INVALID_CODE_POINT :
+                throw invalid_code_point(cp);
+        }
+        return cp;
+    }
+
+    template <typename octet_iterator>
+    uint32_t peek_next(octet_iterator it, octet_iterator end)
+    {
+        return utf8::next(it, end);
+    }
+
+    template <typename octet_iterator>
+    uint32_t prior(octet_iterator& it, octet_iterator start)
+    {
+        // can't do much if it == start
+        if (it == start)
+            throw not_enough_room();
+
+        octet_iterator end = it;
+        // Go back until we hit either a lead octet or start
+        while (utf8::internal::is_trail(*(--it)))
+            if (it == start)
+                throw invalid_utf8(*it); // error - no lead byte in the sequence
+        return utf8::peek_next(it, end);
+    }
+
+    /// Deprecated in versions that include "prior"
+    template <typename octet_iterator>
+    uint32_t previous(octet_iterator& it, octet_iterator pass_start)
+    {
+        octet_iterator end = it;
+        while (utf8::internal::is_trail(*(--it)))
+            if (it == pass_start)
+                throw invalid_utf8(*it); // error - no lead byte in the sequence
+        octet_iterator temp = it;
+        return utf8::next(temp, end);
+    }
+
+    template <typename octet_iterator, typename distance_type>
+    void advance (octet_iterator& it, distance_type n, octet_iterator end)
+    {
+        for (distance_type i = 0; i < n; ++i)
+            utf8::next(it, end);
+    }
+
+    template <typename octet_iterator>
+    typename std::iterator_traits<octet_iterator>::difference_type
+    distance (octet_iterator first, octet_iterator last)
+    {
+        typename std::iterator_traits<octet_iterator>::difference_type dist;
+        for (dist = 0; first < last; ++dist)
+            utf8::next(first, last);
+        return dist;
+    }
+
+    template <typename u16bit_iterator, typename octet_iterator>
+    octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+    {
+        while (start != end) {
+            uint32_t cp = utf8::internal::mask16(*start++);
+            // Take care of surrogate pairs first
+            if (utf8::internal::is_lead_surrogate(cp)) {
+                if (start != end) {
+                    uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+                    if (utf8::internal::is_trail_surrogate(trail_surrogate))
+                        cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+                    else
+                        throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+                }
+                else
+                    throw invalid_utf16(static_cast<uint16_t>(cp));
+
+            }
+            // Lone trail surrogate
+            else if (utf8::internal::is_trail_surrogate(cp))
+                throw invalid_utf16(static_cast<uint16_t>(cp));
+
+            result = utf8::append(cp, result);
+        }
+        return result;
+    }
+
+    template <typename u16bit_iterator, typename octet_iterator>
+    u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+    {
+        while (start != end) {
+            uint32_t cp = utf8::next(start, end);
+            if (cp > 0xffff) { //make a surrogate pair
+                *result++ = static_cast<uint16_t>((cp >> 10)   + internal::LEAD_OFFSET);
+                *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+            }
+            else
+                *result++ = static_cast<uint16_t>(cp);
+        }
+        return result;
+    }
+
+    template <typename octet_iterator, typename u32bit_iterator>
+    octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+    {
+        while (start != end)
+            result = utf8::append(*(start++), result);
+
+        return result;
+    }
+
+    template <typename octet_iterator, typename u32bit_iterator>
+    u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+    {
+        while (start != end)
+            (*result++) = utf8::next(start, end);
+
+        return result;
+    }
+
+    // The iterator class
+    template <typename octet_iterator>
+    class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+      octet_iterator it;
+      octet_iterator range_start;
+      octet_iterator range_end;
+      public:
+      iterator () {}
+      explicit iterator (const octet_iterator& octet_it,
+                         const octet_iterator& range_start,
+                         const octet_iterator& range_end) :
+               it(octet_it), range_start(range_start), range_end(range_end)
+      {
+          if (it < range_start || it > range_end)
+              throw std::out_of_range("Invalid utf-8 iterator position");
+      }
+      // the default "big three" are OK
+      octet_iterator base () const { return it; }
+      uint32_t operator * () const
+      {
+          octet_iterator temp = it;
+          return utf8::next(temp, range_end);
+      }
+      bool operator == (const iterator& rhs) const
+      {
+          if (range_start != rhs.range_start || range_end != rhs.range_end)
+              throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+          return (it == rhs.it);
+      }
+      bool operator != (const iterator& rhs) const
+      {
+          return !(operator == (rhs));
+      }
+      iterator& operator ++ ()
+      {
+          utf8::next(it, range_end);
+          return *this;
+      }
+      iterator operator ++ (int)
+      {
+          iterator temp = *this;
+          utf8::next(it, range_end);
+          return temp;
+      }
+      iterator& operator -- ()
+      {
+          utf8::prior(it, range_start);
+          return *this;
+      }
+      iterator operator -- (int)
+      {
+          iterator temp = *this;
+          utf8::prior(it, range_start);
+          return temp;
+      }
+    }; // class iterator
+
+} // namespace utf8
+
+#endif //header guard
+
+

+ 329 - 0
contrib/utf8cpp/source/utf8/core.h

@@ -0,0 +1,329 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+namespace utf8
+{
+    // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+    // You may need to change them to match your system.
+    // These typedefs have the same names as ones from cstdint, or boost/cstdint
+    typedef unsigned char   uint8_t;
+    typedef unsigned short  uint16_t;
+    typedef unsigned int    uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+    // Unicode constants
+    // Leading (high) surrogates: 0xd800 - 0xdbff
+    // Trailing (low) surrogates: 0xdc00 - 0xdfff
+    const uint16_t LEAD_SURROGATE_MIN  = 0xd800u;
+    const uint16_t LEAD_SURROGATE_MAX  = 0xdbffu;
+    const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+    const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+    const uint16_t LEAD_OFFSET         = LEAD_SURROGATE_MIN - (0x10000 >> 10);
+    const uint32_t SURROGATE_OFFSET    = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
+
+    // Maximum valid value for a Unicode code point
+    const uint32_t CODE_POINT_MAX      = 0x0010ffffu;
+
+    template<typename octet_type>
+    inline uint8_t mask8(octet_type oc)
+    {
+        return static_cast<uint8_t>(0xff & oc);
+    }
+    template<typename u16_type>
+    inline uint16_t mask16(u16_type oc)
+    {
+        return static_cast<uint16_t>(0xffff & oc);
+    }
+    template<typename octet_type>
+    inline bool is_trail(octet_type oc)
+    {
+        return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+    }
+
+    template <typename u16>
+    inline bool is_lead_surrogate(u16 cp)
+    {
+        return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+    }
+
+    template <typename u16>
+    inline bool is_trail_surrogate(u16 cp)
+    {
+        return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+    }
+
+    template <typename u16>
+    inline bool is_surrogate(u16 cp)
+    {
+        return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+    }
+
+    template <typename u32>
+    inline bool is_code_point_valid(u32 cp)
+    {
+        return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+    }
+
+    template <typename octet_iterator>
+    inline typename std::iterator_traits<octet_iterator>::difference_type
+    sequence_length(octet_iterator lead_it)
+    {
+        uint8_t lead = utf8::internal::mask8(*lead_it);
+        if (lead < 0x80)
+            return 1;
+        else if ((lead >> 5) == 0x6)
+            return 2;
+        else if ((lead >> 4) == 0xe)
+            return 3;
+        else if ((lead >> 3) == 0x1e)
+            return 4;
+        else
+            return 0;
+    }
+
+    template <typename octet_difference_type>
+    inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+    {
+        if (cp < 0x80) {
+            if (length != 1) 
+                return true;
+        }
+        else if (cp < 0x800) {
+            if (length != 2) 
+                return true;
+        }
+        else if (cp < 0x10000) {
+            if (length != 3) 
+                return true;
+        }
+
+        return false;
+    }
+
+    enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+    /// Helper for get_sequence_x
+    template <typename octet_iterator>
+    utf_error increase_safely(octet_iterator& it, octet_iterator end)
+    {
+        if (++it == end)
+            return NOT_ENOUGH_ROOM;
+
+        if (!utf8::internal::is_trail(*it))
+            return INCOMPLETE_SEQUENCE;
+        
+        return UTF8_OK;
+    }
+
+    #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}    
+
+    /// get_sequence_x functions decode utf-8 sequences of the length x
+    template <typename octet_iterator>
+    utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+    {
+        if (it == end)
+            return NOT_ENOUGH_ROOM;
+
+        code_point = utf8::internal::mask8(*it);
+
+        return UTF8_OK;
+    }
+
+    template <typename octet_iterator>
+    utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+    {
+        if (it == end) 
+            return NOT_ENOUGH_ROOM;
+        
+        code_point = utf8::internal::mask8(*it);
+
+        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+        code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+        return UTF8_OK;
+    }
+
+    template <typename octet_iterator>
+    utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+    {
+        if (it == end)
+            return NOT_ENOUGH_ROOM;
+            
+        code_point = utf8::internal::mask8(*it);
+
+        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+        code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+        code_point += (*it) & 0x3f;
+
+        return UTF8_OK;
+    }
+
+    template <typename octet_iterator>
+    utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+    {
+        if (it == end)
+           return NOT_ENOUGH_ROOM;
+
+        code_point = utf8::internal::mask8(*it);
+
+        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+        code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+        code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+        UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+        code_point += (*it) & 0x3f;
+
+        return UTF8_OK;
+    }
+
+    #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+    template <typename octet_iterator>
+    utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+    {
+        // Save the original value of it so we can go back in case of failure
+        // Of course, it does not make much sense with i.e. stream iterators
+        octet_iterator original_it = it;
+
+        uint32_t cp = 0;
+        // Determine the sequence length based on the lead octet
+        typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+        const octet_difference_type length = utf8::internal::sequence_length(it);
+
+        // Get trail octets and calculate the code point
+        utf_error err = UTF8_OK;
+        switch (length) {
+            case 0: 
+                return INVALID_LEAD;
+            case 1:
+                err = utf8::internal::get_sequence_1(it, end, cp);
+                break;
+            case 2:
+                err = utf8::internal::get_sequence_2(it, end, cp);
+            break;
+            case 3:
+                err = utf8::internal::get_sequence_3(it, end, cp);
+            break;
+            case 4:
+                err = utf8::internal::get_sequence_4(it, end, cp);
+            break;
+        }
+
+        if (err == UTF8_OK) {
+            // Decoding succeeded. Now, security checks...
+            if (utf8::internal::is_code_point_valid(cp)) {
+                if (!utf8::internal::is_overlong_sequence(cp, length)){
+                    // Passed! Return here.
+                    code_point = cp;
+                    ++it;
+                    return UTF8_OK;
+                }
+                else
+                    err = OVERLONG_SEQUENCE;
+            }
+            else 
+                err = INVALID_CODE_POINT;
+        }
+
+        // Failure branch - restore the original value of the iterator
+        it = original_it;
+        return err;
+    }
+
+    template <typename octet_iterator>
+    inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+        uint32_t ignored;
+        return utf8::internal::validate_next(it, end, ignored);
+    }
+
+} // namespace internal
+
+    /// The library API - functions intended to be called by the users
+
+    // Byte order mark
+    const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+    template <typename octet_iterator>
+    octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+    {
+        octet_iterator result = start;
+        while (result != end) {
+            utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+            if (err_code != internal::UTF8_OK)
+                return result;
+        }
+        return result;
+    }
+
+    template <typename octet_iterator>
+    inline bool is_valid(octet_iterator start, octet_iterator end)
+    {
+        return (utf8::find_invalid(start, end) == end);
+    }
+
+    template <typename octet_iterator>
+    inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+    {
+        return (
+            ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+            ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+            ((it != end) && (utf8::internal::mask8(*it))   == bom[2])
+           );
+    }
+	
+    //Deprecated in release 2.3 
+    template <typename octet_iterator>
+    inline bool is_bom (octet_iterator it)
+    {
+        return (
+            (utf8::internal::mask8(*it++)) == bom[0] &&
+            (utf8::internal::mask8(*it++)) == bom[1] &&
+            (utf8::internal::mask8(*it))   == bom[2]
+           );
+    }
+} // namespace utf8
+
+#endif // header guard
+
+

+ 228 - 0
contrib/utf8cpp/source/utf8/unchecked.h

@@ -0,0 +1,228 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+    namespace unchecked 
+    {
+        template <typename octet_iterator>
+        octet_iterator append(uint32_t cp, octet_iterator result)
+        {
+            if (cp < 0x80)                        // one octet
+                *(result++) = static_cast<uint8_t>(cp);  
+            else if (cp < 0x800) {                // two octets
+                *(result++) = static_cast<uint8_t>((cp >> 6)          | 0xc0);
+                *(result++) = static_cast<uint8_t>((cp & 0x3f)        | 0x80);
+            }
+            else if (cp < 0x10000) {              // three octets
+                *(result++) = static_cast<uint8_t>((cp >> 12)         | 0xe0);
+                *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+                *(result++) = static_cast<uint8_t>((cp & 0x3f)        | 0x80);
+            }
+            else {                                // four octets
+                *(result++) = static_cast<uint8_t>((cp >> 18)         | 0xf0);
+                *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+                *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+                *(result++) = static_cast<uint8_t>((cp & 0x3f)        | 0x80);
+            }
+            return result;
+        }
+
+        template <typename octet_iterator>
+        uint32_t next(octet_iterator& it)
+        {
+            uint32_t cp = utf8::internal::mask8(*it);
+            typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+            switch (length) {
+                case 1:
+                    break;
+                case 2:
+                    it++;
+                    cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+                    break;
+                case 3:
+                    ++it; 
+                    cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+                    ++it;
+                    cp += (*it) & 0x3f;
+                    break;
+                case 4:
+                    ++it;
+                    cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);                
+                    ++it;
+                    cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+                    ++it;
+                    cp += (*it) & 0x3f; 
+                    break;
+            }
+            ++it;
+            return cp;        
+        }
+
+        template <typename octet_iterator>
+        uint32_t peek_next(octet_iterator it)
+        {
+            return utf8::unchecked::next(it);    
+        }
+
+        template <typename octet_iterator>
+        uint32_t prior(octet_iterator& it)
+        {
+            while (utf8::internal::is_trail(*(--it))) ;
+            octet_iterator temp = it;
+            return utf8::unchecked::next(temp);
+        }
+
+        // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
+        template <typename octet_iterator>
+        inline uint32_t previous(octet_iterator& it)
+        {
+            return utf8::unchecked::prior(it);
+        }
+
+        template <typename octet_iterator, typename distance_type>
+        void advance (octet_iterator& it, distance_type n)
+        {
+            for (distance_type i = 0; i < n; ++i)
+                utf8::unchecked::next(it);
+        }
+
+        template <typename octet_iterator>
+        typename std::iterator_traits<octet_iterator>::difference_type
+        distance (octet_iterator first, octet_iterator last)
+        {
+            typename std::iterator_traits<octet_iterator>::difference_type dist;
+            for (dist = 0; first < last; ++dist) 
+                utf8::unchecked::next(first);
+            return dist;
+        }
+
+        template <typename u16bit_iterator, typename octet_iterator>
+        octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+        {       
+            while (start != end) {
+                uint32_t cp = utf8::internal::mask16(*start++);
+            // Take care of surrogate pairs first
+                if (utf8::internal::is_lead_surrogate(cp)) {
+                    uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+                    cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+                }
+                result = utf8::unchecked::append(cp, result);
+            }
+            return result;         
+        }
+
+        template <typename u16bit_iterator, typename octet_iterator>
+        u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+        {
+            while (start < end) {
+                uint32_t cp = utf8::unchecked::next(start);
+                if (cp > 0xffff) { //make a surrogate pair
+                    *result++ = static_cast<uint16_t>((cp >> 10)   + internal::LEAD_OFFSET);
+                    *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+                }
+                else
+                    *result++ = static_cast<uint16_t>(cp);
+            }
+            return result;
+        }
+
+        template <typename octet_iterator, typename u32bit_iterator>
+        octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+        {
+            while (start != end)
+                result = utf8::unchecked::append(*(start++), result);
+
+            return result;
+        }
+
+        template <typename octet_iterator, typename u32bit_iterator>
+        u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+        {
+            while (start < end)
+                (*result++) = utf8::unchecked::next(start);
+
+            return result;
+        }
+
+        // The iterator class
+        template <typename octet_iterator>
+          class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { 
+            octet_iterator it;
+            public:
+            iterator () {}
+            explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+            // the default "big three" are OK
+            octet_iterator base () const { return it; }
+            uint32_t operator * () const
+            {
+                octet_iterator temp = it;
+                return utf8::unchecked::next(temp);
+            }
+            bool operator == (const iterator& rhs) const 
+            { 
+                return (it == rhs.it);
+            }
+            bool operator != (const iterator& rhs) const
+            {
+                return !(operator == (rhs));
+            }
+            iterator& operator ++ () 
+            {
+                ::std::advance(it, utf8::internal::sequence_length(it));
+                return *this;
+            }
+            iterator operator ++ (int)
+            {
+                iterator temp = *this;
+                ::std::advance(it, utf8::internal::sequence_length(it));
+                return temp;
+            }  
+            iterator& operator -- ()
+            {
+                utf8::unchecked::prior(it);
+                return *this;
+            }
+            iterator operator -- (int)
+            {
+                iterator temp = *this;
+                utf8::unchecked::prior(it);
+                return temp;
+            }
+          }; // class iterator
+
+    } // namespace utf8::unchecked
+} // namespace utf8 
+
+
+#endif // header guard
+

+ 0 - 2
code/SceneCombiner.h → include/assimp/SceneCombiner.h

@@ -143,7 +143,6 @@ struct NodeAttachmentInfo
  */
  */
 #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
 #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
 
 
-
 typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
 typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -153,7 +152,6 @@ struct BoneWithHash : public std::pair<uint32_t,aiString*>  {
     std::vector<BoneSrcIndex> pSrcBones;
     std::vector<BoneSrcIndex> pSrcBones;
 };
 };
 
 
-
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief Utility for SceneCombiner
 /** @brief Utility for SceneCombiner
  */
  */

+ 0 - 2
include/assimp/color4.inl

@@ -77,7 +77,6 @@ AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
 AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
-    //return *(&r + i);
     switch ( i ) {
     switch ( i ) {
         case 0:
         case 0:
             return r;
             return r;
@@ -93,7 +92,6 @@ AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
 AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
-//    return *(&r + i);
     switch ( i ) {
     switch ( i ) {
         case 0:
         case 0:
             return r;
             return r;

+ 16 - 4
include/assimp/material.inl

@@ -48,6 +48,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MATERIAL_INL_INC
 #ifndef AI_MATERIAL_INL_INC
 #define AI_MATERIAL_INL_INC
 #define AI_MATERIAL_INL_INC
 
 
+// ---------------------------------------------------------------------------
+inline aiPropertyTypeInfo ai_real_to_property_type_info(float)
+{
+	return aiPTI_Float;
+}
+
+inline aiPropertyTypeInfo ai_real_to_property_type_info(double)
+{
+	return aiPTI_Double;
+}
+// ---------------------------------------------------------------------------
+
 //! @cond never
 //! @cond never
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -223,7 +235,7 @@ inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiUVTransform),
         pNumValues * sizeof(aiUVTransform),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->mRotation));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -235,7 +247,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiColor4D),
         pNumValues * sizeof(aiColor4D),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->a));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -247,7 +259,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiColor3D),
         pNumValues * sizeof(aiColor3D),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->b));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -259,7 +271,7 @@ inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
 {
 {
     return AddBinaryProperty((const void*)pInput,
     return AddBinaryProperty((const void*)pInput,
         pNumValues * sizeof(aiVector3D),
         pNumValues * sizeof(aiVector3D),
-        pKey,type,index,aiPTI_Float); //TODO could be Double ...
+        pKey,type,index,ai_real_to_property_type_info(pInput->x));
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------

+ 4 - 3
include/assimp/matrix4x4.h

@@ -224,7 +224,7 @@ public:
      *  @return Reference to the output matrix
      *  @return Reference to the output matrix
      */
      */
     static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
     static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
-        aiMatrix4x4t& out);
+            aiMatrix4x4t& out);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Returns a translation matrix
     /** @brief Returns a translation matrix
@@ -232,7 +232,8 @@ public:
      *  @param out Receives the output matrix
      *  @param out Receives the output matrix
      *  @return Reference to the output matrix
      *  @return Reference to the output matrix
      */
      */
-    static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
+    static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, 
+            aiMatrix4x4t& out);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Returns a scaling matrix
     /** @brief Returns a scaling matrix
@@ -252,7 +253,7 @@ public:
      *          Journal of Graphics Tools, 4(4):1-4, 1999
      *          Journal of Graphics Tools, 4(4):1-4, 1999
      */
      */
     static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
     static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
-        const aiVector3t<TReal>& to, aiMatrix4x4t& out);
+            const aiVector3t<TReal>& to, aiMatrix4x4t& out);
 
 
 public:
 public:
     TReal a1, a2, a3, a4;
     TReal a1, a2, a3, a4;

+ 1 - 4
port/PyAssimp/pyassimp/helper.py

@@ -8,7 +8,6 @@ import os
 import ctypes
 import ctypes
 from ctypes import POINTER
 from ctypes import POINTER
 import operator
 import operator
-import sys
 
 
 try: import numpy
 try: import numpy
 except: numpy = None
 except: numpy = None
@@ -40,9 +39,7 @@ elif os.name=='nt':
     for dir_candidate in path_dirs:
     for dir_candidate in path_dirs:
         if 'assimp' in dir_candidate.lower():
         if 'assimp' in dir_candidate.lower():
             additional_dirs.append(dir_candidate)
             additional_dirs.append(dir_candidate)
-
-additional_dirs += sys.path
-
+            
 #print(additional_dirs)
 #print(additional_dirs)
 def vec2tuple(x):
 def vec2tuple(x):
     """ Converts a VECTOR3D to a Tuple """
     """ Converts a VECTOR3D to a Tuple """

+ 1 - 3
port/PyAssimp/setup.py

@@ -9,7 +9,5 @@ setup(name='pyassimp',
       url='https://github.com/assimp/assimp',
       url='https://github.com/assimp/assimp',
       packages=['pyassimp'],
       packages=['pyassimp'],
       data_files=[('share/pyassimp', ['README.md']),
       data_files=[('share/pyassimp', ['README.md']),
-                  ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')]),
-                  ('lib/', [f for f in os.listdir('../../lib') if os.path.isfile(f)])],
-      requires=['numpy']
+                  ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')])], requires=['numpy']
       )
       )

+ 28 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln

@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.9
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexturedDirectx11", "SimpleTexturedDirectx11\SimpleTexturedDirectx11.vcxproj", "{E3B160B5-E71F-4F3F-9310-B8F156F736D8}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.ActiveCfg = Debug|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.Build.0 = Debug|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.ActiveCfg = Debug|Win32
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.Build.0 = Debug|Win32
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.ActiveCfg = Release|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.Build.0 = Release|x64
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.ActiveCfg = Release|Win32
+		{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 102 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h

@@ -0,0 +1,102 @@
+#ifndef MESH_H
+#define MESH_H
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <vector>
+using namespace std;
+
+#include <vector>
+#include <d3d11_1.h>
+#include <DirectXMath.h>
+using namespace DirectX;
+
+struct VERTEX {
+	FLOAT X, Y, Z;
+	XMFLOAT2 texcoord;
+};
+
+struct Texture {
+	string type;
+	string path;
+	ID3D11ShaderResourceView *texture;
+};
+
+class Mesh {
+public:
+	vector<VERTEX> vertices;
+	vector<UINT> indices;
+	vector<Texture> textures;
+	ID3D11Device *dev;
+
+	Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
+	{
+		this->vertices = vertices;
+		this->indices = indices;
+		this->textures = textures;
+
+		this->dev = dev;
+
+		this->setupMesh(dev);
+	}
+
+	void Draw(ID3D11DeviceContext *devcon)
+	{
+		UINT stride = sizeof(VERTEX);
+		UINT offset = 0;
+
+		devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
+		devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
+
+		devcon->PSSetShaderResources(0, 1, &textures[0].texture);
+
+		devcon->DrawIndexed(indices.size(), 0, 0);
+	}
+
+	void Close()
+	{
+		VertexBuffer->Release();
+		IndexBuffer->Release();
+	}
+private:
+	/*  Render data  */
+	ID3D11Buffer *VertexBuffer, *IndexBuffer;
+
+	/*  Functions    */
+	// Initializes all the buffer objects/arrays
+	bool setupMesh(ID3D11Device *dev)
+	{
+		HRESULT hr;
+
+		D3D11_BUFFER_DESC vbd;
+		vbd.Usage = D3D11_USAGE_IMMUTABLE;
+		vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
+		vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+		vbd.CPUAccessFlags = 0;
+		vbd.MiscFlags = 0;
+
+		D3D11_SUBRESOURCE_DATA initData;
+		initData.pSysMem = &vertices[0];
+
+		hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
+		if (FAILED(hr))
+			return false;
+
+		D3D11_BUFFER_DESC ibd;
+		ibd.Usage = D3D11_USAGE_IMMUTABLE;
+		ibd.ByteWidth = sizeof(UINT) * indices.size();
+		ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
+		ibd.CPUAccessFlags = 0;
+		ibd.MiscFlags = 0;
+
+		initData.pSysMem = &indices[0];
+
+		hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
+		if (FAILED(hr))
+			return false;
+	}
+};
+
+#endif

+ 205 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

@@ -0,0 +1,205 @@
+#include "ModelLoader.h"
+
+ModelLoader::ModelLoader()
+{
+}
+
+
+ModelLoader::~ModelLoader()
+{
+}
+
+bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename)
+{
+	Assimp::Importer importer;
+
+	const aiScene* pScene = importer.ReadFile(filename,
+		aiProcess_Triangulate |
+		aiProcess_ConvertToLeftHanded);
+
+	if (pScene == NULL)
+		return false;
+
+	this->directory = filename.substr(0, filename.find_last_of('/'));
+
+	this->dev = dev;
+	this->hwnd = hwnd;
+
+	processNode(pScene->mRootNode, pScene);
+
+	return true;
+}
+
+void ModelLoader::Draw(ID3D11DeviceContext * devcon)
+{
+	for (int i = 0; i < meshes.size(); i++)
+	{
+		meshes[i].Draw(devcon);
+	}
+}
+
+string textype;
+
+Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
+{
+	// Data to fill
+	vector<VERTEX> vertices;
+	vector<UINT> indices;
+	vector<Texture> textures;
+
+	if (mesh->mMaterialIndex >= 0)
+	{
+		aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
+
+		if (textype.empty()) textype = determineTextureType(scene, mat);
+	}
+
+	// Walk through each of the mesh's vertices
+	for (UINT i = 0; i < mesh->mNumVertices; i++)
+	{
+		VERTEX vertex;
+
+		vertex.X = mesh->mVertices[i].x;
+		vertex.Y = mesh->mVertices[i].y;
+		vertex.Z = mesh->mVertices[i].z;
+
+		if (mesh->mTextureCoords[0])
+		{
+			vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
+			vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
+		}
+
+		vertices.push_back(vertex);
+	}
+
+	for (UINT i = 0; i < mesh->mNumFaces; i++)
+	{
+		aiFace face = mesh->mFaces[i];
+
+		for (UINT j = 0; j < face.mNumIndices; j++)
+			indices.push_back(face.mIndices[j]);
+	}
+
+	if (mesh->mMaterialIndex >= 0)
+	{
+		aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
+
+		vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
+		textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
+	}
+
+	return Mesh(dev, vertices, indices, textures);
+}
+
+vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
+{
+	vector<Texture> textures;
+	for (UINT i = 0; i < mat->GetTextureCount(type); i++)
+	{
+		aiString str;
+		mat->GetTexture(type, i, &str);
+		// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
+		bool skip = false;
+		for (UINT j = 0; j < textures_loaded.size(); j++)
+		{
+			if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0)
+			{
+				textures.push_back(textures_loaded[j]);
+				skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
+				break;
+			}
+		}
+		if (!skip)
+		{   // If texture hasn't been loaded already, load it
+			HRESULT hr;
+			Texture texture;
+			if (textype == "embedded compressed texture")
+			{
+				int textureindex = getTextureIndex(&str);
+				texture.texture = getTextureFromModel(scene, textureindex);
+			}
+			else
+			{
+				string filename = string(str.C_Str());
+				filename = directory + '/' + filename;
+				wstring filenamews = wstring(filename.begin(), filename.end());
+				hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
+				if (FAILED(hr))
+					MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
+			}
+			texture.type = typeName;
+			texture.path = str.C_Str();
+			textures.push_back(texture);
+			this->textures_loaded.push_back(texture);  // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
+		}
+	}
+	return textures;
+}
+
+void ModelLoader::Close()
+{
+	for (int i = 0; i < meshes.size(); i++)
+	{
+		meshes[i].Close();
+	}
+
+	dev->Release();
+}
+
+void ModelLoader::processNode(aiNode * node, const aiScene * scene)
+{
+	for (UINT i = 0; i < node->mNumMeshes; i++)
+	{
+		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
+		meshes.push_back(this->processMesh(mesh, scene));
+	}
+
+	for (UINT i = 0; i < node->mNumChildren; i++)
+	{
+		this->processNode(node->mChildren[i], scene);
+	}
+}
+
+string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
+{
+	aiString textypeStr;
+	mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
+	string textypeteststr = textypeStr.C_Str();
+	if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
+	{
+		if (scene->mTextures[0]->mHeight == 0)
+		{
+			return "embedded compressed texture";
+		}
+		else
+		{
+			return "embedded non-compressed texture";
+		}
+	}
+	if (textypeteststr.find('.') != string::npos)
+	{
+		return "textures are on disk";
+	}
+}
+
+int ModelLoader::getTextureIndex(aiString * str)
+{
+	string tistr;
+	tistr = str->C_Str();
+	tistr = tistr.substr(1);
+	return stoi(tistr);
+}
+
+ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
+{
+	HRESULT hr;
+	ID3D11ShaderResourceView *texture;
+
+	int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
+
+	hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
+	if (FAILED(hr))
+		MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
+
+	return texture;
+}

Some files were not shown because too many files changed in this diff