Coverage Report

Created: 2025-06-13 06:29

/src/gdal/gcore/gdal_rat.h
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  GDAL Core
4
 * Purpose:  GDALRasterAttributeTable class declarations.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef GDAL_RAT_H_INCLUDED
14
#define GDAL_RAT_H_INCLUDED
15
16
#include "cpl_minixml.h"
17
#include "gdal_priv.h"
18
19
// Clone and Serialize are allowed to fail if GetRowCount()*GetColCount()
20
// greater than this number
21
#define RAT_MAX_ELEM_FOR_CLONE 1000000
22
23
/************************************************************************/
24
/*                       GDALRasterAttributeTable                       */
25
/************************************************************************/
26
27
//! Raster Attribute Table interface.
28
class GDALDefaultRasterAttributeTable;
29
30
class CPL_DLL GDALRasterAttributeTable
31
{
32
  public:
33
    virtual ~GDALRasterAttributeTable();
34
    /**
35
     * \brief Copy Raster Attribute Table
36
     *
37
     * Creates a new copy of an existing raster attribute table.  The new copy
38
     * becomes the responsibility of the caller to destroy.
39
     * May fail (return nullptr) if the attribute table is too large to clone
40
     * (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
41
     *
42
     * This method is the same as the C function GDALRATClone().
43
     *
44
     * @return new copy of the RAT as an in-memory implementation.
45
     */
46
    virtual GDALRasterAttributeTable *Clone() const = 0;
47
48
    /**
49
     * \brief Fetch table column count.
50
     *
51
     * This method is the same as the C function GDALRATGetColumnCount().
52
     *
53
     * @return the number of columns.
54
     */
55
    virtual int GetColumnCount() const = 0;
56
57
    /**
58
     * \brief Fetch name of indicated column.
59
     *
60
     * This method is the same as the C function GDALRATGetNameOfCol().
61
     *
62
     * @param iCol the column index (zero based).
63
     *
64
     * @return the column name or an empty string for invalid column numbers.
65
     */
66
    virtual const char *GetNameOfCol(int iCol) const = 0;
67
68
    /**
69
     * \brief Fetch column usage value.
70
     *
71
     * This method is the same as the C function GDALRATGetUsageOfCol().
72
     *
73
     * @param iCol the column index (zero based).
74
     *
75
     * @return the column usage, or GFU_Generic for improper column numbers.
76
     */
77
    virtual GDALRATFieldUsage GetUsageOfCol(int iCol) const = 0;
78
79
    /**
80
     * \brief Fetch column type.
81
     *
82
     * This method is the same as the C function GDALRATGetTypeOfCol().
83
     *
84
     * @param iCol the column index (zero based).
85
     *
86
     * @return column type or GFT_Integer if the column index is illegal.
87
     */
88
    virtual GDALRATFieldType GetTypeOfCol(int iCol) const = 0;
89
90
    /**
91
     * \brief Fetch column index for given usage.
92
     *
93
     * Returns the index of the first column of the requested usage type, or -1
94
     * if no match is found.
95
     *
96
     * This method is the same as the C function GDALRATGetUsageOfCol().
97
     *
98
     * @param eUsage usage type to search for.
99
     *
100
     * @return column index, or -1 on failure.
101
     */
102
    virtual int GetColOfUsage(GDALRATFieldUsage eUsage) const = 0;
103
104
    /**
105
     * \brief Fetch row count.
106
     *
107
     * This method is the same as the C function GDALRATGetRowCount().
108
     *
109
     * @return the number of rows.
110
     */
111
    virtual int GetRowCount() const = 0;
112
113
    /**
114
     * \brief Fetch field value as a string.
115
     *
116
     * The value of the requested column in the requested row is returned
117
     * as a string.  If the field is numeric, it is formatted as a string
118
     * using default rules, so some precision may be lost.
119
     *
120
     * The returned string is temporary and cannot be expected to be
121
     * available after the next GDAL call.
122
     *
123
     * This method is the same as the C function GDALRATGetValueAsString().
124
     *
125
     * @param iRow row to fetch (zero based).
126
     * @param iField column to fetch (zero based).
127
     *
128
     * @return field value.
129
     */
130
    virtual const char *GetValueAsString(int iRow, int iField) const = 0;
131
132
    /**
133
     * \brief Fetch field value as a integer.
134
     *
135
     * The value of the requested column in the requested row is returned
136
     * as an integer.  Non-integer fields will be converted to integer with
137
     * the possibility of data loss.
138
     *
139
     * This method is the same as the C function GDALRATGetValueAsInt().
140
     *
141
     * @param iRow row to fetch (zero based).
142
     * @param iField column to fetch (zero based).
143
     *
144
     * @return field value
145
     */
146
    virtual int GetValueAsInt(int iRow, int iField) const = 0;
147
148
    /**
149
     * \brief Fetch field value as a double.
150
     *
151
     * The value of the requested column in the requested row is returned
152
     * as a double.   Non double fields will be converted to double with
153
     * the possibility of data loss.
154
     *
155
     * This method is the same as the C function GDALRATGetValueAsDouble().
156
     *
157
     * @param iRow row to fetch (zero based).
158
     * @param iField column to fetch (zero based).
159
     *
160
     * @return field value
161
     */
162
    virtual double GetValueAsDouble(int iRow, int iField) const = 0;
163
164
    /**
165
     * \brief Set field value from string.
166
     *
167
     * The indicated field (column) on the indicated row is set from the
168
     * passed value.  The value will be automatically converted for other field
169
     * types, with a possible loss of precision.
170
     *
171
     * This method is the same as the C function GDALRATSetValueAsString().
172
     *
173
     * @param iRow row to fetch (zero based).
174
     * @param iField column to fetch (zero based).
175
     * @param pszValue the value to assign.
176
     * @return (since 3.12) CE_None in case of success, error code otherwise
177
     */
178
    virtual CPLErr SetValue(int iRow, int iField, const char *pszValue) = 0;
179
180
    /**
181
     * \brief Set field value from integer.
182
     *
183
     * The indicated field (column) on the indicated row is set from the
184
     * passed value.  The value will be automatically converted for other field
185
     * types, with a possible loss of precision.
186
     *
187
     * This method is the same as the C function GDALRATSetValueAsInteger().
188
     *
189
     * @param iRow row to fetch (zero based).
190
     * @param iField column to fetch (zero based).
191
     * @param nValue the value to assign.
192
     * @return (since 3.12) CE_None in case of success, error code otherwise
193
     */
194
    virtual CPLErr SetValue(int iRow, int iField, int nValue) = 0;
195
196
    /**
197
     * \brief Set field value from double.
198
     *
199
     * The indicated field (column) on the indicated row is set from the
200
     * passed value.  The value will be automatically converted for other field
201
     * types, with a possible loss of precision.
202
     *
203
     * This method is the same as the C function GDALRATSetValueAsDouble().
204
     *
205
     * @param iRow row to fetch (zero based).
206
     * @param iField column to fetch (zero based).
207
     * @param dfValue the value to assign.
208
     * @return (since 3.12) CE_None in case of success, error code otherwise
209
     */
210
    virtual CPLErr SetValue(int iRow, int iField, double dfValue) = 0;
211
212
    /**
213
     * \brief Determine whether changes made to this RAT are reflected directly
214
     * in the dataset
215
     *
216
     * If this returns FALSE then GDALRasterBand.SetDefaultRAT() should be
217
     * called. Otherwise this is unnecessary since changes to this object are
218
     * reflected in the dataset.
219
     *
220
     * This method is the same as the C function
221
     * GDALRATChangesAreWrittenToFile().
222
     *
223
     */
224
    virtual int ChangesAreWrittenToFile() = 0;
225
226
    /**
227
     * \brief Set the RAT table type.
228
     *
229
     * Set whether the RAT is thematic or athematic (continuous).
230
     *
231
     * @since GDAL 2.4
232
     */
233
    virtual CPLErr SetTableType(const GDALRATTableType eInTableType) = 0;
234
235
    /**
236
     * \brief Get the RAT table type.
237
     *
238
     * Indicates whether the RAT is thematic or athematic (continuous).
239
     *
240
     * @since GDAL 2.4
241
     * @return table type
242
     */
243
    virtual GDALRATTableType GetTableType() const = 0;
244
245
    virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
246
                            int iLength, double *pdfData);
247
    virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
248
                            int iLength, int *pnData);
249
    virtual CPLErr ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow,
250
                            int iLength, char **papszStrList);
251
252
    virtual void SetRowCount(int iCount);
253
    virtual int GetRowOfValue(double dfValue) const;
254
    virtual int GetRowOfValue(int nValue) const;
255
256
    virtual CPLErr CreateColumn(const char *pszFieldName,
257
                                GDALRATFieldType eFieldType,
258
                                GDALRATFieldUsage eFieldUsage);
259
    virtual CPLErr SetLinearBinning(double dfRow0Min, double dfBinSize);
260
    virtual int GetLinearBinning(double *pdfRow0Min, double *pdfBinSize) const;
261
262
    /**
263
     * \brief Serialize
264
     *
265
     * May fail (return nullptr) if the attribute table is too large to
266
     * serialize (GetRowCount() * GetColCount() > RAT_MAX_ELEM_FOR_CLONE)
267
     */
268
    virtual CPLXMLNode *Serialize() const;
269
    virtual void *SerializeJSON() const;
270
    virtual CPLErr XMLInit(const CPLXMLNode *, const char *);
271
272
    virtual CPLErr InitializeFromColorTable(const GDALColorTable *);
273
    virtual GDALColorTable *TranslateToColorTable(int nEntryCount = -1);
274
275
    virtual void DumpReadable(FILE * = nullptr);
276
277
    /** Convert a GDALRasterAttributeTable* to a GDALRasterAttributeTableH.
278
     * @since GDAL 2.3
279
     */
280
    static inline GDALRasterAttributeTableH
281
    ToHandle(GDALRasterAttributeTable *poRAT)
282
0
    {
283
0
        return static_cast<GDALRasterAttributeTableH>(poRAT);
284
0
    }
285
286
    /** Convert a GDALRasterAttributeTableH to a GDALRasterAttributeTable*.
287
     * @since GDAL 2.3
288
     */
289
    static inline GDALRasterAttributeTable *
290
    FromHandle(GDALRasterAttributeTableH hRAT)
291
0
    {
292
0
        return static_cast<GDALRasterAttributeTable *>(hRAT);
293
0
    }
294
295
    /**
296
     * \brief Remove statistics from the RAT.
297
     *
298
     * @since GDAL 2.4
299
     */
300
    virtual void RemoveStatistics() = 0;
301
302
  protected:
303
    //! @cond Doxygen_Suppress
304
0
    GDALRasterAttributeTable() = default;
305
0
    GDALRasterAttributeTable(const GDALRasterAttributeTable &) = default;
306
    GDALRasterAttributeTable &
307
    operator=(const GDALRasterAttributeTable &) = default;
308
    GDALRasterAttributeTable(GDALRasterAttributeTable &&) = default;
309
    GDALRasterAttributeTable &operator=(GDALRasterAttributeTable &&) = default;
310
    //! @endcond
311
};
312
313
/************************************************************************/
314
/*                    GDALDefaultRasterAttributeTable                   */
315
/************************************************************************/
316
317
//! Raster Attribute Table container.
318
319
class CPL_DLL GDALDefaultRasterAttributeTable : public GDALRasterAttributeTable
320
{
321
  private:
322
    struct GDALRasterAttributeField
323
    {
324
        CPLString sName{};
325
326
        GDALRATFieldType eType = GFT_Integer;
327
328
        GDALRATFieldUsage eUsage = GFU_Generic;
329
330
        std::vector<GInt32> anValues{};
331
        std::vector<double> adfValues{};
332
        std::vector<CPLString> aosValues{};
333
    };
334
335
    std::vector<GDALRasterAttributeField> aoFields{};
336
337
    int bLinearBinning = false;  // TODO(schwehr): Can this be a bool?
338
    double dfRow0Min = -0.5;
339
    double dfBinSize = 1.0;
340
341
    GDALRATTableType eTableType = GRTT_THEMATIC;
342
343
    void AnalyseColumns();
344
    int bColumnsAnalysed = false;  // TODO(schwehr): Can this be a bool?
345
    int nMinCol = -1;
346
    int nMaxCol = -1;
347
348
    int nRowCount = 0;
349
350
    CPLString osWorkingResult{};
351
352
  public:
353
    GDALDefaultRasterAttributeTable();
354
    ~GDALDefaultRasterAttributeTable() override;
355
356
    //! @cond Doxygen_Suppress
357
    GDALDefaultRasterAttributeTable(const GDALDefaultRasterAttributeTable &) =
358
0
        default;
359
    GDALDefaultRasterAttributeTable &
360
    operator=(const GDALDefaultRasterAttributeTable &) = default;
361
    GDALDefaultRasterAttributeTable(GDALDefaultRasterAttributeTable &&) =
362
        default;
363
    GDALDefaultRasterAttributeTable &
364
    operator=(GDALDefaultRasterAttributeTable &&) = default;
365
    //! @endcond
366
367
    GDALDefaultRasterAttributeTable *Clone() const override;
368
369
    int GetColumnCount() const override;
370
371
    const char *GetNameOfCol(int) const override;
372
    GDALRATFieldUsage GetUsageOfCol(int) const override;
373
    GDALRATFieldType GetTypeOfCol(int) const override;
374
375
    int GetColOfUsage(GDALRATFieldUsage) const override;
376
377
    int GetRowCount() const override;
378
379
    const char *GetValueAsString(int iRow, int iField) const override;
380
    int GetValueAsInt(int iRow, int iField) const override;
381
    double GetValueAsDouble(int iRow, int iField) const override;
382
383
    CPLErr SetValue(int iRow, int iField, const char *pszValue) override;
384
    CPLErr SetValue(int iRow, int iField, double dfValue) override;
385
    CPLErr SetValue(int iRow, int iField, int nValue) override;
386
387
    int ChangesAreWrittenToFile() override;
388
    void SetRowCount(int iCount) override;
389
390
    int GetRowOfValue(double dfValue) const override;
391
    int GetRowOfValue(int nValue) const override;
392
393
    CPLErr CreateColumn(const char *pszFieldName, GDALRATFieldType eFieldType,
394
                        GDALRATFieldUsage eFieldUsage) override;
395
    CPLErr SetLinearBinning(double dfRow0Min, double dfBinSize) override;
396
    int GetLinearBinning(double *pdfRow0Min, double *pdfBinSize) const override;
397
398
    CPLErr SetTableType(const GDALRATTableType eInTableType) override;
399
    GDALRATTableType GetTableType() const override;
400
401
    void RemoveStatistics() override;
402
};
403
404
std::unique_ptr<GDALRasterAttributeTable>
405
    CPL_DLL GDALLoadVATDBF(const char *pszFilename);
406
407
#endif /* ndef GDAL_RAT_H_INCLUDED */