Coverage Report

Created: 2026-08-11 08:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OGR
4
 * Purpose:  OGRNASDriver implementation
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_conv.h"
14
#include "cpl_multiproc.h"
15
#include "nasreaderp.h"
16
#include "ogr_nas.h"
17
18
/************************************************************************/
19
/*                        OGRNASDriverIdentify()                        */
20
/************************************************************************/
21
22
static int OGRNASDriverIdentify(GDALOpenInfo *poOpenInfo)
23
24
160k
{
25
160k
    if (poOpenInfo->fpL == nullptr)
26
51.2k
        return FALSE;
27
28
    /* -------------------------------------------------------------------- */
29
    /*      Check for a UTF-8 BOM and skip if found                         */
30
    /*                                                                      */
31
    /*      TODO: BOM is variable-length parameter and depends on encoding. */
32
    /*            Add BOM detection for other encodings.                    */
33
    /* -------------------------------------------------------------------- */
34
35
    // Used to skip to actual beginning of XML data
36
108k
    const char *pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
37
38
    // Skip UTF-8 BOM
39
108k
    if (poOpenInfo->nHeaderBytes > 3 &&
40
104k
        memcmp(poOpenInfo->pabyHeader, "\xEF\xBB\xBF", 3) == 0)
41
209
    {
42
209
        pszPtr += 3;
43
209
    }
44
45
    // Skip spaces
46
173k
    while (*pszPtr && std::isspace(static_cast<unsigned char>(*pszPtr)))
47
64.8k
        ++pszPtr;
48
49
    /* -------------------------------------------------------------------- */
50
    /*      Here, we expect the opening chevrons of NAS tree root element   */
51
    /* -------------------------------------------------------------------- */
52
108k
    if (pszPtr[0] != '<')
53
96.3k
        return FALSE;
54
55
12.4k
    if (poOpenInfo->IsSingleAllowedDriver("NAS"))
56
0
        return TRUE;
57
58
    // TryToIngest() invalidates above pszPtr
59
12.4k
    pszPtr = nullptr;
60
12.4k
    CPL_IGNORE_RET_VAL(pszPtr);
61
12.4k
    if (!poOpenInfo->TryToIngest(8192))
62
0
        return FALSE;
63
12.4k
    pszPtr = reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
64
65
12.4k
    if (strstr(pszPtr, "opengis.net/gml") == nullptr)
66
7.20k
        return FALSE;
67
68
5.24k
    char **papszIndicators = CSLTokenizeStringComplex(
69
5.24k
        CPLGetConfigOption("NAS_INDICATOR",
70
5.24k
                           "NAS-Operationen;AAA-Fachschema;aaa.xsd;aaa-suite"),
71
5.24k
        ";", 0, 0);
72
73
5.24k
    bool bFound = false;
74
21.7k
    for (int i = 0; papszIndicators[i] && !bFound; i++)
75
16.4k
    {
76
16.4k
        bFound = strstr(pszPtr, papszIndicators[i]) != nullptr;
77
16.4k
    }
78
79
5.24k
    CSLDestroy(papszIndicators);
80
81
    // Require NAS_GFS_TEMPLATE to be defined
82
5.24k
    if (bFound && !CPLGetConfigOption("NAS_GFS_TEMPLATE", nullptr))
83
1.89k
    {
84
1.89k
        CPLDebug("NAS",
85
1.89k
                 "This file could be recognized by the NAS driver. "
86
1.89k
                 "If this is desired, you need to define the NAS_GFS_TEMPLATE "
87
1.89k
                 "configuration option.");
88
1.89k
        return FALSE;
89
1.89k
    }
90
91
3.34k
    return bFound;
92
5.24k
}
93
94
/************************************************************************/
95
/*                                Open()                                */
96
/************************************************************************/
97
98
static GDALDataset *OGRNASDriverOpen(GDALOpenInfo *poOpenInfo)
99
100
0
{
101
0
    if (poOpenInfo->eAccess == GA_Update || !OGRNASDriverIdentify(poOpenInfo))
102
0
        return nullptr;
103
104
0
    VSIFCloseL(poOpenInfo->fpL);
105
0
    poOpenInfo->fpL = nullptr;
106
107
0
    OGRNASDataSource *poDS = new OGRNASDataSource();
108
109
0
    if (!poDS->Open(poOpenInfo->pszFilename))
110
0
    {
111
0
        delete poDS;
112
0
        return nullptr;
113
0
    }
114
115
0
    return poDS;
116
0
}
117
118
/************************************************************************/
119
/*                           RegisterOGRNAS()                           */
120
/************************************************************************/
121
122
void RegisterOGRNAS()
123
124
22
{
125
22
    if (GDALGetDriverByName("NAS") != nullptr)
126
0
        return;
127
128
22
    GDALDriver *poDriver = new GDALDriver();
129
130
22
    poDriver->SetDescription("NAS");
131
22
    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
132
22
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "NAS - ALKIS");
133
22
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "xml");
134
22
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/nas.html");
135
22
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
136
22
    poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
137
138
22
    poDriver->pfnOpen = OGRNASDriverOpen;
139
22
    poDriver->pfnIdentify = OGRNASDriverIdentify;
140
141
22
    GetGDALDriverManager()->RegisterDriver(poDriver);
142
22
}