Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements reading of FileGDB tables
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef FILEGDBTABLE_PRIV_H_INCLUDED
14 : #define FILEGDBTABLE_PRIV_H_INCLUDED
15 :
16 : #include "filegdbtable.h"
17 :
18 : #include "cpl_conv.h"
19 : #include "cpl_error.h"
20 : #include "cpl_time.h"
21 :
22 : #include <algorithm>
23 : #include <cwchar>
24 : #include <vector>
25 : #include <limits>
26 :
27 : #define DIV_ROUND_UP(a, b) (((a) % (b)) == 0 ? ((a) / (b)) : (((a) / (b)) + 1))
28 :
29 : #define TEST_BIT(ar, bit) (ar[(bit) / 8] & (1 << ((bit) % 8)))
30 : #define BIT_ARRAY_SIZE_IN_BYTES(bitsize) (((bitsize) + 7) / 8)
31 :
32 : namespace OpenFileGDB
33 : {
34 :
35 : /************************************************************************/
36 : /* GetInt16() */
37 : /************************************************************************/
38 :
39 7680 : inline GInt16 GetInt16(const GByte *pBaseAddr, int iOffset)
40 : {
41 : GInt16 nVal;
42 7680 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
43 7680 : CPL_LSBPTR16(&nVal);
44 7680 : return nVal;
45 : }
46 :
47 : /************************************************************************/
48 : /* GetUInt16() */
49 : /************************************************************************/
50 :
51 8294 : inline GUInt16 GetUInt16(const GByte *pBaseAddr, int iOffset)
52 : {
53 : GUInt16 nVal;
54 8294 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
55 8294 : CPL_LSBPTR16(&nVal);
56 8294 : return nVal;
57 : }
58 :
59 : /************************************************************************/
60 : /* GetInt32() */
61 : /************************************************************************/
62 :
63 51623 : inline GInt32 GetInt32(const GByte *pBaseAddr, int iOffset)
64 : {
65 : GInt32 nVal;
66 51623 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
67 51623 : CPL_LSBPTR32(&nVal);
68 51623 : return nVal;
69 : }
70 :
71 : /************************************************************************/
72 : /* GetUInt32() */
73 : /************************************************************************/
74 :
75 543651 : inline GUInt32 GetUInt32(const GByte *pBaseAddr, int iOffset)
76 : {
77 : GUInt32 nVal;
78 543651 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
79 543651 : CPL_LSBPTR32(&nVal);
80 543651 : return nVal;
81 : }
82 :
83 : /************************************************************************/
84 : /* GetInt64() */
85 : /************************************************************************/
86 :
87 83111 : inline int64_t GetInt64(const GByte *pBaseAddr, int iOffset)
88 : {
89 : int64_t nVal;
90 83111 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
91 83111 : CPL_LSBPTR64(&nVal);
92 83111 : return nVal;
93 : }
94 :
95 : /************************************************************************/
96 : /* GetUInt64() */
97 : /************************************************************************/
98 :
99 4763 : inline uint64_t GetUInt64(const GByte *pBaseAddr, int iOffset)
100 : {
101 : uint64_t nVal;
102 4763 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
103 4763 : CPL_LSBPTR64(&nVal);
104 4763 : return nVal;
105 : }
106 :
107 : /************************************************************************/
108 : /* GetFloat32() */
109 : /************************************************************************/
110 :
111 7696 : inline float GetFloat32(const GByte *pBaseAddr, int iOffset)
112 : {
113 : float fVal;
114 7696 : memcpy(&fVal, pBaseAddr + sizeof(fVal) * iOffset, sizeof(fVal));
115 7696 : CPL_LSBPTR32(&fVal);
116 7696 : return fVal;
117 : }
118 :
119 : /************************************************************************/
120 : /* GetFloat64() */
121 : /************************************************************************/
122 :
123 75566 : inline double GetFloat64(const GByte *pBaseAddr, int iOffset)
124 : {
125 : double dfVal;
126 75566 : memcpy(&dfVal, pBaseAddr + sizeof(dfVal) * iOffset, sizeof(dfVal));
127 75566 : CPL_LSBPTR64(&dfVal);
128 75566 : return dfVal;
129 : }
130 :
131 : /************************************************************************/
132 : /* ReadUInt32() */
133 : /************************************************************************/
134 :
135 7999 : inline bool ReadUInt32(VSILFILE *fp, uint32_t &nVal)
136 : {
137 7999 : const bool bRet = VSIFReadL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
138 7999 : CPL_LSBPTR32(&nVal);
139 7999 : return bRet;
140 : }
141 :
142 : /************************************************************************/
143 : /* WriteUInt32() */
144 : /************************************************************************/
145 :
146 77762 : inline bool WriteUInt32(VSILFILE *fp, uint32_t nVal)
147 : {
148 77762 : CPL_LSBPTR32(&nVal);
149 77762 : return VSIFWriteL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
150 : }
151 :
152 : /************************************************************************/
153 : /* WriteUInt64() */
154 : /************************************************************************/
155 :
156 10714 : inline bool WriteUInt64(VSILFILE *fp, uint64_t nVal)
157 : {
158 10714 : CPL_LSBPTR64(&nVal);
159 10714 : return VSIFWriteL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
160 : }
161 :
162 : /************************************************************************/
163 : /* WriteFloat64() */
164 : /************************************************************************/
165 :
166 650 : inline bool WriteFloat64(VSILFILE *fp, double dfVal)
167 : {
168 650 : CPL_LSBPTR64(&dfVal);
169 650 : return VSIFWriteL(&dfVal, 1, sizeof(dfVal), fp) == sizeof(dfVal);
170 : }
171 :
172 : /************************************************************************/
173 : /* WriteUInt32() */
174 : /************************************************************************/
175 :
176 21914 : inline void WriteUInt32(std::vector<GByte> &abyBuffer, uint32_t nVal)
177 : {
178 21914 : CPL_LSBPTR32(&nVal);
179 21914 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
180 21914 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
181 21914 : }
182 :
183 : /************************************************************************/
184 : /* WriteUInt32() */
185 : /************************************************************************/
186 :
187 10210 : inline void WriteUInt32(std::vector<GByte> &abyBuffer, uint32_t nVal,
188 : size_t nPos)
189 : {
190 10210 : CPL_LSBPTR32(&nVal);
191 10210 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
192 10210 : memcpy(&abyBuffer[nPos], pabyInput, sizeof(nVal));
193 10210 : }
194 :
195 : /************************************************************************/
196 : /* WriteFloat32() */
197 : /************************************************************************/
198 :
199 54 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
200 : {
201 54 : CPL_LSBPTR32(&fVal);
202 54 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
203 54 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
204 54 : }
205 :
206 : /************************************************************************/
207 : /* WriteFloat64() */
208 : /************************************************************************/
209 :
210 13063 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
211 : {
212 13063 : CPL_LSBPTR64(&dfVal);
213 13063 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
214 13063 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
215 13063 : }
216 :
217 : /************************************************************************/
218 : /* WriteInt32() */
219 : /************************************************************************/
220 :
221 3952 : inline void WriteInt32(std::vector<GByte> &abyBuffer, int32_t nVal)
222 : {
223 3952 : CPL_LSBPTR32(&nVal);
224 3952 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
225 3952 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
226 3952 : }
227 :
228 : /************************************************************************/
229 : /* WriteInt64() */
230 : /************************************************************************/
231 :
232 3 : inline void WriteInt64(std::vector<GByte> &abyBuffer, int64_t nVal)
233 : {
234 3 : CPL_LSBPTR64(&nVal);
235 3 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
236 3 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
237 3 : }
238 :
239 : /************************************************************************/
240 : /* WriteUInt16() */
241 : /************************************************************************/
242 :
243 4571 : inline void WriteUInt16(std::vector<GByte> &abyBuffer, uint16_t nVal)
244 : {
245 4571 : CPL_LSBPTR16(&nVal);
246 4571 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
247 4571 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
248 4571 : }
249 :
250 : /************************************************************************/
251 : /* WriteInt16() */
252 : /************************************************************************/
253 :
254 3756 : inline void WriteInt16(std::vector<GByte> &abyBuffer, int16_t nVal)
255 : {
256 3756 : CPL_LSBPTR16(&nVal);
257 3756 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
258 3756 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
259 3756 : }
260 :
261 : /************************************************************************/
262 : /* WriteUInt8() */
263 : /************************************************************************/
264 :
265 203754 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
266 : {
267 203754 : abyBuffer.push_back(nVal);
268 203754 : }
269 :
270 : /************************************************************************/
271 : /* WriteUInt64() */
272 : /************************************************************************/
273 :
274 4061 : inline void WriteUInt64(std::vector<GByte> &abyBuffer, uint64_t nVal)
275 : {
276 4061 : CPL_LSBPTR64(&nVal);
277 4061 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
278 4061 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
279 4061 : }
280 :
281 : /************************************************************************/
282 : /* WriteVarUInt() */
283 : /************************************************************************/
284 :
285 121848 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
286 : {
287 : while (true)
288 : {
289 121848 : if (nVal >= 0x80)
290 : {
291 54261 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
292 54261 : nVal >>= 7;
293 : }
294 : else
295 : {
296 67587 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
297 67587 : break;
298 : }
299 : }
300 67587 : }
301 :
302 : /************************************************************************/
303 : /* WriteVarInt() */
304 : /************************************************************************/
305 :
306 3389 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
307 : {
308 : uint64_t nUVal;
309 3389 : if (nVal < 0)
310 : {
311 427 : if (nVal == std::numeric_limits<int64_t>::min())
312 0 : nUVal = static_cast<uint64_t>(1) << 63;
313 : else
314 427 : nUVal = -nVal;
315 427 : if (nUVal >= 0x40)
316 : {
317 427 : WriteUInt8(abyBuffer,
318 427 : static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
319 427 : nUVal >>= 6;
320 : }
321 : else
322 : {
323 0 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x40 | (nUVal & 0x3F)));
324 0 : return;
325 : }
326 : }
327 : else
328 : {
329 2962 : nUVal = nVal;
330 2962 : if (nUVal >= 0x40)
331 : {
332 705 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
333 705 : nUVal >>= 6;
334 : }
335 : else
336 : {
337 2257 : WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
338 2257 : return;
339 : }
340 : }
341 :
342 1132 : WriteVarUInt(abyBuffer, nUVal);
343 : }
344 :
345 : /************************************************************************/
346 : /* ReadUTF16String() */
347 : /************************************************************************/
348 :
349 100103 : inline std::string ReadUTF16String(const GByte *pabyIter, int nCarCount)
350 : {
351 200206 : std::wstring osWideStr;
352 795020 : for (int j = 0; j < nCarCount; j++)
353 694917 : osWideStr += pabyIter[2 * j] | (pabyIter[2 * j + 1] << 8);
354 : char *pszStr =
355 100103 : CPLRecodeFromWChar(osWideStr.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8);
356 100103 : std::string osRet(pszStr);
357 100103 : CPLFree(pszStr);
358 200206 : return osRet;
359 : }
360 :
361 : /************************************************************************/
362 : /* WriteUTF16String() */
363 : /************************************************************************/
364 :
365 : enum UTF16StringFormat
366 : {
367 : NUMBER_OF_BYTES_ON_UINT16,
368 : NUMBER_OF_BYTES_ON_VARUINT,
369 : NUMBER_OF_CHARS_ON_UINT8,
370 : NUMBER_OF_CHARS_ON_UINT32,
371 : };
372 :
373 29282 : inline void WriteUTF16String(std::vector<GByte> &abyBuffer, const char *pszStr,
374 : UTF16StringFormat eFormat)
375 : {
376 29282 : wchar_t *pszWStr = CPLRecodeToWChar(pszStr, CPL_ENC_UTF8, CPL_ENC_UCS2);
377 29282 : size_t nWLen = wcslen(pszWStr);
378 29282 : switch (eFormat)
379 : {
380 546 : case NUMBER_OF_BYTES_ON_UINT16:
381 : {
382 : // Write length as bytes
383 : const auto nLenToWrite =
384 546 : std::min(static_cast<size_t>(65534), sizeof(uint16_t) * nWLen);
385 546 : if (nLenToWrite < sizeof(uint16_t) * nWLen)
386 : {
387 0 : CPLError(CE_Warning, CPLE_AppDefined,
388 : "String %s truncated to %u bytes", pszStr,
389 : static_cast<uint32_t>(nLenToWrite));
390 0 : nWLen = nLenToWrite / sizeof(uint16_t);
391 : }
392 546 : WriteUInt16(abyBuffer, static_cast<uint16_t>(nLenToWrite));
393 546 : break;
394 : }
395 :
396 2 : case NUMBER_OF_BYTES_ON_VARUINT:
397 : {
398 : // Write length as bytes
399 2 : WriteVarUInt(abyBuffer, sizeof(uint16_t) * nWLen);
400 2 : break;
401 : }
402 :
403 27722 : case NUMBER_OF_CHARS_ON_UINT8:
404 : {
405 : // Write length as number of UTF16 characters
406 27722 : const auto nLenToWrite = std::min(static_cast<size_t>(255), nWLen);
407 27722 : if (nLenToWrite < nWLen)
408 : {
409 0 : CPLError(CE_Warning, CPLE_AppDefined,
410 : "String %s truncated to %u UTF16 characters", pszStr,
411 : static_cast<uint32_t>(nLenToWrite));
412 0 : nWLen = nLenToWrite;
413 : }
414 27722 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nLenToWrite));
415 27722 : break;
416 : }
417 :
418 1012 : case NUMBER_OF_CHARS_ON_UINT32:
419 : {
420 : // Write length as number of UTF16 characters
421 1012 : WriteUInt32(abyBuffer, static_cast<uint32_t>(nWLen));
422 1012 : break;
423 : }
424 : }
425 :
426 29282 : if (nWLen)
427 : {
428 15425 : std::vector<uint16_t> anChars(nWLen);
429 182272 : for (size_t i = 0; i < nWLen; ++i)
430 : {
431 166847 : anChars[i] = static_cast<uint16_t>(pszWStr[i]);
432 166847 : CPL_LSBPTR16(&anChars[i]);
433 : }
434 : const GByte *pabyInput =
435 15425 : reinterpret_cast<const GByte *>(anChars.data());
436 0 : abyBuffer.insert(abyBuffer.end(), pabyInput,
437 15425 : pabyInput + nWLen * sizeof(uint16_t));
438 : }
439 29282 : CPLFree(pszWStr);
440 29282 : }
441 :
442 : /************************************************************************/
443 : /* FileGDBOGRDateToDoubleDate() */
444 : /************************************************************************/
445 :
446 134 : inline double FileGDBOGRDateToDoubleDate(const OGRField *psField,
447 : bool bConvertToGMT,
448 : bool bHighPrecision)
449 : {
450 : struct tm brokendowntime;
451 134 : brokendowntime.tm_year = psField->Date.Year - 1900;
452 134 : brokendowntime.tm_mon = psField->Date.Month - 1;
453 134 : brokendowntime.tm_mday = psField->Date.Day;
454 134 : brokendowntime.tm_hour = psField->Date.Hour;
455 134 : brokendowntime.tm_min = psField->Date.Minute;
456 134 : brokendowntime.tm_sec = bHighPrecision
457 134 : ? static_cast<int>(psField->Date.Second)
458 118 : : static_cast<int>(psField->Date.Second + 0.5);
459 134 : GIntBig nUnixTime = CPLYMDHMSToUnixTime(&brokendowntime);
460 134 : if (bConvertToGMT && psField->Date.TZFlag > 1 &&
461 39 : psField->Date.TZFlag != 100)
462 : {
463 : // Convert to GMT
464 38 : const int TZOffset = std::abs(psField->Date.TZFlag - 100) * 15;
465 38 : const int TZHour = TZOffset / 60;
466 38 : const int TZMinute = TZOffset - TZHour * 60;
467 38 : const int nOffset = TZHour * 3600 + TZMinute * 60;
468 38 : if (psField->Date.TZFlag >= 100)
469 38 : nUnixTime -= nOffset;
470 : else
471 0 : nUnixTime += nOffset;
472 : }
473 : // 25569: Number of days between 1899/12/30 00:00:00 and 1970/01/01 00:00:00
474 : return static_cast<double>(
475 268 : nUnixTime +
476 : (bHighPrecision
477 134 : ? fmod(static_cast<double>(psField->Date.Second), 1.0)
478 134 : : 0)) /
479 134 : 3600.0 / 24.0 +
480 134 : 25569.0;
481 : }
482 :
483 : /************************************************************************/
484 : /* FileGDBOGRTimeToDoubleTime() */
485 : /************************************************************************/
486 :
487 12 : inline double FileGDBOGRTimeToDoubleTime(const OGRField *psField)
488 : {
489 12 : return static_cast<double>(psField->Date.Hour * 3600 +
490 12 : psField->Date.Minute * 60 +
491 12 : psField->Date.Second) /
492 12 : 3600.0 / 24.0;
493 : }
494 :
495 : void FileGDBTablePrintError(const char *pszFile, int nLineNumber);
496 :
497 : #define PrintError() FileGDBTablePrintError(__FILE__, __LINE__)
498 :
499 : /************************************************************************/
500 : /* returnError() */
501 : /************************************************************************/
502 :
503 : #define returnError() \
504 : do \
505 : { \
506 : PrintError(); \
507 : return (errorRetValue); \
508 : } while (0)
509 :
510 : /************************************************************************/
511 : /* returnErrorIf() */
512 : /************************************************************************/
513 :
514 : #define returnErrorIf(expr) \
515 : do \
516 : { \
517 : if ((expr)) \
518 : returnError(); \
519 : } while (0)
520 :
521 : /************************************************************************/
522 : /* returnErrorAndCleanupIf() */
523 : /************************************************************************/
524 :
525 : #define returnErrorAndCleanupIf(expr, cleanup) \
526 : do \
527 : { \
528 : if ((expr)) \
529 : { \
530 : cleanup; \
531 : returnError(); \
532 : } \
533 : } while (0)
534 :
535 : } /* namespace OpenFileGDB */
536 :
537 : #endif /* FILEGDBTABLE_PRIV_H_INCLUDED */
|