• 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

92.47
/frmts/raw/snodasdataset.cpp
1
/******************************************************************************
2
 *
3
 * Project:  SNODAS driver
4
 * Purpose:  Implementation of SNODASDataset
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 "gdal_frmts.h"
15
#include "ogr_srs_api.h"
16
#include "rawdataset.h"
17

18
/************************************************************************/
19
/* ==================================================================== */
20
/*                            SNODASDataset                             */
21
/* ==================================================================== */
22
/************************************************************************/
23

24
class SNODASRasterBand;
25

26
class SNODASDataset final : public RawDataset
27
{
28
    CPLString osDataFilename{};
29
    bool bGotTransform;
30
    GDALGeoTransform m_gt{};
31
    bool bHasNoData;
32
    double dfNoData;
33
    bool bHasMin;
34
    double dfMin;
35
    int bHasMax;
36
    double dfMax;
37
    OGRSpatialReference m_oSRS{};
38

39
    friend class SNODASRasterBand;
40

41
    CPL_DISALLOW_COPY_ASSIGN(SNODASDataset)
42

43
    CPLErr Close() override;
44

45
  public:
46
    SNODASDataset();
47
    ~SNODASDataset() override;
48

49
    CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
50

51
    const OGRSpatialReference *GetSpatialRef() const override
1✔
52
    {
53
        return &m_oSRS;
1✔
54
    }
55

56
    char **GetFileList() override;
57

58
    static GDALDataset *Open(GDALOpenInfo *);
59
    static int Identify(GDALOpenInfo *);
60
};
61

62
/************************************************************************/
63
/* ==================================================================== */
64
/*                            SNODASRasterBand                          */
65
/* ==================================================================== */
66
/************************************************************************/
67

68
class SNODASRasterBand final : public RawRasterBand
69
{
70
    CPL_DISALLOW_COPY_ASSIGN(SNODASRasterBand)
71

72
  public:
73
    SNODASRasterBand(VSILFILE *fpRaw, int nXSize, int nYSize);
74

75
    ~SNODASRasterBand() override
6✔
76
    {
3✔
77
    }
6✔
78

79
    double GetNoDataValue(int *pbSuccess = nullptr) override;
80
    double GetMinimum(int *pbSuccess = nullptr) override;
81
    double GetMaximum(int *pbSuccess = nullptr) override;
82
};
83

84
/************************************************************************/
85
/*                         SNODASRasterBand()                           */
86
/************************************************************************/
87

88
SNODASRasterBand::SNODASRasterBand(VSILFILE *fpRawIn, int nXSize, int nYSize)
3✔
89
    : RawRasterBand(fpRawIn, 0, 2, nXSize * 2, GDT_Int16, !CPL_IS_LSB, nXSize,
90
                    nYSize, RawRasterBand::OwnFP::YES)
3✔
91
{
92
}
3✔
93

94
/************************************************************************/
95
/*                          GetNoDataValue()                            */
96
/************************************************************************/
97

98
double SNODASRasterBand::GetNoDataValue(int *pbSuccess)
1✔
99
{
100
    SNODASDataset *poGDS = reinterpret_cast<SNODASDataset *>(poDS);
1✔
101
    if (pbSuccess)
1✔
102
        *pbSuccess = poGDS->bHasNoData;
1✔
103

104
    if (poGDS->bHasNoData)
1✔
105
        return poGDS->dfNoData;
1✔
106

107
    return RawRasterBand::GetNoDataValue(pbSuccess);
×
108
}
109

110
/************************************************************************/
111
/*                            GetMinimum()                              */
112
/************************************************************************/
113

114
double SNODASRasterBand::GetMinimum(int *pbSuccess)
1✔
115
{
116
    SNODASDataset *poGDS = reinterpret_cast<SNODASDataset *>(poDS);
1✔
117
    if (pbSuccess)
1✔
118
        *pbSuccess = poGDS->bHasMin;
1✔
119

120
    if (poGDS->bHasMin)
1✔
121
        return poGDS->dfMin;
1✔
122

123
    return RawRasterBand::GetMinimum(pbSuccess);
×
124
}
125

126
/************************************************************************/
127
/*                            GetMaximum()                             */
128
/************************************************************************/
129

130
double SNODASRasterBand::GetMaximum(int *pbSuccess)
1✔
131
{
132
    SNODASDataset *poGDS = reinterpret_cast<SNODASDataset *>(poDS);
1✔
133
    if (pbSuccess)
1✔
134
        *pbSuccess = poGDS->bHasMax;
1✔
135

136
    if (poGDS->bHasMax)
1✔
137
        return poGDS->dfMax;
1✔
138

139
    return RawRasterBand::GetMaximum(pbSuccess);
×
140
}
141

142
/************************************************************************/
143
/* ==================================================================== */
144
/*                            SNODASDataset                             */
145
/* ==================================================================== */
146
/************************************************************************/
147

148
/************************************************************************/
149
/*                           SNODASDataset()                            */
150
/************************************************************************/
151

152
SNODASDataset::SNODASDataset()
3✔
153
    : bGotTransform(false), bHasNoData(false), dfNoData(0.0), bHasMin(false),
154
      dfMin(0.0), bHasMax(false), dfMax(0.0)
3✔
155
{
156
    m_oSRS.SetFromUserInput(SRS_WKT_WGS84_LAT_LONG);
3✔
157
    m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
3✔
158
}
3✔
159

160
/************************************************************************/
161
/*                           ~SNODASDataset()                           */
162
/************************************************************************/
163

164
SNODASDataset::~SNODASDataset()
6✔
165

166
{
167
    SNODASDataset::Close();
3✔
168
}
6✔
169

170
/************************************************************************/
171
/*                              Close()                                 */
172
/************************************************************************/
173

174
CPLErr SNODASDataset::Close()
6✔
175
{
176
    CPLErr eErr = CE_None;
6✔
177
    if (nOpenFlags != OPEN_FLAGS_CLOSED)
6✔
178
    {
179
        if (SNODASDataset::FlushCache(true) != CE_None)
3✔
180
            eErr = CE_Failure;
×
181

182
        if (GDALPamDataset::Close() != CE_None)
3✔
183
            eErr = CE_Failure;
×
184
    }
185
    return eErr;
6✔
186
}
187

188
/************************************************************************/
189
/*                          GetGeoTransform()                           */
190
/************************************************************************/
191

192
CPLErr SNODASDataset::GetGeoTransform(GDALGeoTransform &gt) const
1✔
193

194
{
195
    if (bGotTransform)
1✔
196
    {
197
        gt = m_gt;
1✔
198
        return CE_None;
1✔
199
    }
200

201
    return GDALPamDataset::GetGeoTransform(gt);
×
202
}
203

204
/************************************************************************/
205
/*                            GetFileList()                             */
206
/************************************************************************/
207

208
char **SNODASDataset::GetFileList()
2✔
209

210
{
211
    char **papszFileList = GDALPamDataset::GetFileList();
2✔
212

213
    papszFileList = CSLAddString(papszFileList, osDataFilename);
2✔
214

215
    return papszFileList;
2✔
216
}
217

218
/************************************************************************/
219
/*                            Identify()                                */
220
/************************************************************************/
221

222
int SNODASDataset::Identify(GDALOpenInfo *poOpenInfo)
57,073✔
223
{
224
    if (poOpenInfo->nHeaderBytes == 0)
57,073✔
225
        return FALSE;
53,286✔
226

227
    return STARTS_WITH_CI(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
3,787✔
228
                          "Format version: NOHRSC GIS/RS raster file v1.1");
229
}
230

231
/************************************************************************/
232
/*                                Open()                                */
233
/************************************************************************/
234

235
GDALDataset *SNODASDataset::Open(GDALOpenInfo *poOpenInfo)
3✔
236

237
{
238
    if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
3✔
239
        return nullptr;
×
240

241
    /* -------------------------------------------------------------------- */
242
    /*      Confirm the requested access is supported.                      */
243
    /* -------------------------------------------------------------------- */
244
    if (poOpenInfo->eAccess == GA_Update)
3✔
245
    {
246
        ReportUpdateNotSupportedByDriver("SNODAS");
×
247
        return nullptr;
×
248
    }
249

250
    int nRows = -1;
3✔
251
    int nCols = -1;
3✔
252
    CPLString osDataFilename;
6✔
253
    bool bIsInteger = false;
3✔
254
    bool bIs2Bytes = false;
3✔
255
    double dfNoData = 0;
3✔
256
    bool bHasNoData = false;
3✔
257
    double dfMin = 0;
3✔
258
    bool bHasMin = false;
3✔
259
    double dfMax = 0;
3✔
260
    bool bHasMax = false;
3✔
261
    double dfMinX = 0.0;
3✔
262
    double dfMinY = 0.0;
3✔
263
    double dfMaxX = 0.0;
3✔
264
    double dfMaxY = 0.0;
3✔
265
    bool bHasMinX = false;
3✔
266
    bool bHasMinY = false;
3✔
267
    bool bHasMaxX = false;
3✔
268
    bool bHasMaxY = false;
3✔
269
    bool bNotProjected = false;
3✔
270
    bool bIsWGS84 = false;
3✔
271
    CPLString osDataUnits;
6✔
272
    CPLString osDescription;
6✔
273
    int nStartYear = -1;
3✔
274
    int nStartMonth = -1;
3✔
275
    int nStartDay = -1;
3✔
276
    int nStartHour = -1;
3✔
277
    int nStartMinute = -1;
3✔
278
    int nStartSecond = -1;
3✔
279
    int nStopYear = -1;
3✔
280
    int nStopMonth = -1;
3✔
281
    int nStopDay = -1;
3✔
282
    int nStopHour = -1;
3✔
283
    int nStopMinute = -1;
3✔
284
    int nStopSecond = -1;
3✔
285

286
    const char *pszLine = nullptr;
3✔
287
    while ((pszLine = CPLReadLine2L(poOpenInfo->fpL, 1024, nullptr)) != nullptr)
324✔
288
    {
289
        char **papszTokens =
290
            CSLTokenizeStringComplex(pszLine, ":", TRUE, FALSE);
321✔
291
        if (CSLCount(papszTokens) != 2)
321✔
292
        {
293
            CSLDestroy(papszTokens);
3✔
294
            continue;
3✔
295
        }
296
        if (papszTokens[1][0] == ' ')
318✔
297
            memmove(papszTokens[1], papszTokens[1] + 1,
318✔
298
                    strlen(papszTokens[1] + 1) + 1);
318✔
299

300
        if (EQUAL(papszTokens[0], "Data file pathname"))
318✔
301
        {
302
            osDataFilename = papszTokens[1];
3✔
303
        }
304
        else if (EQUAL(papszTokens[0], "Description"))
315✔
305
        {
306
            osDescription = papszTokens[1];
3✔
307
        }
308
        else if (EQUAL(papszTokens[0], "Data units"))
312✔
309
        {
310
            osDataUnits = papszTokens[1];
3✔
311
        }
312

313
        else if (EQUAL(papszTokens[0], "Start year"))
309✔
314
            nStartYear = atoi(papszTokens[1]);
3✔
315
        else if (EQUAL(papszTokens[0], "Start month"))
306✔
316
            nStartMonth = atoi(papszTokens[1]);
3✔
317
        else if (EQUAL(papszTokens[0], "Start day"))
303✔
318
            nStartDay = atoi(papszTokens[1]);
3✔
319
        else if (EQUAL(papszTokens[0], "Start hour"))
300✔
320
            nStartHour = atoi(papszTokens[1]);
3✔
321
        else if (EQUAL(papszTokens[0], " Start minute"))
297✔
322
            nStartMinute = atoi(papszTokens[1]);
×
323
        else if (EQUAL(papszTokens[0], "Start second"))
297✔
324
            nStartSecond = atoi(papszTokens[1]);
3✔
325

326
        else if (EQUAL(papszTokens[0], "Stop year"))
294✔
327
            nStopYear = atoi(papszTokens[1]);
3✔
328
        else if (EQUAL(papszTokens[0], "Stop month"))
291✔
329
            nStopMonth = atoi(papszTokens[1]);
3✔
330
        else if (EQUAL(papszTokens[0], "Stop day"))
288✔
331
            nStopDay = atoi(papszTokens[1]);
3✔
332
        else if (EQUAL(papszTokens[0], "Stop hour"))
285✔
333
            nStopHour = atoi(papszTokens[1]);
3✔
334
        else if (EQUAL(papszTokens[0], "Stop minute"))
282✔
335
            nStopMinute = atoi(papszTokens[1]);
3✔
336
        else if (EQUAL(papszTokens[0], "Stop second"))
279✔
337
            nStopSecond = atoi(papszTokens[1]);
3✔
338

339
        else if (EQUAL(papszTokens[0], "Number of columns"))
276✔
340
        {
341
            nCols = atoi(papszTokens[1]);
3✔
342
        }
343
        else if (EQUAL(papszTokens[0], "Number of rows"))
273✔
344
        {
345
            nRows = atoi(papszTokens[1]);
3✔
346
        }
347
        else if (EQUAL(papszTokens[0], "Data type"))
270✔
348
        {
349
            bIsInteger = EQUAL(papszTokens[1], "integer");
3✔
350
        }
351
        else if (EQUAL(papszTokens[0], "Data bytes per pixel"))
267✔
352
        {
353
            bIs2Bytes = EQUAL(papszTokens[1], "2");
3✔
354
        }
355
        else if (EQUAL(papszTokens[0], "Projected"))
264✔
356
        {
357
            bNotProjected = EQUAL(papszTokens[1], "no");
3✔
358
        }
359
        else if (EQUAL(papszTokens[0], "Horizontal datum"))
261✔
360
        {
361
            bIsWGS84 = EQUAL(papszTokens[1], "WGS84");
3✔
362
        }
363
        else if (EQUAL(papszTokens[0], "No data value"))
258✔
364
        {
365
            bHasNoData = true;
3✔
366
            dfNoData = CPLAtofM(papszTokens[1]);
3✔
367
        }
368
        else if (EQUAL(papszTokens[0], "Minimum data value"))
255✔
369
        {
370
            bHasMin = true;
3✔
371
            dfMin = CPLAtofM(papszTokens[1]);
3✔
372
        }
373
        else if (EQUAL(papszTokens[0], "Maximum data value"))
252✔
374
        {
375
            bHasMax = true;
3✔
376
            dfMax = CPLAtofM(papszTokens[1]);
3✔
377
        }
378
        else if (EQUAL(papszTokens[0], "Minimum x-axis coordinate"))
249✔
379
        {
380
            bHasMinX = true;
3✔
381
            dfMinX = CPLAtofM(papszTokens[1]);
3✔
382
        }
383
        else if (EQUAL(papszTokens[0], "Minimum y-axis coordinate"))
246✔
384
        {
385
            bHasMinY = true;
3✔
386
            dfMinY = CPLAtofM(papszTokens[1]);
3✔
387
        }
388
        else if (EQUAL(papszTokens[0], "Maximum x-axis coordinate"))
243✔
389
        {
390
            bHasMaxX = true;
3✔
391
            dfMaxX = CPLAtofM(papszTokens[1]);
3✔
392
        }
393
        else if (EQUAL(papszTokens[0], "Maximum y-axis coordinate"))
240✔
394
        {
395
            bHasMaxY = true;
3✔
396
            dfMaxY = CPLAtofM(papszTokens[1]);
3✔
397
        }
398

399
        CSLDestroy(papszTokens);
318✔
400
    }
401

402
    CPL_IGNORE_RET_VAL(VSIFCloseL(poOpenInfo->fpL));
3✔
403
    poOpenInfo->fpL = nullptr;
3✔
404

405
    /* -------------------------------------------------------------------- */
406
    /*      Did we get the required keywords?  If not we return with        */
407
    /*      this never having been considered to be a match. This isn't     */
408
    /*      an error!                                                       */
409
    /* -------------------------------------------------------------------- */
410
    if (nRows == -1 || nCols == -1 || !bIsInteger || !bIs2Bytes)
3✔
411
        return nullptr;
×
412

413
    if (!bNotProjected || !bIsWGS84)
3✔
414
        return nullptr;
×
415

416
    if (osDataFilename.empty())
3✔
417
        return nullptr;
×
418

419
    if (!GDALCheckDatasetDimensions(nCols, nRows))
3✔
420
        return nullptr;
×
421

422
    /* -------------------------------------------------------------------- */
423
    /*      Open target binary file.                                        */
424
    /* -------------------------------------------------------------------- */
425
    const std::string osPath = CPLGetPathSafe(poOpenInfo->pszFilename);
6✔
426
    osDataFilename =
427
        CPLFormFilenameSafe(osPath.c_str(), osDataFilename, nullptr);
3✔
428

429
    VSILFILE *fpRaw = VSIFOpenL(osDataFilename, "rb");
3✔
430

431
    if (fpRaw == nullptr)
3✔
432
        return nullptr;
×
433

434
    /* -------------------------------------------------------------------- */
435
    /*      Create a corresponding GDALDataset.                             */
436
    /* -------------------------------------------------------------------- */
437
    auto poDS = std::make_unique<SNODASDataset>();
6✔
438

439
    poDS->nRasterXSize = nCols;
3✔
440
    poDS->nRasterYSize = nRows;
3✔
441
    poDS->osDataFilename = std::move(osDataFilename);
3✔
442
    poDS->bHasNoData = bHasNoData;
3✔
443
    poDS->dfNoData = dfNoData;
3✔
444
    poDS->bHasMin = bHasMin;
3✔
445
    poDS->dfMin = dfMin;
3✔
446
    poDS->bHasMax = bHasMax;
3✔
447
    poDS->dfMax = dfMax;
3✔
448
    if (bHasMinX && bHasMinY && bHasMaxX && bHasMaxY)
3✔
449
    {
450
        poDS->bGotTransform = true;
3✔
451
        poDS->m_gt[0] = dfMinX;
3✔
452
        poDS->m_gt[1] = (dfMaxX - dfMinX) / nCols;
3✔
453
        poDS->m_gt[2] = 0.0;
3✔
454
        poDS->m_gt[3] = dfMaxY;
3✔
455
        poDS->m_gt[4] = 0.0;
3✔
456
        poDS->m_gt[5] = -(dfMaxY - dfMinY) / nRows;
3✔
457
    }
458

459
    if (!osDescription.empty())
3✔
460
        poDS->SetMetadataItem("Description", osDescription);
3✔
461
    if (!osDataUnits.empty())
3✔
462
        poDS->SetMetadataItem("Data_Units", osDataUnits);
3✔
463
    if (nStartYear != -1 && nStartMonth != -1 && nStartDay != -1 &&
3✔
464
        nStartHour != -1 && nStartMinute != -1 && nStartSecond != -1)
3✔
465
        poDS->SetMetadataItem(
×
466
            "Start_Date",
467
            CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d", nStartYear, nStartMonth,
468
                       nStartDay, nStartHour, nStartMinute, nStartSecond));
×
469
    if (nStopYear != -1 && nStopMonth != -1 && nStopDay != -1 &&
3✔
470
        nStopHour != -1 && nStopMinute != -1 && nStopSecond != -1)
3✔
471
        poDS->SetMetadataItem("Stop_Date",
6✔
472
                              CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
473
                                         nStopYear, nStopMonth, nStopDay,
474
                                         nStopHour, nStopMinute, nStopSecond));
3✔
475

476
    /* -------------------------------------------------------------------- */
477
    /*      Create band information objects.                                */
478
    /* -------------------------------------------------------------------- */
479
    auto poBand = std::make_unique<SNODASRasterBand>(fpRaw, nCols, nRows);
6✔
480
    if (!poBand->IsValid())
3✔
481
        return nullptr;
×
482
    poDS->SetBand(1, std::move(poBand));
3✔
483

484
    /* -------------------------------------------------------------------- */
485
    /*      Initialize any PAM information.                                 */
486
    /* -------------------------------------------------------------------- */
487
    poDS->SetDescription(poOpenInfo->pszFilename);
3✔
488
    poDS->TryLoadXML();
3✔
489

490
    /* -------------------------------------------------------------------- */
491
    /*      Check for overviews.                                            */
492
    /* -------------------------------------------------------------------- */
493
    poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
3✔
494

495
    return poDS.release();
3✔
496
}
497

498
/************************************************************************/
499
/*                       GDALRegister_SNODAS()                          */
500
/************************************************************************/
501

502
void GDALRegister_SNODAS()
1,911✔
503

504
{
505
    if (GDALGetDriverByName("SNODAS") != nullptr)
1,911✔
506
        return;
282✔
507

508
    GDALDriver *poDriver = new GDALDriver();
1,629✔
509

510
    poDriver->SetDescription("SNODAS");
1,629✔
511
    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1,629✔
512
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
1,629✔
513
                              "Snow Data Assimilation System");
1,629✔
514
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/snodas.html");
1,629✔
515
    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdr");
1,629✔
516
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1,629✔
517

518
    poDriver->pfnOpen = SNODASDataset::Open;
1,629✔
519
    poDriver->pfnIdentify = SNODASDataset::Identify;
1,629✔
520

521
    GetGDALDriverManager()->RegisterDriver(poDriver);
1,629✔
522
}
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