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 9309 : inline GUInt16 GetUInt16(const GByte *pBaseAddr, int iOffset)
52 : {
53 : GUInt16 nVal;
54 9309 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
55 9309 : CPL_LSBPTR16(&nVal);
56 9309 : return nVal;
57 : }
58 :
59 : /************************************************************************/
60 : /* GetInt32() */
61 : /************************************************************************/
62 :
63 56584 : inline GInt32 GetInt32(const GByte *pBaseAddr, int iOffset)
64 : {
65 : GInt32 nVal;
66 56584 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
67 56584 : CPL_LSBPTR32(&nVal);
68 56584 : return nVal;
69 : }
70 :
71 : /************************************************************************/
72 : /* GetUInt32() */
73 : /************************************************************************/
74 :
75 548445 : inline GUInt32 GetUInt32(const GByte *pBaseAddr, int iOffset)
76 : {
77 : GUInt32 nVal;
78 548445 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
79 548445 : CPL_LSBPTR32(&nVal);
80 548445 : return nVal;
81 : }
82 :
83 : /************************************************************************/
84 : /* GetInt64() */
85 : /************************************************************************/
86 :
87 83218 : inline int64_t GetInt64(const GByte *pBaseAddr, int iOffset)
88 : {
89 : int64_t nVal;
90 83218 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
91 83218 : CPL_LSBPTR64(&nVal);
92 83218 : return nVal;
93 : }
94 :
95 : /************************************************************************/
96 : /* GetUInt64() */
97 : /************************************************************************/
98 :
99 5322 : inline uint64_t GetUInt64(const GByte *pBaseAddr, int iOffset)
100 : {
101 : uint64_t nVal;
102 5322 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
103 5322 : CPL_LSBPTR64(&nVal);
104 5322 : 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 84192 : inline double GetFloat64(const GByte *pBaseAddr, int iOffset)
124 : {
125 : double dfVal;
126 84192 : memcpy(&dfVal, pBaseAddr + sizeof(dfVal) * iOffset, sizeof(dfVal));
127 84192 : CPL_LSBPTR64(&dfVal);
128 84192 : return dfVal;
129 : }
130 :
131 : /************************************************************************/
132 : /* ReadUInt32() */
133 : /************************************************************************/
134 :
135 8007 : inline bool ReadUInt32(VSILFILE *fp, uint32_t &nVal)
136 : {
137 8007 : const bool bRet = VSIFReadL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
138 8007 : CPL_LSBPTR32(&nVal);
139 8007 : return bRet;
140 : }
141 :
142 : /************************************************************************/
143 : /* WriteUInt32() */
144 : /************************************************************************/
145 :
146 81579 : inline bool WriteUInt32(VSILFILE *fp, uint32_t nVal)
147 : {
148 81579 : CPL_LSBPTR32(&nVal);
149 81579 : return VSIFWriteL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
150 : }
151 :
152 : /************************************************************************/
153 : /* WriteUInt64() */
154 : /************************************************************************/
155 :
156 11424 : inline bool WriteUInt64(VSILFILE *fp, uint64_t nVal)
157 : {
158 11424 : CPL_LSBPTR64(&nVal);
159 11424 : return VSIFWriteL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
160 : }
161 :
162 : /************************************************************************/
163 : /* WriteFloat64() */
164 : /************************************************************************/
165 :
166 860 : inline bool WriteFloat64(VSILFILE *fp, double dfVal)
167 : {
168 860 : CPL_LSBPTR64(&dfVal);
169 860 : return VSIFWriteL(&dfVal, 1, sizeof(dfVal), fp) == sizeof(dfVal);
170 : }
171 :
172 : /************************************************************************/
173 : /* WriteUInt32() */
174 : /************************************************************************/
175 :
176 23514 : inline void WriteUInt32(std::vector<GByte> &abyBuffer, uint32_t nVal)
177 : {
178 23514 : CPL_LSBPTR32(&nVal);
179 23514 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
180 23514 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
181 23514 : }
182 :
183 : /************************************************************************/
184 : /* WriteUInt32() */
185 : /************************************************************************/
186 :
187 10334 : inline void WriteUInt32(std::vector<GByte> &abyBuffer, uint32_t nVal,
188 : size_t nPos)
189 : {
190 10334 : CPL_LSBPTR32(&nVal);
191 10334 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
192 10334 : memcpy(&abyBuffer[nPos], pabyInput, sizeof(nVal));
193 10334 : }
194 :
195 : /************************************************************************/
196 : /* WriteFloat32() */
197 : /************************************************************************/
198 :
199 394 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
200 : {
201 394 : CPL_LSBPTR32(&fVal);
202 394 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
203 394 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
204 394 : }
205 :
206 : /************************************************************************/
207 : /* WriteFloat64() */
208 : /************************************************************************/
209 :
210 14471 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
211 : {
212 14471 : CPL_LSBPTR64(&dfVal);
213 14471 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
214 14471 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
215 14471 : }
216 :
217 : /************************************************************************/
218 : /* WriteInt32() */
219 : /************************************************************************/
220 :
221 4590 : inline void WriteInt32(std::vector<GByte> &abyBuffer, int32_t nVal)
222 : {
223 4590 : CPL_LSBPTR32(&nVal);
224 4590 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
225 4590 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
226 4590 : }
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 4971 : inline void WriteUInt16(std::vector<GByte> &abyBuffer, uint16_t nVal)
244 : {
245 4971 : CPL_LSBPTR16(&nVal);
246 4971 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
247 4971 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
248 4971 : }
249 :
250 : /************************************************************************/
251 : /* WriteInt16() */
252 : /************************************************************************/
253 :
254 4240 : inline void WriteInt16(std::vector<GByte> &abyBuffer, int16_t nVal)
255 : {
256 4240 : CPL_LSBPTR16(&nVal);
257 4240 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
258 4240 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
259 4240 : }
260 :
261 : /************************************************************************/
262 : /* WriteUInt8() */
263 : /************************************************************************/
264 :
265 231257 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
266 : {
267 231257 : abyBuffer.push_back(nVal);
268 231257 : }
269 :
270 : /************************************************************************/
271 : /* WriteUInt64() */
272 : /************************************************************************/
273 :
274 4434 : inline void WriteUInt64(std::vector<GByte> &abyBuffer, uint64_t nVal)
275 : {
276 4434 : CPL_LSBPTR64(&nVal);
277 4434 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
278 4434 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
279 4434 : }
280 :
281 : /************************************************************************/
282 : /* WriteVarUInt() */
283 : /************************************************************************/
284 :
285 139419 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
286 : {
287 : while (true)
288 : {
289 139419 : if (nVal >= 0x80)
290 : {
291 64297 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
292 64297 : nVal >>= 7;
293 : }
294 : else
295 : {
296 75122 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
297 75122 : break;
298 : }
299 : }
300 75122 : }
301 :
302 : /************************************************************************/
303 : /* WriteVarInt() */
304 : /************************************************************************/
305 :
306 7385 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
307 : {
308 : uint64_t nUVal;
309 7385 : if (nVal < 0)
310 : {
311 1784 : if (nVal == std::numeric_limits<int64_t>::min())
312 0 : nUVal = static_cast<uint64_t>(1) << 63;
313 : else
314 1784 : nUVal = -nVal;
315 1784 : if (nUVal >= 0x40)
316 : {
317 1784 : WriteUInt8(abyBuffer,
318 1784 : static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
319 1784 : 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 5601 : nUVal = nVal;
330 5601 : if (nUVal >= 0x40)
331 : {
332 2628 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
333 2628 : nUVal >>= 6;
334 : }
335 : else
336 : {
337 2973 : WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
338 2973 : return;
339 : }
340 : }
341 :
342 4412 : WriteVarUInt(abyBuffer, nUVal);
343 : }
344 :
345 : /************************************************************************/
346 : /* ReadUTF16String() */
347 : /************************************************************************/
348 :
349 118535 : inline std::string ReadUTF16String(const GByte *pabyIter, int nCarCount)
350 : {
351 237070 : std::wstring osWideStr;
352 956153 : for (int j = 0; j < nCarCount; j++)
353 837618 : osWideStr += pabyIter[2 * j] | (pabyIter[2 * j + 1] << 8);
354 : char *pszStr =
355 118535 : CPLRecodeFromWChar(osWideStr.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8);
356 118535 : std::string osRet(pszStr);
357 118535 : CPLFree(pszStr);
358 237070 : 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 31559 : inline void WriteUTF16String(std::vector<GByte> &abyBuffer, const char *pszStr,
374 : UTF16StringFormat eFormat)
375 : {
376 31559 : wchar_t *pszWStr = CPLRecodeToWChar(pszStr, CPL_ENC_UTF8, CPL_ENC_UCS2);
377 31559 : size_t nWLen = wcslen(pszWStr);
378 31559 : switch (eFormat)
379 : {
380 595 : case NUMBER_OF_BYTES_ON_UINT16:
381 : {
382 : // Write length as bytes
383 : const auto nLenToWrite =
384 595 : std::min(static_cast<size_t>(65534), sizeof(uint16_t) * nWLen);
385 595 : 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 595 : WriteUInt16(abyBuffer, static_cast<uint16_t>(nLenToWrite));
393 595 : 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 29786 : case NUMBER_OF_CHARS_ON_UINT8:
404 : {
405 : // Write length as number of UTF16 characters
406 29786 : const auto nLenToWrite = std::min(static_cast<size_t>(255), nWLen);
407 29786 : 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 29786 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nLenToWrite));
415 29786 : break;
416 : }
417 :
418 1176 : case NUMBER_OF_CHARS_ON_UINT32:
419 : {
420 : // Write length as number of UTF16 characters
421 1176 : WriteUInt32(abyBuffer, static_cast<uint32_t>(nWLen));
422 1176 : break;
423 : }
424 : }
425 :
426 31559 : if (nWLen)
427 : {
428 16670 : std::vector<uint16_t> anChars(nWLen);
429 198716 : for (size_t i = 0; i < nWLen; ++i)
430 : {
431 182046 : anChars[i] = static_cast<uint16_t>(pszWStr[i]);
432 182046 : CPL_LSBPTR16(&anChars[i]);
433 : }
434 : const GByte *pabyInput =
435 16670 : reinterpret_cast<const GByte *>(anChars.data());
436 0 : abyBuffer.insert(abyBuffer.end(), pabyInput,
437 16670 : pabyInput + nWLen * sizeof(uint16_t));
438 : }
439 31559 : CPLFree(pszWStr);
440 31559 : }
441 :
442 : /************************************************************************/
443 : /* FileGDBOGRDateToDoubleDate() */
444 : /************************************************************************/
445 :
446 304 : inline double FileGDBOGRDateToDoubleDate(const OGRField *psField,
447 : bool bConvertToGMT,
448 : bool bHighPrecision)
449 : {
450 : struct tm brokendowntime;
451 304 : brokendowntime.tm_year = psField->Date.Year - 1900;
452 304 : brokendowntime.tm_mon = psField->Date.Month - 1;
453 304 : brokendowntime.tm_mday = psField->Date.Day;
454 304 : brokendowntime.tm_hour = psField->Date.Hour;
455 304 : brokendowntime.tm_min = psField->Date.Minute;
456 304 : brokendowntime.tm_sec = bHighPrecision
457 304 : ? static_cast<int>(psField->Date.Second)
458 288 : : static_cast<int>(psField->Date.Second + 0.5);
459 304 : GIntBig nUnixTime = CPLYMDHMSToUnixTime(&brokendowntime);
460 304 : 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 608 : nUnixTime +
476 : (bHighPrecision
477 304 : ? fmod(static_cast<double>(psField->Date.Second), 1.0)
478 304 : : 0)) /
479 304 : 3600.0 / 24.0 +
480 304 : 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 */
|