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