Coverage Report

Created: 2025-07-23 09:13

/src/gdal/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRDGNDriver class.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2000, Frank Warmerdam (warmerdam@pobox.com)
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "ogr_dgn.h"
14
#include "cpl_conv.h"
15
16
/************************************************************************/
17
/*                       OGRDGNDriverIdentify()                         */
18
/************************************************************************/
19
20
static int OGRDGNDriverIdentify(GDALOpenInfo *poOpenInfo)
21
22
162k
{
23
162k
    if (poOpenInfo->fpL != nullptr && poOpenInfo->nHeaderBytes >= 512 &&
24
162k
        DGNTestOpen(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes))
25
4.90k
    {
26
4.90k
        return TRUE;
27
4.90k
    }
28
29
    // Is this is a DGNv8 file ? If so, and if the DGNV8 driver is not
30
    // available, and we are called from GDALError(), emit an explicit
31
    // error.
32
157k
    VSIStatBuf sStat;
33
157k
    if ((poOpenInfo->nOpenFlags & GDAL_OF_FROM_GDALOPEN) != 0 &&
34
157k
        poOpenInfo->papszAllowedDrivers == nullptr &&
35
157k
        poOpenInfo->fpL != nullptr && poOpenInfo->nHeaderBytes >= 512 &&
36
157k
        memcmp(poOpenInfo->pabyHeader, "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) ==
37
78.9k
            0 &&
38
157k
        poOpenInfo->IsExtensionEqualToCI("DGN") &&
39
157k
        VSIStat(poOpenInfo->pszFilename, &sStat) == 0 &&
40
157k
        GDALGetDriverByName("DGNV8") == nullptr)
41
0
    {
42
0
        CPLError(CE_Failure, CPLE_AppDefined,
43
0
                 "`%s' recognized as a DGNv8 dataset, but the DGNv8 driver is "
44
0
                 "not available in this GDAL build. Consult "
45
0
                 "https://gdal.org/drivers/vector/dgnv8.html",
46
0
                 poOpenInfo->pszFilename);
47
0
    }
48
157k
    return FALSE;
49
162k
}
50
51
/************************************************************************/
52
/*                                Open()                                */
53
/************************************************************************/
54
55
static GDALDataset *OGRDGNDriverOpen(GDALOpenInfo *poOpenInfo)
56
57
2.45k
{
58
2.45k
    if (!OGRDGNDriverIdentify(poOpenInfo))
59
0
        return nullptr;
60
61
2.45k
    OGRDGNDataSource *poDS = new OGRDGNDataSource();
62
63
2.45k
    if (!poDS->Open(poOpenInfo) || poDS->GetLayerCount() == 0)
64
0
    {
65
0
        delete poDS;
66
0
        return nullptr;
67
0
    }
68
69
2.45k
    return poDS;
70
2.45k
}
71
72
/************************************************************************/
73
/*                              Create()                                */
74
/************************************************************************/
75
76
static GDALDataset *OGRDGNDriverCreate(const char *, int /* nBands */,
77
                                       int /* nXSize */, int /* nYSize */,
78
                                       GDALDataType /* eDT */,
79
                                       char **papszOptions)
80
0
{
81
0
    OGRDGNDataSource *poDS = new OGRDGNDataSource();
82
0
    poDS->PreCreate(papszOptions);
83
0
    return poDS;
84
0
}
85
86
/************************************************************************/
87
/*                          RegisterOGRDGN()                            */
88
/************************************************************************/
89
90
void RegisterOGRDGN()
91
92
22
{
93
22
    if (GDALGetDriverByName("DGN") != nullptr)
94
0
        return;
95
96
22
    GDALDriver *poDriver = new GDALDriver();
97
98
22
    poDriver->SetDescription("DGN");
99
22
    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
100
22
    poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
101
22
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Microstation DGN");
102
22
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "dgn");
103
22
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/dgn.html");
104
22
    poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
105
22
    poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
106
107
22
    poDriver->SetMetadataItem(
108
22
        GDAL_DMD_OPENOPTIONLIST,
109
22
        "<OpenOptionList>"
110
22
        "  <Option name='ENCODING' type='string' description="
111
22
        "'Encoding name, as supported by iconv'/>"
112
22
        "</OpenOptionList>");
113
114
22
    poDriver->SetMetadataItem(
115
22
        GDAL_DMD_CREATIONOPTIONLIST,
116
22
        "<CreationOptionList>"
117
22
        "  <Option name='3D' type='boolean' description='whether 2D "
118
22
        "(seed_2d.dgn) or 3D (seed_3d.dgn) seed file should be used. This "
119
22
        "option is ignored if the SEED option is provided'/>"
120
22
        "  <Option name='SEED' type='string' description='Filename of seed "
121
22
        "file to use'/>"
122
22
        "  <Option name='COPY_WHOLE_SEED_FILE' type='boolean' "
123
22
        "description='whether the whole seed file should be copied. If not, "
124
22
        "only the first three elements (and potentially the color table) will "
125
22
        "be copied.' default='NO'/>"
126
22
        "  <Option name='COPY_SEED_FILE_COLOR_TABLE' type='boolean' "
127
22
        "description='whether the color table should be copied from the seed "
128
22
        "file.' default='NO'/>"
129
22
        "  <Option name='MASTER_UNIT_NAME' type='string' description='Override "
130
22
        "the master unit name from the seed file with the provided one or two "
131
22
        "character unit name.'/>"
132
22
        "  <Option name='SUB_UNIT_NAME' type='string' description='Override "
133
22
        "the master unit name from the seed file with the provided one or two "
134
22
        "character unit name.'/>"
135
22
        "  <Option name='MASTER_UNIT_NAME' type='string' description='Override "
136
22
        "the master unit name from the seed file with the provided one or two "
137
22
        "character unit name.'/>"
138
22
        "  <Option name='SUB_UNIT_NAME' type='string' description='Override "
139
22
        "the sub unit name from the seed file with the provided one or two "
140
22
        "character unit name.'/>"
141
22
        "  <Option name='SUB_UNITS_PER_MASTER_UNIT' type='int' "
142
22
        "description='Override the number of subunits per master unit. By "
143
22
        "default the seed file value is used.'/>"
144
22
        "  <Option name='UOR_PER_SUB_UNIT' type='int' description='Override "
145
22
        "the number of UORs (Units of Resolution) per sub unit. By default the "
146
22
        "seed file value is used.'/>"
147
22
        "  <Option name='ORIGIN' type='string' description='Value as x,y,z. "
148
22
        "Override the origin of the design plane. By default the origin from "
149
22
        "the seed file is used.'/>"
150
22
        "  <Option name='ENCODING' type='string' description="
151
22
        "'Encoding name, as supported by iconv'/>"
152
22
        "</CreationOptionList>");
153
154
22
    poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
155
22
                              "<LayerCreationOptionList/>");
156
22
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
157
22
    poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
158
22
    poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES");
159
22
    poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES");
160
22
    poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
161
162
22
    poDriver->pfnOpen = OGRDGNDriverOpen;
163
22
    poDriver->pfnIdentify = OGRDGNDriverIdentify;
164
22
    poDriver->pfnCreate = OGRDGNDriverCreate;
165
166
22
    GetGDALDriverManager()->RegisterDriver(poDriver);
167
22
}