Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements OGRGmtDataSource class.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_conv.h"
14
#include "cpl_string.h"
15
#include "ogr_gmt.h"
16
17
/************************************************************************/
18
/*                          OGRGmtDataSource()                          */
19
/************************************************************************/
20
21
OGRGmtDataSource::OGRGmtDataSource()
22
10.9k
    : papoLayers(nullptr), nLayers(0), bUpdate(false)
23
10.9k
{
24
10.9k
}
25
26
/************************************************************************/
27
/*                         ~OGRGmtDataSource()                          */
28
/************************************************************************/
29
30
OGRGmtDataSource::~OGRGmtDataSource()
31
32
10.9k
{
33
21.9k
    for (int i = 0; i < nLayers; i++)
34
10.9k
        delete papoLayers[i];
35
10.9k
    CPLFree(papoLayers);
36
10.9k
}
37
38
/************************************************************************/
39
/*                                Open()                                */
40
/************************************************************************/
41
42
int OGRGmtDataSource::Open(const char *pszFilename, VSILFILE *fp,
43
                           const OGRSpatialReference *poSRS, int bUpdateIn)
44
45
10.9k
{
46
10.9k
    bUpdate = CPL_TO_BOOL(bUpdateIn);
47
48
10.9k
    OGRGmtLayer *poLayer =
49
10.9k
        new OGRGmtLayer(this, pszFilename, fp, poSRS, bUpdate);
50
10.9k
    if (!poLayer->bValidFile)
51
82
    {
52
82
        delete poLayer;
53
82
        return FALSE;
54
82
    }
55
56
10.9k
    papoLayers = static_cast<OGRGmtLayer **>(
57
10.9k
        CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRGmtLayer *)));
58
10.9k
    papoLayers[nLayers] = poLayer;
59
10.9k
    nLayers++;
60
61
10.9k
    return TRUE;
62
10.9k
}
63
64
/************************************************************************/
65
/*                            ICreateLayer()                            */
66
/************************************************************************/
67
68
OGRLayer *
69
OGRGmtDataSource::ICreateLayer(const char *pszLayerName,
70
                               const OGRGeomFieldDefn *poGeomFieldDefn,
71
                               CSLConstList /*papszOptions*/)
72
458
{
73
458
    if (nLayers != 0)
74
377
        return nullptr;
75
76
81
    const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
77
81
    const auto poSRS =
78
81
        poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
79
80
    /* -------------------------------------------------------------------- */
81
    /*      Establish the geometry type.  Note this logic                   */
82
    /* -------------------------------------------------------------------- */
83
81
    const char *pszGeom = nullptr;
84
85
81
    switch (wkbFlatten(eType))
86
81
    {
87
0
        case wkbPoint:
88
0
            pszGeom = " @GPOINT";
89
0
            break;
90
1
        case wkbLineString:
91
1
            pszGeom = " @GLINESTRING";
92
1
            break;
93
2
        case wkbPolygon:
94
2
            pszGeom = " @GPOLYGON";
95
2
            break;
96
3
        case wkbMultiPoint:
97
3
            pszGeom = " @GMULTIPOINT";
98
3
            break;
99
0
        case wkbMultiLineString:
100
0
            pszGeom = " @GMULTILINESTRING";
101
0
            break;
102
0
        case wkbMultiPolygon:
103
0
            pszGeom = " @GMULTIPOLYGON";
104
0
            break;
105
75
        default:
106
75
            pszGeom = "";
107
75
            break;
108
81
    }
109
110
    /* -------------------------------------------------------------------- */
111
    /*      If this is the first layer for this datasource, and if the      */
112
    /*      datasource name ends in .gmt we will override the provided      */
113
    /*      layer name with the name from the gmt.                          */
114
    /* -------------------------------------------------------------------- */
115
116
81
    CPLString osPath = CPLGetPathSafe(GetDescription());
117
81
    CPLString osFilename(GetDescription());
118
81
    const char *pszFlags = "wb+";
119
120
81
    if (osFilename == "/dev/stdout")
121
0
        osFilename = "/vsistdout";
122
123
81
    if (STARTS_WITH(osFilename, "/vsistdout"))
124
0
        pszFlags = "wb";
125
81
    else if (!EQUAL(CPLGetExtensionSafe(GetDescription()).c_str(), "gmt"))
126
0
        osFilename = CPLFormFilenameSafe(osPath, pszLayerName, "gmt");
127
128
    /* -------------------------------------------------------------------- */
129
    /*      Open the file.                                                  */
130
    /* -------------------------------------------------------------------- */
131
81
    VSILFILE *fp = VSIFOpenL(osFilename, pszFlags);
132
81
    if (fp == nullptr)
133
0
    {
134
0
        CPLError(CE_Failure, CPLE_OpenFailed, "open(%s) failed: %s",
135
0
                 osFilename.c_str(), VSIStrerror(errno));
136
0
        return nullptr;
137
0
    }
138
139
    /* -------------------------------------------------------------------- */
140
    /*      Write out header.                                               */
141
    /* -------------------------------------------------------------------- */
142
81
    VSIFPrintfL(fp, "# @VGMT1.0%s\n", pszGeom);
143
81
    if (!STARTS_WITH(osFilename, "/vsistdout"))
144
81
    {
145
81
        VSIFPrintfL(fp, "# REGION_STUB                                      "
146
81
                        "                       \n");
147
81
    }
148
149
    /* -------------------------------------------------------------------- */
150
    /*      Write the projection, if possible.                              */
151
    /* -------------------------------------------------------------------- */
152
81
    if (poSRS != nullptr)
153
11
    {
154
11
        if (poSRS->GetAuthorityName(nullptr) &&
155
4
            EQUAL(poSRS->GetAuthorityName(nullptr), "EPSG"))
156
4
        {
157
4
            VSIFPrintfL(fp, "# @Je%s\n", poSRS->GetAuthorityCode(nullptr));
158
4
        }
159
160
11
        char *pszValue = nullptr;
161
11
        if (poSRS->exportToProj4(&pszValue) == OGRERR_NONE)
162
4
        {
163
4
            VSIFPrintfL(fp, "# @Jp\"%s\"\n", pszValue);
164
4
        }
165
11
        CPLFree(pszValue);
166
11
        pszValue = nullptr;
167
168
11
        if (poSRS->exportToWkt(&pszValue) == OGRERR_NONE)
169
4
        {
170
4
            char *pszEscapedWkt =
171
4
                CPLEscapeString(pszValue, -1, CPLES_BackslashQuotable);
172
173
4
            VSIFPrintfL(fp, "# @Jw\"%s\"\n", pszEscapedWkt);
174
4
            CPLFree(pszEscapedWkt);
175
4
        }
176
11
        CPLFree(pszValue);
177
11
    }
178
179
    /* -------------------------------------------------------------------- */
180
    /*      Return open layer handle.                                       */
181
    /* -------------------------------------------------------------------- */
182
81
    if (Open(osFilename, fp, poSRS, TRUE))
183
81
    {
184
81
        OGRLayer *poLayer = papoLayers[nLayers - 1];
185
81
        if (strcmp(pszGeom, "") != 0)
186
6
        {
187
6
            poLayer->GetLayerDefn()->SetGeomType(wkbFlatten(eType));
188
6
        }
189
81
        return poLayer;
190
81
    }
191
192
0
    VSIFCloseL(fp);
193
0
    return nullptr;
194
81
}
195
196
/************************************************************************/
197
/*                           TestCapability()                           */
198
/************************************************************************/
199
200
int OGRGmtDataSource::TestCapability(const char *pszCap) const
201
202
1.02k
{
203
1.02k
    if (EQUAL(pszCap, ODsCCreateLayer))
204
458
        return TRUE;
205
571
    else if (EQUAL(pszCap, ODsCZGeometries))
206
0
        return TRUE;
207
208
571
    return FALSE;
209
1.02k
}
210
211
/************************************************************************/
212
/*                              GetLayer()                              */
213
/************************************************************************/
214
215
const OGRLayer *OGRGmtDataSource::GetLayer(int iLayer) const
216
217
10.7k
{
218
10.7k
    if (iLayer < 0 || iLayer >= nLayers)
219
0
        return nullptr;
220
221
10.7k
    return papoLayers[iLayer];
222
10.7k
}