Coverage Report

Created: 2026-06-30 08:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/nitf/offsetpatcher.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  NITF Read/Write Library
4
 * Purpose:  Manages writing offsets to file locations
5
 * Author:   Even Rouault, even dot rouault at spatialys dot com
6
 *
7
 **********************************************************************
8
 * Copyright (c) 2026, T-Kartor
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#ifndef OFFSET_PATCHER_INCLUDED
14
#define OFFSET_PATCHER_INCLUDED
15
16
#include "cpl_vsi_virtual.h"
17
18
#include <cstdint>
19
20
#include <map>
21
#include <memory>
22
#include <string>
23
#include <vector>
24
25
namespace GDALOffsetPatcher
26
{
27
28
class OffsetPatcher;
29
class OffsetPatcherBuffer;
30
31
constexpr vsi_l_offset INVALID_OFFSET = static_cast<vsi_l_offset>(-1);
32
33
/************************************************************************/
34
/*                         OffsetOrSizeLocation                         */
35
/************************************************************************/
36
37
/** Location of an offset or size */
38
struct OffsetOrSizeLocation
39
{
40
    OffsetPatcherBuffer *buffer = nullptr;
41
    size_t offsetInBuffer = 0;
42
};
43
44
/************************************************************************/
45
/*                        OffsetOrSizeReference                         */
46
/************************************************************************/
47
48
/** Reference to an offset or size */
49
struct OffsetOrSizeReference
50
{
51
    OffsetPatcherBuffer *buffer = nullptr;
52
    size_t offsetInBuffer = 0;
53
    int objectSizeBytes = 0;
54
    bool bEndiannessIsLittle = true;
55
};
56
57
/************************************************************************/
58
/*                       OffsetOrSizeDeclaration                        */
59
/************************************************************************/
60
61
/** Declaration of a to-be-resolved offset location or size. */
62
class OffsetOrSizeDeclaration
63
{
64
  public:
65
    explicit OffsetOrSizeDeclaration(const std::string &osName,
66
                                     bool bRelativeToStartOfBuffer = false)
67
0
        : m_osName(osName), m_bRelativeToStartOfBuffer(bRelativeToStartOfBuffer)
68
0
    {
69
0
    }
70
71
    bool HasAlreadyRegisteredLocation() const
72
0
    {
73
0
        return m_location.buffer != nullptr;
74
0
    }
75
76
    const OffsetOrSizeLocation &GetLocation() const
77
0
    {
78
0
        return m_location;
79
0
    }
80
81
    bool SetLocation(OffsetPatcherBuffer *buffer, size_t offsetInBuffer);
82
    void SetReference(OffsetPatcherBuffer *buffer, size_t offsetInBuffer,
83
                      int objectSizeBytes, bool bEndiannessIsLittle);
84
85
  private:
86
    friend class OffsetPatcher;
87
88
    const std::string m_osName;
89
    const bool m_bRelativeToStartOfBuffer;
90
    OffsetOrSizeLocation m_location{};
91
    std::vector<OffsetOrSizeReference> m_references{};
92
};
93
94
/************************************************************************/
95
/*                         OffsetPatcherBuffer                          */
96
/************************************************************************/
97
98
/** Buffer that can contain unresolved references to an offset in another
99
 * buffer or the size of another buffer.
100
 */
101
class OffsetPatcherBuffer
102
{
103
  public:
104
    explicit OffsetPatcherBuffer(const std::string &osName,
105
                                 OffsetPatcher &offsetPatcher,
106
                                 bool bEndiannessIsLittle)
107
0
        : m_osName(osName), m_offsetPatcher(offsetPatcher),
108
0
          m_bEndiannessIsLittle(bEndiannessIsLittle)
109
0
    {
110
0
    }
111
112
    void AppendUInt32RefForOffset(const std::string &osName,
113
                                  bool bRelativeToStartOfBuffer = false);
114
    void AppendUInt16RefForSizeOfBuffer(const std::string &osBufferName);
115
    void AppendUInt32RefForSizeOfBuffer(const std::string &osBufferName);
116
    void AppendByte(uint8_t byVal);
117
    void AppendUInt16(uint16_t nVal);
118
    void AppendUInt32(uint32_t nVal);
119
    void AppendFloat64(double dfVal);
120
    void AppendString(const std::string &s);
121
122
    bool DeclareOffsetAtCurrentPosition(const std::string &osName);
123
124
    void DeclareBufferWrittenAtPosition(vsi_l_offset nFileOffset);
125
126
    const std::vector<uint8_t> &GetBuffer() const
127
0
    {
128
0
        return m_abyBuffer;
129
0
    }
130
131
    vsi_l_offset GetFileLocation() const
132
0
    {
133
0
        return m_nOffset;
134
0
    }
135
136
  private:
137
    friend class OffsetPatcher;
138
139
    const std::string m_osName;
140
    OffsetPatcher &m_offsetPatcher;
141
    const bool m_bEndiannessIsLittle;
142
    std::vector<uint8_t> m_abyBuffer{};
143
    vsi_l_offset m_nOffset = INVALID_OFFSET;
144
145
    bool NeedByteSwap() const
146
0
    {
147
0
#if CPL_IS_LSB
148
0
        return !m_bEndiannessIsLittle;
149
#else
150
        return m_bEndiannessIsLittle;
151
#endif
152
0
    }
153
};
154
155
/************************************************************************/
156
/*                            OffsetPatcher                             */
157
/************************************************************************/
158
159
/** Higher level class managing buffers, offset and sizes declarations */
160
class OffsetPatcher
161
{
162
  public:
163
23
    OffsetPatcher() = default;
164
165
    OffsetPatcherBuffer *CreateBuffer(const std::string &osName,
166
                                      bool bEndiannessIsLittle);
167
168
    OffsetPatcherBuffer *GetBufferFromName(const std::string &osName) const;
169
    OffsetOrSizeDeclaration *
170
    GetOffsetDeclaration(const std::string &osName) const;
171
172
    bool Finalize(VSILFILE *fp);
173
174
  private:
175
    friend class OffsetPatcherBuffer;
176
177
    std::map<std::string, std::unique_ptr<OffsetPatcherBuffer>> m_buffers{};
178
    std::map<std::string, std::unique_ptr<OffsetOrSizeDeclaration>> m_offsets{};
179
    std::map<std::string, std::unique_ptr<OffsetOrSizeDeclaration>> m_sizes{};
180
181
    OffsetPatcher(const OffsetPatcher &) = delete;
182
    OffsetPatcher &operator=(const OffsetPatcher &) = delete;
183
};
184
185
}  // namespace GDALOffsetPatcher
186
187
#endif  // OFFSET_PATCHER_INCLUDED