Line data Source code
1 : /******************************************************************************* 2 : * Project: libopencad_api.cpp 3 : * Purpose: libOpenCAD OpenSource CAD formats support library 4 : * Author: Alexandr Borzykh, mush3d at gmail.com 5 : * Author: Dmitry Baryshnikov, bishop.dev@gmail.com 6 : * Language: C++ 7 : ******************************************************************************* 8 : * The MIT License (MIT) 9 : * 10 : * Copyright (c) 2016 Alexandr Borzykh 11 : * Copyright (c) 2016-2019 NextGIS, <info@nextgis.com> 12 : * 13 : * SPDX-License-Identifier: MIT 14 : *******************************************************************************/ 15 : #include "opencad_api.h" 16 : #include "cadfilestreamio.h" 17 : #include "dwg/r2000.h" 18 : 19 : #include <cctype> 20 : #include <cstdarg> 21 : #include <cstdlib> 22 : #include <cstring> 23 : #include <iostream> 24 : 25 : static int gLastError = CADErrorCodes::SUCCESS; 26 : 27 : /** 28 : * @brief Check CAD file 29 : * @param pCADFileIO CAD file reader pointer owned by function 30 : * @return returns and int, 0 if CAD file has unsupported format 31 : */ 32 18 : static int CheckCADFile(CADFileIO * pCADFileIO) 33 : { 34 18 : if( pCADFileIO == nullptr ) 35 0 : return 0; 36 : 37 : #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(OPENCAD_DISABLE_EXTENSION_CHECK) 38 18 : const char * pszFilePath = pCADFileIO->GetFilePath(); 39 18 : size_t nPathLen = strlen( pszFilePath ); 40 : 41 18 : if( nPathLen > 3 && 42 18 : toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 3]) ) == 'D' && 43 18 : toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 2]) ) == 'X' && 44 0 : toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 1]) ) == 'F' ) 45 : { 46 : //TODO: "AutoCAD Binary DXF" 47 : //std::cerr << "DXF ASCII and binary is not supported yet."; 48 0 : return 0; 49 : } 50 18 : if( ! ( nPathLen > 3 && 51 18 : toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 3]) ) == 'D' && 52 18 : toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 2]) ) == 'W' && 53 18 : toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 1]) ) == 'G' ) ) 54 : { 55 0 : return 0; 56 : } 57 : #endif 58 : 59 18 : if( !pCADFileIO->IsOpened() ) 60 9 : pCADFileIO->Open( CADFileIO::OpenMode::in | CADFileIO::OpenMode::binary ); 61 18 : if( !pCADFileIO->IsOpened() ) 62 0 : return 0; 63 : 64 18 : char pabyDWGVersion[DWG_VERSION_STR_SIZE + 1] = { 0 }; 65 18 : pCADFileIO->Rewind (); 66 18 : pCADFileIO->Read( pabyDWGVersion, DWG_VERSION_STR_SIZE ); 67 18 : return atoi( pabyDWGVersion + 2 ); 68 : } 69 : 70 : /** 71 : * @brief Open CAD file 72 : * @param pCADFileIO CAD file reader pointer ownd by function 73 : * @param eOptions Open options 74 : * @param bReadUnsupportedGeometries Unsupported geoms will be returned as CADUnknown 75 : * @return CADFile pointer or NULL if failed. The pointer have to be freed by user 76 : */ 77 9 : CADFile * OpenCADFile( CADFileIO * pCADFileIO, enum CADFile::OpenOptions eOptions, bool bReadUnsupportedGeometries ) 78 : { 79 9 : int nCADFileVersion = CheckCADFile( pCADFileIO ); 80 9 : CADFile * poCAD = nullptr; 81 : 82 9 : switch( nCADFileVersion ) 83 : { 84 8 : case CADVersions::DWG_R2000: 85 8 : poCAD = new DWGFileR2000( pCADFileIO ); 86 8 : break; 87 1 : default: 88 1 : gLastError = CADErrorCodes::UNSUPPORTED_VERSION; 89 1 : delete pCADFileIO; 90 1 : return nullptr; 91 : } 92 : 93 8 : gLastError = poCAD->ParseFile( eOptions, bReadUnsupportedGeometries ); 94 8 : if( gLastError != CADErrorCodes::SUCCESS ) 95 : { 96 0 : delete poCAD; 97 0 : return nullptr; 98 : } 99 : 100 8 : return poCAD; 101 : } 102 : 103 : 104 : /** 105 : * @brief Get library version number as major * 10000 + minor * 100 + rev 106 : * @return library version number 107 : */ 108 0 : int GetVersion() 109 : { 110 0 : return OCAD_VERSION_NUM; 111 : } 112 : 113 : /** 114 : * @brief Get library version string 115 : * @return library version string 116 : */ 117 1 : const char * GetVersionString() 118 : { 119 1 : return OCAD_VERSION; 120 : } 121 : 122 : /** 123 : * @brief Get last error code 124 : * @return last error code 125 : */ 126 30 : int GetLastErrorCode() 127 : { 128 30 : return gLastError; 129 : } 130 : 131 : /** 132 : * @brief GetDefaultFileIO return default file in/out class. 133 : * @param pszFileName CAD file path 134 : * @return CADFileIO pointer or null if error. The pointer have to be freed by 135 : * user 136 : */ 137 0 : CADFileIO* GetDefaultFileIO( const char * pszFileName ) 138 : { 139 0 : return new CADFileStreamIO( pszFileName ); 140 : } 141 : 142 : /** 143 : * @brief IdentifyCADFile 144 : * @param pCADFileIO pointer to file in/out class 145 : * @return positive number for dwg version, negative for dxf version, 0 if error 146 : * occurred 147 : */ 148 9 : int IdentifyCADFile( CADFileIO * pCADFileIO, bool bOwn ) 149 : { 150 9 : int result = CheckCADFile(pCADFileIO); 151 9 : if(bOwn) 152 : { 153 0 : delete pCADFileIO; 154 : } 155 9 : return result; 156 : } 157 : 158 : /** 159 : * @brief List supported CAD Formats 160 : * @return String describes supported CAD formats 161 : */ 162 1 : const char * GetCADFormats() 163 : { 164 1 : return "DWG R2000 [ACAD1015]\n"; 165 : } 166 : 167 : /** 168 : * @brief Open CAD file 169 : * @param pszFileName Path to CAD file 170 : * @param eOptions Open options 171 : * @return CADFile pointer or NULL if failed. The pointer have to be freed by user. 172 : */ 173 0 : CADFile * OpenCADFile( const char * pszFileName, enum CADFile::OpenOptions eOptions, bool bReadUnsupportedGeometries ) 174 : { 175 0 : return OpenCADFile( GetDefaultFileIO( pszFileName ), eOptions, bReadUnsupportedGeometries ); 176 : } 177 : 178 : #ifdef _DEBUG 179 : void DebugMsg( const char* format, ... ) 180 : #else 181 251 : void DebugMsg( const char*, ... ) 182 : #endif 183 : { 184 : #ifdef _DEBUG 185 : va_list argptr; 186 : va_start( argptr, format ); 187 : vfprintf( stdout, format, argptr ); 188 : va_end( argptr ); 189 : #endif //_DEBUG 190 251 : }