• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 15885686134

25 Jun 2025 07:44PM UTC coverage: 71.084%. Remained the same
15885686134

push

github

rouault
gdal_priv.h: fix C++11 compatibility

573814 of 807237 relevant lines covered (71.08%)

250621.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.03
/frmts/ngsgeoid/ngsgeoiddataset.cpp
1
/******************************************************************************
2
 *
3
 * Project:  NGSGEOID driver
4
 * Purpose:  GDALDataset driver for NGSGEOID dataset.
5
 * Author:   Even Rouault, <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12

13
#include "cpl_string.h"
14
#include "cpl_vsi_virtual.h"
15
#include "gdal_frmts.h"
16
#include "gdal_pam.h"
17
#include "ogr_srs_api.h"
18

19
#define HEADER_SIZE (4 * 8 + 3 * 4)
20

21
/************************************************************************/
22
/* ==================================================================== */
23
/*                            NGSGEOIDDataset                           */
24
/* ==================================================================== */
25
/************************************************************************/
26

27
class NGSGEOIDRasterBand;
28

29
class NGSGEOIDDataset final : public GDALPamDataset
30
{
31
    friend class NGSGEOIDRasterBand;
32

33
    VSILFILE *fp{};
34
    GDALGeoTransform m_gt{};
35
    int bIsLittleEndian{};
36
    mutable OGRSpatialReference m_oSRS{};
37

38
    static int GetHeaderInfo(const GByte *pBuffer, GDALGeoTransform &gt,
39
                             int *pnRows, int *pnCols, int *pbIsLittleEndian);
40

41
    CPL_DISALLOW_COPY_ASSIGN(NGSGEOIDDataset)
42

43
  public:
44
    NGSGEOIDDataset();
45
    virtual ~NGSGEOIDDataset();
46

47
    virtual CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
48
    const OGRSpatialReference *GetSpatialRef() const override;
49

50
    static GDALDataset *Open(GDALOpenInfo *);
51
    static int Identify(GDALOpenInfo *);
52
};
53

54
/************************************************************************/
55
/* ==================================================================== */
56
/*                          NGSGEOIDRasterBand                          */
57
/* ==================================================================== */
58
/************************************************************************/
59

60
class NGSGEOIDRasterBand final : public GDALPamRasterBand
61
{
62
    friend class NGSGEOIDDataset;
63

64
  public:
65
    explicit NGSGEOIDRasterBand(NGSGEOIDDataset *);
66

67
    virtual CPLErr IReadBlock(int, int, void *) override;
68

69
    virtual const char *GetUnitType() override
×
70
    {
71
        return "m";
×
72
    }
73
};
74

75
/************************************************************************/
76
/*                        NGSGEOIDRasterBand()                          */
77
/************************************************************************/
78

79
NGSGEOIDRasterBand::NGSGEOIDRasterBand(NGSGEOIDDataset *poDSIn)
4✔
80

81
{
82
    poDS = poDSIn;
4✔
83
    nBand = 1;
4✔
84

85
    eDataType = GDT_Float32;
4✔
86

87
    nBlockXSize = poDS->GetRasterXSize();
4✔
88
    nBlockYSize = 1;
4✔
89
}
4✔
90

91
/************************************************************************/
92
/*                             IReadBlock()                             */
93
/************************************************************************/
94

95
CPLErr NGSGEOIDRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
2✔
96
                                      void *pImage)
97

98
{
99
    NGSGEOIDDataset *poGDS = reinterpret_cast<NGSGEOIDDataset *>(poDS);
2✔
100

101
    /* First values in the file corresponds to the south-most line of the
102
     * imagery */
103
    VSIFSeekL(poGDS->fp,
2✔
104
              HEADER_SIZE +
2✔
105
                  static_cast<vsi_l_offset>(nRasterYSize - 1 - nBlockYOff) *
2✔
106
                      nRasterXSize * 4,
2✔
107
              SEEK_SET);
108

109
    if (static_cast<int>(VSIFReadL(pImage, 4, nRasterXSize, poGDS->fp)) !=
2✔
110
        nRasterXSize)
2✔
111
        return CE_Failure;
×
112

113
#ifdef CPL_MSB
114
    if (poGDS->bIsLittleEndian)
115
    {
116
        GDALSwapWords(pImage, 4, nRasterXSize, 4);
117
    }
118
#endif
119

120
#ifdef CPL_LSB
121
    if (!poGDS->bIsLittleEndian)
2✔
122
    {
123
        GDALSwapWords(pImage, 4, nRasterXSize, 4);
1✔
124
    }
125
#endif
126

127
    return CE_None;
2✔
128
}
129

130
/************************************************************************/
131
/*                          ~NGSGEOIDDataset()                          */
132
/************************************************************************/
133

134
NGSGEOIDDataset::NGSGEOIDDataset() : fp(nullptr), bIsLittleEndian(TRUE)
4✔
135
{
136
    m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4✔
137
}
4✔
138

139
/************************************************************************/
140
/*                           ~NGSGEOIDDataset()                         */
141
/************************************************************************/
142

143
NGSGEOIDDataset::~NGSGEOIDDataset()
8✔
144

145
{
146
    FlushCache(true);
4✔
147
    if (fp)
4✔
148
        VSIFCloseL(fp);
4✔
149
}
8✔
150

151
/************************************************************************/
152
/*                            GetHeaderInfo()                           */
153
/************************************************************************/
154

155
int NGSGEOIDDataset::GetHeaderInfo(const GByte *pBuffer, GDALGeoTransform &gt,
2,989✔
156
                                   int *pnRows, int *pnCols,
157
                                   int *pbIsLittleEndian)
158
{
159
    /* First check IKIND marker to determine if the file */
160
    /* is in little or big-endian order, and if it is a valid */
161
    /* NGSGEOID dataset */
162
    int nIKIND;
163
    memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
2,989✔
164
    CPL_LSBPTR32(&nIKIND);
2,989✔
165
    if (nIKIND == 1)
2,989✔
166
    {
167
        *pbIsLittleEndian = TRUE;
27✔
168
    }
169
    else
170
    {
171
        memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
2,962✔
172
        CPL_MSBPTR32(&nIKIND);
2,962✔
173
        if (nIKIND == 1)
2,962✔
174
        {
175
            *pbIsLittleEndian = FALSE;
7✔
176
        }
177
        else
178
        {
179
            return FALSE;
2,955✔
180
        }
181
    }
182

183
    double dfSLAT;
184
    memcpy(&dfSLAT, pBuffer, 8);
34✔
185
    if (*pbIsLittleEndian)
34✔
186
    {
187
        CPL_LSBPTR64(&dfSLAT);
27✔
188
    }
189
    else
190
    {
191
        CPL_MSBPTR64(&dfSLAT);
7✔
192
    }
193
    pBuffer += 8;
34✔
194

195
    double dfWLON;
196
    memcpy(&dfWLON, pBuffer, 8);
34✔
197
    if (*pbIsLittleEndian)
34✔
198
    {
199
        CPL_LSBPTR64(&dfWLON);
27✔
200
    }
201
    else
202
    {
203
        CPL_MSBPTR64(&dfWLON);
7✔
204
    }
205
    pBuffer += 8;
34✔
206

207
    double dfDLAT;
208
    memcpy(&dfDLAT, pBuffer, 8);
34✔
209
    if (*pbIsLittleEndian)
34✔
210
    {
211
        CPL_LSBPTR64(&dfDLAT);
27✔
212
    }
213
    else
214
    {
215
        CPL_MSBPTR64(&dfDLAT);
7✔
216
    }
217
    pBuffer += 8;
34✔
218

219
    double dfDLON;
220
    memcpy(&dfDLON, pBuffer, 8);
34✔
221
    if (*pbIsLittleEndian)
34✔
222
    {
223
        CPL_LSBPTR64(&dfDLON);
27✔
224
    }
225
    else
226
    {
227
        CPL_MSBPTR64(&dfDLON);
7✔
228
    }
229
    pBuffer += 8;
34✔
230

231
    int nNLAT;
232
    memcpy(&nNLAT, pBuffer, 4);
34✔
233
    if (*pbIsLittleEndian)
34✔
234
    {
235
        CPL_LSBPTR32(&nNLAT);
27✔
236
    }
237
    else
238
    {
239
        CPL_MSBPTR32(&nNLAT);
7✔
240
    }
241
    pBuffer += 4;
34✔
242

243
    int nNLON;
244
    memcpy(&nNLON, pBuffer, 4);
34✔
245
    if (*pbIsLittleEndian)
34✔
246
    {
247
        CPL_LSBPTR32(&nNLON);
27✔
248
    }
249
    else
250
    {
251
        CPL_MSBPTR32(&nNLON);
7✔
252
    }
253
    /*pBuffer += 4;*/
254

255
    /*CPLDebug("NGSGEOID", "SLAT=%f, WLON=%f, DLAT=%f, DLON=%f, NLAT=%d,
256
       NLON=%d, IKIND=%d", dfSLAT, dfWLON, dfDLAT, dfDLON, nNLAT, nNLON,
257
       nIKIND);*/
258

259
    if (nNLAT <= 0 || nNLON <= 0 || dfDLAT <= 1e-15 || dfDLON <= 1e-15)
34✔
260
        return FALSE;
22✔
261

262
    /* Grids go over +180 in longitude */
263
    // Test written that way to be robust to NaN values
264
    if (!(dfSLAT >= -90.0 && dfSLAT + nNLAT * dfDLAT <= 90.0 &&
12✔
265
          dfWLON >= -180.0 && dfWLON + nNLON * dfDLON <= 360.0))
12✔
266
        return FALSE;
×
267

268
    gt[0] = dfWLON - dfDLON / 2;
12✔
269
    gt[1] = dfDLON;
12✔
270
    gt[2] = 0.0;
12✔
271
    gt[3] = dfSLAT + nNLAT * dfDLAT - dfDLAT / 2;
12✔
272
    gt[4] = 0.0;
12✔
273
    gt[5] = -dfDLAT;
12✔
274

275
    *pnRows = nNLAT;
12✔
276
    *pnCols = nNLON;
12✔
277

278
    return TRUE;
12✔
279
}
280

281
/************************************************************************/
282
/*                             Identify()                               */
283
/************************************************************************/
284

285
int NGSGEOIDDataset::Identify(GDALOpenInfo *poOpenInfo)
56,338✔
286
{
287
    if (poOpenInfo->nHeaderBytes < HEADER_SIZE)
56,338✔
288
        return FALSE;
53,355✔
289

290
    GDALGeoTransform gt;
2,983✔
291
    int nRows, nCols;
292
    int bIsLittleEndian;
293
    if (!GetHeaderInfo(poOpenInfo->pabyHeader, gt, &nRows, &nCols,
2,983✔
294
                       &bIsLittleEndian))
295
        return FALSE;
2,977✔
296

297
    return TRUE;
8✔
298
}
299

300
/************************************************************************/
301
/*                                Open()                                */
302
/************************************************************************/
303

304
GDALDataset *NGSGEOIDDataset::Open(GDALOpenInfo *poOpenInfo)
4✔
305

306
{
307
    if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
4✔
308
        return nullptr;
×
309

310
    if (poOpenInfo->eAccess == GA_Update)
4✔
311
    {
312
        ReportUpdateNotSupportedByDriver("NGSGEOID");
×
313
        return nullptr;
×
314
    }
315

316
    /* -------------------------------------------------------------------- */
317
    /*      Create a corresponding GDALDataset.                             */
318
    /* -------------------------------------------------------------------- */
319
    NGSGEOIDDataset *poDS = new NGSGEOIDDataset();
4✔
320
    poDS->fp = poOpenInfo->fpL;
4✔
321
    poOpenInfo->fpL = nullptr;
4✔
322

323
    int nRows = 0, nCols = 0;
4✔
324
    GetHeaderInfo(poOpenInfo->pabyHeader, poDS->m_gt, &nRows, &nCols,
4✔
325
                  &poDS->bIsLittleEndian);
326
    poDS->nRasterXSize = nCols;
4✔
327
    poDS->nRasterYSize = nRows;
4✔
328

329
    /* -------------------------------------------------------------------- */
330
    /*      Create band information objects.                                */
331
    /* -------------------------------------------------------------------- */
332
    poDS->nBands = 1;
4✔
333
    poDS->SetBand(1, new NGSGEOIDRasterBand(poDS));
4✔
334

335
    /* -------------------------------------------------------------------- */
336
    /*      Initialize any PAM information.                                 */
337
    /* -------------------------------------------------------------------- */
338
    poDS->SetDescription(poOpenInfo->pszFilename);
4✔
339
    poDS->TryLoadXML();
4✔
340

341
    /* -------------------------------------------------------------------- */
342
    /*      Support overviews.                                              */
343
    /* -------------------------------------------------------------------- */
344
    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
4✔
345
    return poDS;
4✔
346
}
347

348
/************************************************************************/
349
/*                          GetGeoTransform()                           */
350
/************************************************************************/
351

352
CPLErr NGSGEOIDDataset::GetGeoTransform(GDALGeoTransform &gt) const
2✔
353

354
{
355
    gt = m_gt;
2✔
356

357
    return CE_None;
2✔
358
}
359

360
/************************************************************************/
361
/*                         GetSpatialRef()                              */
362
/************************************************************************/
363

364
const OGRSpatialReference *NGSGEOIDDataset::GetSpatialRef() const
2✔
365
{
366
    if (!m_oSRS.IsEmpty())
2✔
367
    {
368
        return &m_oSRS;
×
369
    }
370

371
    const CPLString osFilename =
372
        CPLString(CPLGetBasenameSafe(GetDescription())).tolower();
6✔
373

374
    // See https://www.ngs.noaa.gov/GEOID/GEOID12B/faq_2012B.shtml
375

376
    // GEOID2012 files ?
377
    if (STARTS_WITH(osFilename, "g2012") && osFilename.size() >= 7)
2✔
378
    {
379
        if (osFilename[6] == 'h' /* Hawai */ ||
×
380
            osFilename[6] == 's' /* Samoa */)
×
381
        {
382
            // NAD83 (PA11)
383
            m_oSRS.importFromEPSG(6322);
×
384
        }
385
        else if (osFilename[6] == 'g' /* Guam */)
×
386
        {
387
            // NAD83 (MA11)
388
            m_oSRS.importFromEPSG(6325);
×
389
        }
390
        else
391
        {
392
            // NAD83 (2011)
393
            m_oSRS.importFromEPSG(6318);
×
394
        }
395

396
        return &m_oSRS;
×
397
    }
398

399
    // USGG2012 files ? We should return IGS08, but there is only a
400
    // geocentric CRS in EPSG, so manually forge a geographic one from it
401
    if (STARTS_WITH(osFilename, "s2012"))
2✔
402
    {
403
        m_oSRS.importFromWkt(
×
404
            "GEOGCS[\"IGS08\",\n"
405
            "    DATUM[\"IGS08\",\n"
406
            "        SPHEROID[\"GRS 1980\",6378137,298.257222101,\n"
407
            "            AUTHORITY[\"EPSG\",\"7019\"]],\n"
408
            "        AUTHORITY[\"EPSG\",\"1141\"]],\n"
409
            "    PRIMEM[\"Greenwich\",0,\n"
410
            "        AUTHORITY[\"EPSG\",\"8901\"]],\n"
411
            "    UNIT[\"degree\",0.0174532925199433,\n"
412
            "        AUTHORITY[\"EPSG\",\"9122\"]]]");
413
        return &m_oSRS;
×
414
    }
415

416
    m_oSRS.importFromWkt(SRS_WKT_WGS84_LAT_LONG);
2✔
417
    return &m_oSRS;
2✔
418
}
419

420
/************************************************************************/
421
/*                       GDALRegister_NGSGEOID()                        */
422
/************************************************************************/
423

424
void GDALRegister_NGSGEOID()
1,911✔
425

426
{
427
    if (GDALGetDriverByName("NGSGEOID") != nullptr)
1,911✔
428
        return;
282✔
429

430
    GDALDriver *poDriver = new GDALDriver();
1,629✔
431

432
    poDriver->SetDescription("NGSGEOID");
1,629✔
433
    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1,629✔
434
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "NOAA NGS Geoid Height Grids");
1,629✔
435
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
1,629✔
436
                              "drivers/raster/ngsgeoid.html");
1,629✔
437
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "bin");
1,629✔
438

439
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1,629✔
440

441
    poDriver->pfnOpen = NGSGEOIDDataset::Open;
1,629✔
442
    poDriver->pfnIdentify = NGSGEOIDDataset::Identify;
1,629✔
443

444
    GetGDALDriverManager()->RegisterDriver(poDriver);
1,629✔
445
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc