/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 |