Coverage Report

Created: 2025-12-31 08:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/cad/libopencad/opencad.cpp
Line
Count
Source
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
static int CheckCADFile(CADFileIO * pCADFileIO)
33
14.0k
{
34
14.0k
    if( pCADFileIO == nullptr )
35
0
        return 0;
36
37
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(OPENCAD_DISABLE_EXTENSION_CHECK)
38
    const char * pszFilePath = pCADFileIO->GetFilePath();
39
    size_t nPathLen = strlen( pszFilePath );
40
41
    if( nPathLen > 3 &&
42
        toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 3]) ) == 'D' &&
43
        toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 2]) ) == 'X' &&
44
        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
        return 0;
49
    }
50
    if( ! ( nPathLen > 3 &&
51
            toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 3]) ) == 'D' &&
52
            toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 2]) ) == 'W' &&
53
            toupper( static_cast<unsigned char>(pszFilePath[nPathLen - 1]) ) == 'G' ) )
54
    {
55
        return 0;
56
    }
57
#endif
58
59
14.0k
    if( !pCADFileIO->IsOpened() )
60
7.01k
        pCADFileIO->Open( CADFileIO::OpenMode::in | CADFileIO::OpenMode::binary );
61
14.0k
    if( !pCADFileIO->IsOpened() )
62
0
        return 0;
63
64
14.0k
    char pabyDWGVersion[DWG_VERSION_STR_SIZE + 1] = { 0 };
65
14.0k
    pCADFileIO->Rewind ();
66
14.0k
    pCADFileIO->Read( pabyDWGVersion, DWG_VERSION_STR_SIZE );
67
14.0k
    return atoi( pabyDWGVersion + 2 );
68
14.0k
}
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
CADFile * OpenCADFile( CADFileIO * pCADFileIO, enum CADFile::OpenOptions eOptions, bool bReadUnsupportedGeometries )
78
7.00k
{
79
7.00k
    int nCADFileVersion = CheckCADFile( pCADFileIO );
80
7.00k
    CADFile * poCAD = nullptr;
81
82
7.00k
    switch( nCADFileVersion )
83
7.00k
    {
84
6.97k
        case CADVersions::DWG_R2000:
85
6.97k
            poCAD = new DWGFileR2000( pCADFileIO );
86
6.97k
            break;
87
35
        default:
88
35
            gLastError = CADErrorCodes::UNSUPPORTED_VERSION;
89
35
            delete pCADFileIO;
90
35
            return nullptr;
91
7.00k
    }
92
93
6.97k
    gLastError = poCAD->ParseFile( eOptions, bReadUnsupportedGeometries );
94
6.97k
    if( gLastError != CADErrorCodes::SUCCESS )
95
5.17k
    {
96
5.17k
        delete poCAD;
97
5.17k
        return nullptr;
98
5.17k
    }
99
100
1.79k
    return poCAD;
101
6.97k
}
102
103
104
/**
105
 * @brief Get library version number as major * 10000 + minor * 100 + rev
106
 * @return library version number
107
 */
108
int GetVersion()
109
0
{
110
0
    return OCAD_VERSION_NUM;
111
0
}
112
113
/**
114
 * @brief Get library version string
115
 * @return library version string
116
 */
117
const char * GetVersionString()
118
5.20k
{
119
5.20k
    return OCAD_VERSION;
120
5.20k
}
121
122
/**
123
 * @brief Get last error code
124
 * @return last error code
125
 */
126
int GetLastErrorCode()
127
20.4k
{
128
20.4k
    return gLastError;
129
20.4k
}
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
CADFileIO* GetDefaultFileIO( const char * pszFileName )
138
0
{
139
0
    return new CADFileStreamIO( pszFileName );
140
0
}
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
int IdentifyCADFile( CADFileIO * pCADFileIO, bool bOwn )
149
7.01k
{
150
7.01k
    int result = CheckCADFile(pCADFileIO);
151
7.01k
    if(bOwn)
152
0
    {
153
0
        delete pCADFileIO;
154
0
    }
155
7.01k
    return result;
156
7.01k
}
157
158
/**
159
 * @brief List supported CAD Formats
160
 * @return String describes supported CAD formats
161
 */
162
const char * GetCADFormats()
163
5.20k
{
164
5.20k
    return "DWG R2000 [ACAD1015]\n";
165
5.20k
}
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
CADFile * OpenCADFile( const char * pszFileName, enum CADFile::OpenOptions eOptions, bool bReadUnsupportedGeometries )
174
0
{
175
0
    return OpenCADFile( GetDefaultFileIO( pszFileName ), eOptions, bReadUnsupportedGeometries );
176
0
}
177
178
#ifdef _DEBUG
179
void DebugMsg( const char* format, ... )
180
#else
181
void DebugMsg( const char*, ... )
182
#endif
183
1.20M
{
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
1.20M
}