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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #ifndef FILEGDBTABLE_PRIV_H_INCLUDED
31 : #define FILEGDBTABLE_PRIV_H_INCLUDED
32 :
33 : #include "filegdbtable.h"
34 :
35 : #include "cpl_conv.h"
36 : #include "cpl_error.h"
37 : #include "cpl_time.h"
38 :
39 : #include <algorithm>
40 : #include <cwchar>
41 : #include <vector>
42 : #include <limits>
43 :
44 : #define DIV_ROUND_UP(a, b) (((a) % (b)) == 0 ? ((a) / (b)) : (((a) / (b)) + 1))
45 :
46 : #define TEST_BIT(ar, bit) (ar[(bit) / 8] & (1 << ((bit) % 8)))
47 : #define BIT_ARRAY_SIZE_IN_BYTES(bitsize) (((bitsize) + 7) / 8)
48 :
49 : namespace OpenFileGDB
50 : {
51 :
52 : /************************************************************************/
53 : /* GetInt16() */
54 : /************************************************************************/
55 :
56 7681 : inline GInt16 GetInt16(const GByte *pBaseAddr, int iOffset)
57 : {
58 : GInt16 nVal;
59 7681 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
60 7681 : CPL_LSBPTR16(&nVal);
61 7681 : return nVal;
62 : }
63 :
64 : /************************************************************************/
65 : /* GetUInt16() */
66 : /************************************************************************/
67 :
68 7064 : inline GUInt16 GetUInt16(const GByte *pBaseAddr, int iOffset)
69 : {
70 : GUInt16 nVal;
71 7064 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
72 7064 : CPL_LSBPTR16(&nVal);
73 7064 : return nVal;
74 : }
75 :
76 : /************************************************************************/
77 : /* GetInt32() */
78 : /************************************************************************/
79 :
80 44825 : inline GInt32 GetInt32(const GByte *pBaseAddr, int iOffset)
81 : {
82 : GInt32 nVal;
83 44825 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
84 44825 : CPL_LSBPTR32(&nVal);
85 44825 : return nVal;
86 : }
87 :
88 : /************************************************************************/
89 : /* GetUInt32() */
90 : /************************************************************************/
91 :
92 532901 : inline GUInt32 GetUInt32(const GByte *pBaseAddr, int iOffset)
93 : {
94 : GUInt32 nVal;
95 532901 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
96 532901 : CPL_LSBPTR32(&nVal);
97 532901 : return nVal;
98 : }
99 :
100 : /************************************************************************/
101 : /* GetInt64() */
102 : /************************************************************************/
103 :
104 83016 : inline int64_t GetInt64(const GByte *pBaseAddr, int iOffset)
105 : {
106 : int64_t nVal;
107 83016 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
108 83016 : CPL_LSBPTR64(&nVal);
109 83016 : return nVal;
110 : }
111 :
112 : /************************************************************************/
113 : /* GetUInt64() */
114 : /************************************************************************/
115 :
116 4360 : inline uint64_t GetUInt64(const GByte *pBaseAddr, int iOffset)
117 : {
118 : uint64_t nVal;
119 4360 : memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
120 4360 : CPL_LSBPTR64(&nVal);
121 4360 : return nVal;
122 : }
123 :
124 : /************************************************************************/
125 : /* GetFloat32() */
126 : /************************************************************************/
127 :
128 7697 : inline float GetFloat32(const GByte *pBaseAddr, int iOffset)
129 : {
130 : float fVal;
131 7697 : memcpy(&fVal, pBaseAddr + sizeof(fVal) * iOffset, sizeof(fVal));
132 7697 : CPL_LSBPTR32(&fVal);
133 7697 : return fVal;
134 : }
135 :
136 : /************************************************************************/
137 : /* GetFloat64() */
138 : /************************************************************************/
139 :
140 72227 : inline double GetFloat64(const GByte *pBaseAddr, int iOffset)
141 : {
142 : double dfVal;
143 72227 : memcpy(&dfVal, pBaseAddr + sizeof(dfVal) * iOffset, sizeof(dfVal));
144 72227 : CPL_LSBPTR64(&dfVal);
145 72227 : return dfVal;
146 : }
147 :
148 : /************************************************************************/
149 : /* ReadUInt32() */
150 : /************************************************************************/
151 :
152 7999 : inline bool ReadUInt32(VSILFILE *fp, uint32_t &nVal)
153 : {
154 7999 : const bool bRet = VSIFReadL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
155 7999 : CPL_LSBPTR32(&nVal);
156 7999 : return bRet;
157 : }
158 :
159 : /************************************************************************/
160 : /* WriteUInt32() */
161 : /************************************************************************/
162 :
163 76074 : inline bool WriteUInt32(VSILFILE *fp, uint32_t nVal)
164 : {
165 76074 : CPL_LSBPTR32(&nVal);
166 76074 : return VSIFWriteL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
167 : }
168 :
169 : /************************************************************************/
170 : /* WriteUInt64() */
171 : /************************************************************************/
172 :
173 10336 : inline bool WriteUInt64(VSILFILE *fp, uint64_t nVal)
174 : {
175 10336 : CPL_LSBPTR64(&nVal);
176 10336 : return VSIFWriteL(&nVal, 1, sizeof(nVal), fp) == sizeof(nVal);
177 : }
178 :
179 : /************************************************************************/
180 : /* WriteFloat64() */
181 : /************************************************************************/
182 :
183 641 : inline bool WriteFloat64(VSILFILE *fp, double dfVal)
184 : {
185 641 : CPL_LSBPTR64(&dfVal);
186 641 : return VSIFWriteL(&dfVal, 1, sizeof(dfVal), fp) == sizeof(dfVal);
187 : }
188 :
189 : /************************************************************************/
190 : /* WriteUInt32() */
191 : /************************************************************************/
192 :
193 21596 : inline void WriteUInt32(std::vector<GByte> &abyBuffer, uint32_t nVal)
194 : {
195 21596 : CPL_LSBPTR32(&nVal);
196 21596 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
197 21596 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
198 21596 : }
199 :
200 : /************************************************************************/
201 : /* WriteUInt32() */
202 : /************************************************************************/
203 :
204 10166 : inline void WriteUInt32(std::vector<GByte> &abyBuffer, uint32_t nVal,
205 : size_t nPos)
206 : {
207 10166 : CPL_LSBPTR32(&nVal);
208 10166 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
209 10166 : memcpy(&abyBuffer[nPos], pabyInput, sizeof(nVal));
210 10166 : }
211 :
212 : /************************************************************************/
213 : /* WriteFloat32() */
214 : /************************************************************************/
215 :
216 54 : inline void WriteFloat32(std::vector<GByte> &abyBuffer, float fVal)
217 : {
218 54 : CPL_LSBPTR32(&fVal);
219 54 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&fVal);
220 54 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(fVal));
221 54 : }
222 :
223 : /************************************************************************/
224 : /* WriteFloat64() */
225 : /************************************************************************/
226 :
227 12878 : inline void WriteFloat64(std::vector<GByte> &abyBuffer, double dfVal)
228 : {
229 12878 : CPL_LSBPTR64(&dfVal);
230 12878 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&dfVal);
231 12878 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(dfVal));
232 12878 : }
233 :
234 : /************************************************************************/
235 : /* WriteInt32() */
236 : /************************************************************************/
237 :
238 3797 : inline void WriteInt32(std::vector<GByte> &abyBuffer, int32_t nVal)
239 : {
240 3797 : CPL_LSBPTR32(&nVal);
241 3797 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
242 3797 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
243 3797 : }
244 :
245 : /************************************************************************/
246 : /* WriteInt64() */
247 : /************************************************************************/
248 :
249 3 : inline void WriteInt64(std::vector<GByte> &abyBuffer, int64_t nVal)
250 : {
251 3 : CPL_LSBPTR64(&nVal);
252 3 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
253 3 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
254 3 : }
255 :
256 : /************************************************************************/
257 : /* WriteUInt16() */
258 : /************************************************************************/
259 :
260 4460 : inline void WriteUInt16(std::vector<GByte> &abyBuffer, uint16_t nVal)
261 : {
262 4460 : CPL_LSBPTR16(&nVal);
263 4460 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
264 4460 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
265 4460 : }
266 :
267 : /************************************************************************/
268 : /* WriteInt16() */
269 : /************************************************************************/
270 :
271 3692 : inline void WriteInt16(std::vector<GByte> &abyBuffer, int16_t nVal)
272 : {
273 3692 : CPL_LSBPTR16(&nVal);
274 3692 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
275 3692 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
276 3692 : }
277 :
278 : /************************************************************************/
279 : /* WriteUInt8() */
280 : /************************************************************************/
281 :
282 201186 : inline void WriteUInt8(std::vector<GByte> &abyBuffer, uint8_t nVal)
283 : {
284 201186 : abyBuffer.push_back(nVal);
285 201186 : }
286 :
287 : /************************************************************************/
288 : /* WriteUInt64() */
289 : /************************************************************************/
290 :
291 4058 : inline void WriteUInt64(std::vector<GByte> &abyBuffer, uint64_t nVal)
292 : {
293 4058 : CPL_LSBPTR64(&nVal);
294 4058 : const GByte *pabyInput = reinterpret_cast<const GByte *>(&nVal);
295 4058 : abyBuffer.insert(abyBuffer.end(), pabyInput, pabyInput + sizeof(nVal));
296 4058 : }
297 :
298 : /************************************************************************/
299 : /* WriteVarUInt() */
300 : /************************************************************************/
301 :
302 120728 : inline void WriteVarUInt(std::vector<GByte> &abyBuffer, uint64_t nVal)
303 : {
304 : while (true)
305 : {
306 120728 : if (nVal >= 0x80)
307 : {
308 54148 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nVal & 0x7F)));
309 54148 : nVal >>= 7;
310 : }
311 : else
312 : {
313 66580 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nVal));
314 66580 : break;
315 : }
316 : }
317 66580 : }
318 :
319 : /************************************************************************/
320 : /* WriteVarInt() */
321 : /************************************************************************/
322 :
323 3359 : inline void WriteVarInt(std::vector<GByte> &abyBuffer, int64_t nVal)
324 : {
325 : uint64_t nUVal;
326 3359 : if (nVal < 0)
327 : {
328 425 : if (nVal == std::numeric_limits<int64_t>::min())
329 0 : nUVal = static_cast<uint64_t>(1) << 63;
330 : else
331 425 : nUVal = -nVal;
332 425 : if (nUVal >= 0x40)
333 : {
334 425 : WriteUInt8(abyBuffer,
335 425 : static_cast<uint8_t>(0x80 | 0x40 | (nUVal & 0x3F)));
336 425 : nUVal >>= 6;
337 : }
338 : else
339 : {
340 0 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x40 | (nUVal & 0x3F)));
341 0 : return;
342 : }
343 : }
344 : else
345 : {
346 2934 : nUVal = nVal;
347 2934 : if (nUVal >= 0x40)
348 : {
349 699 : WriteUInt8(abyBuffer, static_cast<uint8_t>(0x80 | (nUVal & 0x3F)));
350 699 : nUVal >>= 6;
351 : }
352 : else
353 : {
354 2235 : WriteUInt8(abyBuffer, static_cast<uint8_t>((nUVal & 0x3F)));
355 2235 : return;
356 : }
357 : }
358 :
359 1124 : WriteVarUInt(abyBuffer, nUVal);
360 : }
361 :
362 : /************************************************************************/
363 : /* ReadUTF16String() */
364 : /************************************************************************/
365 :
366 92931 : inline std::string ReadUTF16String(const GByte *pabyIter, int nCarCount)
367 : {
368 185862 : std::wstring osWideStr;
369 732277 : for (int j = 0; j < nCarCount; j++)
370 639346 : osWideStr += pabyIter[2 * j] | (pabyIter[2 * j + 1] << 8);
371 : char *pszStr =
372 92931 : CPLRecodeFromWChar(osWideStr.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8);
373 92931 : std::string osRet(pszStr);
374 92931 : CPLFree(pszStr);
375 185862 : return osRet;
376 : }
377 :
378 : /************************************************************************/
379 : /* WriteUTF16String() */
380 : /************************************************************************/
381 :
382 : enum UTF16StringFormat
383 : {
384 : NUMBER_OF_BYTES_ON_UINT16,
385 : NUMBER_OF_BYTES_ON_VARUINT,
386 : NUMBER_OF_CHARS_ON_UINT8,
387 : NUMBER_OF_CHARS_ON_UINT32,
388 : };
389 :
390 28707 : inline void WriteUTF16String(std::vector<GByte> &abyBuffer, const char *pszStr,
391 : UTF16StringFormat eFormat)
392 : {
393 28707 : wchar_t *pszWStr = CPLRecodeToWChar(pszStr, CPL_ENC_UTF8, CPL_ENC_UCS2);
394 28707 : size_t nWLen = wcslen(pszWStr);
395 28707 : switch (eFormat)
396 : {
397 539 : case NUMBER_OF_BYTES_ON_UINT16:
398 : {
399 : // Write length as bytes
400 : const auto nLenToWrite =
401 539 : std::min(static_cast<size_t>(65534), sizeof(uint16_t) * nWLen);
402 539 : if (nLenToWrite < sizeof(uint16_t) * nWLen)
403 : {
404 0 : CPLError(CE_Warning, CPLE_AppDefined,
405 : "String %s truncated to %u bytes", pszStr,
406 : static_cast<uint32_t>(nLenToWrite));
407 0 : nWLen = nLenToWrite / sizeof(uint16_t);
408 : }
409 539 : WriteUInt16(abyBuffer, static_cast<uint16_t>(nLenToWrite));
410 539 : break;
411 : }
412 :
413 2 : case NUMBER_OF_BYTES_ON_VARUINT:
414 : {
415 : // Write length as bytes
416 2 : WriteVarUInt(abyBuffer, sizeof(uint16_t) * nWLen);
417 2 : break;
418 : }
419 :
420 27194 : case NUMBER_OF_CHARS_ON_UINT8:
421 : {
422 : // Write length as number of UTF16 characters
423 27194 : const auto nLenToWrite = std::min(static_cast<size_t>(255), nWLen);
424 27194 : if (nLenToWrite < nWLen)
425 : {
426 0 : CPLError(CE_Warning, CPLE_AppDefined,
427 : "String %s truncated to %u UTF16 characters", pszStr,
428 : static_cast<uint32_t>(nLenToWrite));
429 0 : nWLen = nLenToWrite;
430 : }
431 27194 : WriteUInt8(abyBuffer, static_cast<uint8_t>(nLenToWrite));
432 27194 : break;
433 : }
434 :
435 972 : case NUMBER_OF_CHARS_ON_UINT32:
436 : {
437 : // Write length as number of UTF16 characters
438 972 : WriteUInt32(abyBuffer, static_cast<uint32_t>(nWLen));
439 972 : break;
440 : }
441 : }
442 :
443 28707 : if (nWLen)
444 : {
445 15114 : std::vector<uint16_t> anChars(nWLen);
446 178188 : for (size_t i = 0; i < nWLen; ++i)
447 : {
448 163074 : anChars[i] = static_cast<uint16_t>(pszWStr[i]);
449 163074 : CPL_LSBPTR16(&anChars[i]);
450 : }
451 : const GByte *pabyInput =
452 15114 : reinterpret_cast<const GByte *>(anChars.data());
453 0 : abyBuffer.insert(abyBuffer.end(), pabyInput,
454 15114 : pabyInput + nWLen * sizeof(uint16_t));
455 : }
456 28707 : CPLFree(pszWStr);
457 28707 : }
458 :
459 : /************************************************************************/
460 : /* FileGDBOGRDateToDoubleDate() */
461 : /************************************************************************/
462 :
463 134 : inline double FileGDBOGRDateToDoubleDate(const OGRField *psField,
464 : bool bConvertToGMT,
465 : bool bHighPrecision)
466 : {
467 : struct tm brokendowntime;
468 134 : brokendowntime.tm_year = psField->Date.Year - 1900;
469 134 : brokendowntime.tm_mon = psField->Date.Month - 1;
470 134 : brokendowntime.tm_mday = psField->Date.Day;
471 134 : brokendowntime.tm_hour = psField->Date.Hour;
472 134 : brokendowntime.tm_min = psField->Date.Minute;
473 134 : brokendowntime.tm_sec = bHighPrecision
474 134 : ? static_cast<int>(psField->Date.Second)
475 118 : : static_cast<int>(psField->Date.Second + 0.5);
476 134 : GIntBig nUnixTime = CPLYMDHMSToUnixTime(&brokendowntime);
477 134 : if (bConvertToGMT && psField->Date.TZFlag > 1 &&
478 39 : psField->Date.TZFlag != 100)
479 : {
480 : // Convert to GMT
481 38 : const int TZOffset = std::abs(psField->Date.TZFlag - 100) * 15;
482 38 : const int TZHour = TZOffset / 60;
483 38 : const int TZMinute = TZOffset - TZHour * 60;
484 38 : const int nOffset = TZHour * 3600 + TZMinute * 60;
485 38 : if (psField->Date.TZFlag >= 100)
486 38 : nUnixTime -= nOffset;
487 : else
488 0 : nUnixTime += nOffset;
489 : }
490 : // 25569: Number of days between 1899/12/30 00:00:00 and 1970/01/01 00:00:00
491 : return static_cast<double>(
492 268 : nUnixTime +
493 : (bHighPrecision
494 134 : ? fmod(static_cast<double>(psField->Date.Second), 1.0)
495 134 : : 0)) /
496 134 : 3600.0 / 24.0 +
497 134 : 25569.0;
498 : }
499 :
500 : /************************************************************************/
501 : /* FileGDBOGRTimeToDoubleTime() */
502 : /************************************************************************/
503 :
504 12 : inline double FileGDBOGRTimeToDoubleTime(const OGRField *psField)
505 : {
506 12 : return static_cast<double>(psField->Date.Hour * 3600 +
507 12 : psField->Date.Minute * 60 +
508 12 : psField->Date.Second) /
509 12 : 3600.0 / 24.0;
510 : }
511 :
512 : void FileGDBTablePrintError(const char *pszFile, int nLineNumber);
513 :
514 : #define PrintError() FileGDBTablePrintError(__FILE__, __LINE__)
515 :
516 : /************************************************************************/
517 : /* returnError() */
518 : /************************************************************************/
519 :
520 : #define returnError() \
521 : do \
522 : { \
523 : PrintError(); \
524 : return (errorRetValue); \
525 : } while (0)
526 :
527 : /************************************************************************/
528 : /* returnErrorIf() */
529 : /************************************************************************/
530 :
531 : #define returnErrorIf(expr) \
532 : do \
533 : { \
534 : if ((expr)) \
535 : returnError(); \
536 : } while (0)
537 :
538 : /************************************************************************/
539 : /* returnErrorAndCleanupIf() */
540 : /************************************************************************/
541 :
542 : #define returnErrorAndCleanupIf(expr, cleanup) \
543 : do \
544 : { \
545 : if ((expr)) \
546 : { \
547 : cleanup; \
548 : returnError(); \
549 : } \
550 : } while (0)
551 :
552 : } /* namespace OpenFileGDB */
553 :
554 : #endif /* FILEGDBTABLE_PRIV_H_INCLUDED */
|