Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PDS Translator
4 : * Purpose: Implements OGRPDSLayer class.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "ogr_pds.h"
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "ogr_p.h"
17 : #include "cpl_safemaths.hpp"
18 :
19 : #include <algorithm>
20 :
21 : namespace OGRPDS
22 : {
23 :
24 : /************************************************************************/
25 : /* OGRPDSLayer() */
26 : /************************************************************************/
27 :
28 2 : OGRPDSLayer::OGRPDSLayer(const std::string &osTableIDIn,
29 : const char *pszLayerName, VSILFILE *fp,
30 : const std::string &osLabelFilename,
31 : const std::string &osStructureFilename, int nRecordsIn,
32 : int nStartBytesIn, int nRecordSizeIn,
33 2 : GByte *pabyRecordIn, bool bIsASCII)
34 2 : : poFeatureDefn(new OGRFeatureDefn(pszLayerName)), osTableID(osTableIDIn),
35 : fpPDS(fp), nRecords(nRecordsIn), nStartBytes(nStartBytesIn),
36 : nRecordSize(nRecordSizeIn), pabyRecord(pabyRecordIn), nNextFID(0),
37 4 : nLongitudeIndex(-1), nLatitudeIndex(-1), pasFieldDesc(nullptr)
38 : {
39 2 : SetDescription(poFeatureDefn->GetName());
40 2 : poFeatureDefn->Reference();
41 2 : poFeatureDefn->SetGeomType(wkbNone);
42 :
43 2 : if (!osStructureFilename.empty())
44 : {
45 2 : ReadStructure(osStructureFilename);
46 : }
47 : else
48 : {
49 0 : ReadStructure(osLabelFilename);
50 : }
51 :
52 2 : if (bIsASCII && poFeatureDefn->GetFieldCount() == 0)
53 : {
54 0 : VSIFSeekL(fpPDS, nStartBytes, SEEK_SET);
55 0 : VSIFReadL(pabyRecord, nRecordSize, 1, fpPDS);
56 :
57 0 : char **papszTokens = CSLTokenizeString2((const char *)pabyRecord, " ",
58 : CSLT_HONOURSTRINGS);
59 0 : const int nTokens = CSLCount(papszTokens);
60 0 : for (int i = 0; i < nTokens; i++)
61 : {
62 0 : const char *pszStr = papszTokens[i];
63 0 : char ch = '\0';
64 0 : OGRFieldType eFieldType = OFTInteger;
65 0 : while ((ch = *pszStr) != 0)
66 : {
67 0 : if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-')
68 : {
69 : }
70 0 : else if (ch == '.')
71 : {
72 0 : eFieldType = OFTReal;
73 : }
74 : else
75 : {
76 0 : eFieldType = OFTString;
77 0 : break;
78 : }
79 0 : pszStr++;
80 : }
81 : char szFieldName[32];
82 0 : snprintf(szFieldName, sizeof(szFieldName), "field_%d",
83 0 : poFeatureDefn->GetFieldCount() + 1);
84 0 : OGRFieldDefn oFieldDefn(szFieldName, eFieldType);
85 0 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
86 : }
87 0 : CSLDestroy(papszTokens);
88 : }
89 :
90 2 : if (nLongitudeIndex >= 0 && nLatitudeIndex >= 0)
91 : {
92 1 : poFeatureDefn->SetGeomType(wkbPoint);
93 : }
94 :
95 2 : OGRPDSLayer::ResetReading();
96 2 : }
97 :
98 : /************************************************************************/
99 : /* ~OGRPDSLayer() */
100 : /************************************************************************/
101 :
102 4 : OGRPDSLayer::~OGRPDSLayer()
103 :
104 : {
105 2 : CPLFree(pasFieldDesc);
106 2 : poFeatureDefn->Release();
107 2 : VSIFree(pabyRecord);
108 :
109 2 : VSIFCloseL(fpPDS);
110 4 : }
111 :
112 : /************************************************************************/
113 : /* ReadStructure() */
114 : /************************************************************************/
115 :
116 2 : void OGRPDSLayer::ReadStructure(const std::string &osStructureFilename)
117 :
118 : {
119 2 : VSILFILE *fpStructure = VSIFOpenL(osStructureFilename.c_str(), "rb");
120 2 : if (fpStructure == nullptr)
121 0 : return;
122 :
123 2 : int nFields = 0;
124 2 : bool bInObjectColumn = false;
125 2 : int nExpectedColumnNumber = 0;
126 4 : CPLString osColumnName;
127 4 : CPLString osColumnDataType;
128 4 : CPLString osColumnStartByte;
129 4 : CPLString osColumnBytes;
130 4 : CPLString osColumnFormat;
131 4 : CPLString osColumnUnit;
132 4 : CPLString osColumnItems;
133 4 : CPLString osColumnItemBytes;
134 2 : int nRowBytes = nRecordSize;
135 : while (true)
136 : {
137 871 : CPLPushErrorHandler(CPLQuietErrorHandler);
138 871 : const char *pszLine = CPLReadLine2L(fpStructure, 256, nullptr);
139 871 : CPLPopErrorHandler();
140 871 : CPLErrorReset();
141 871 : if (pszLine == nullptr)
142 2 : break;
143 :
144 : char **papszTokens =
145 869 : CSLTokenizeString2(pszLine, " =", CSLT_HONOURSTRINGS);
146 869 : const int nTokens = CSLCount(papszTokens);
147 :
148 869 : if (bInObjectColumn && nTokens >= 1 &&
149 723 : EQUAL(papszTokens[0], "END_OBJECT"))
150 : {
151 116 : if (!osColumnName.empty() && !osColumnDataType.empty() &&
152 116 : !osColumnStartByte.empty() && !osColumnBytes.empty())
153 : {
154 116 : pasFieldDesc = static_cast<FieldDesc *>(CPLRealloc(
155 58 : pasFieldDesc, (nFields + 1) * sizeof(FieldDesc)));
156 58 : pasFieldDesc[nFields].nStartByte = atoi(osColumnStartByte) - 1;
157 58 : pasFieldDesc[nFields].nByteCount = atoi(osColumnBytes);
158 58 : if (pasFieldDesc[nFields].nStartByte >= 0 &&
159 58 : pasFieldDesc[nFields].nByteCount > 0 &&
160 58 : pasFieldDesc[nFields].nStartByte <
161 58 : INT_MAX - pasFieldDesc[nFields].nByteCount &&
162 58 : pasFieldDesc[nFields].nStartByte +
163 58 : pasFieldDesc[nFields].nByteCount <=
164 58 : nRecordSize)
165 : {
166 58 : OGRFieldType eFieldType = OFTString;
167 58 : OGRFieldSubType eSubType = OFSTNone;
168 58 : pasFieldDesc[nFields].eFormat = CHARACTER;
169 58 : pasFieldDesc[nFields].nItemBytes = atoi(osColumnItemBytes);
170 58 : pasFieldDesc[nFields].nItems = atoi(osColumnItems);
171 58 : if (pasFieldDesc[nFields].nItems == 0)
172 51 : pasFieldDesc[nFields].nItems = 1;
173 58 : if (pasFieldDesc[nFields].nItemBytes == 0 &&
174 51 : pasFieldDesc[nFields].nItems == 1)
175 51 : pasFieldDesc[nFields].nItemBytes =
176 51 : pasFieldDesc[nFields].nByteCount;
177 :
178 58 : if (osColumnDataType.compare("ASCII_REAL") == 0)
179 : {
180 14 : eFieldType = OFTReal;
181 14 : pasFieldDesc[nFields].eFormat = ASCII_REAL;
182 : }
183 44 : else if (osColumnDataType.compare("ASCII_INTEGER") == 0)
184 : {
185 11 : eFieldType = OFTInteger;
186 11 : pasFieldDesc[nFields].eFormat = ASCII_INTEGER;
187 : }
188 33 : else if (osColumnDataType.compare("MSB_UNSIGNED_INTEGER") ==
189 : 0)
190 : {
191 11 : if (pasFieldDesc[nFields].nItemBytes == 1 ||
192 11 : pasFieldDesc[nFields].nItemBytes == 2)
193 : {
194 9 : if (pasFieldDesc[nFields].nItems > 1)
195 0 : eFieldType = OFTIntegerList;
196 : else
197 9 : eFieldType = OFTInteger;
198 : }
199 : else
200 : {
201 2 : pasFieldDesc[nFields].nItemBytes = 4;
202 2 : if (pasFieldDesc[nFields].nItems > 1)
203 0 : eFieldType = OFTRealList;
204 : else
205 2 : eFieldType = OFTReal;
206 : }
207 11 : pasFieldDesc[nFields].eFormat = MSB_UNSIGNED_INTEGER;
208 : }
209 22 : else if (osColumnDataType.compare("MSB_INTEGER") == 0)
210 : {
211 4 : if (pasFieldDesc[nFields].nItemBytes != 1 &&
212 4 : pasFieldDesc[nFields].nItemBytes != 2)
213 4 : pasFieldDesc[nFields].nItemBytes = 4;
214 4 : if (pasFieldDesc[nFields].nItems > 1)
215 0 : eFieldType = OFTIntegerList;
216 : else
217 4 : eFieldType = OFTInteger;
218 4 : pasFieldDesc[nFields].eFormat = MSB_INTEGER;
219 : }
220 18 : else if (osColumnDataType.compare("IEEE_REAL") == 0)
221 : {
222 16 : if (pasFieldDesc[nFields].nItemBytes == 4)
223 : {
224 8 : eSubType = OFSTFloat32;
225 : }
226 8 : else if (pasFieldDesc[nFields].nItemBytes != 8)
227 : {
228 : // Not sure if this is correct, but default to
229 : // Float32
230 0 : pasFieldDesc[nFields].nItemBytes = 4;
231 : }
232 16 : if (pasFieldDesc[nFields].nItems > 1)
233 7 : eFieldType = OFTRealList;
234 : else
235 9 : eFieldType = OFTReal;
236 16 : pasFieldDesc[nFields].eFormat = IEEE_REAL;
237 : }
238 :
239 58 : OGRFieldDefn oFieldDefn(osColumnName, eFieldType);
240 130 : if ((pasFieldDesc[nFields].eFormat == ASCII_REAL &&
241 102 : !osColumnFormat.empty() && osColumnFormat[0] == 'F') ||
242 44 : (pasFieldDesc[nFields].eFormat == ASCII_INTEGER &&
243 11 : !osColumnFormat.empty() && osColumnFormat[0] == 'I'))
244 : {
245 25 : const char *pszFormat = osColumnFormat.c_str();
246 25 : int nWidth = atoi(pszFormat + 1);
247 25 : oFieldDefn.SetWidth(nWidth);
248 25 : const char *pszPoint = strchr(pszFormat, '.');
249 25 : if (pszPoint)
250 : {
251 14 : int nPrecision = atoi(pszPoint + 1);
252 14 : oFieldDefn.SetPrecision(nPrecision);
253 : }
254 : }
255 33 : else if (oFieldDefn.GetType() == OFTString &&
256 33 : !osColumnFormat.empty() &&
257 0 : osColumnFormat[0] == 'A')
258 : {
259 0 : const char *pszFormat = osColumnFormat.c_str();
260 0 : int nWidth = atoi(pszFormat + 1);
261 0 : oFieldDefn.SetWidth(nWidth);
262 : }
263 58 : oFieldDefn.SetSubType(eSubType);
264 58 : poFeatureDefn->AddFieldDefn(&oFieldDefn);
265 :
266 83 : if (oFieldDefn.GetType() == OFTReal &&
267 25 : osColumnUnit.compare("DEGREE") == 0)
268 : {
269 7 : if (osColumnName.compare("LONGITUDE") == 0)
270 1 : nLongitudeIndex = nFields;
271 6 : else if (osColumnName.compare("LATITUDE") == 0)
272 1 : nLatitudeIndex = nFields;
273 : }
274 :
275 58 : nFields++;
276 : }
277 : else
278 : {
279 0 : CPLError(CE_Failure, CPLE_AppDefined,
280 : "Field %d out of record extents", nFields);
281 0 : CSLDestroy(papszTokens);
282 0 : if (nFields == 0)
283 : {
284 0 : CPLFree(pasFieldDesc);
285 0 : pasFieldDesc = nullptr;
286 : }
287 0 : break;
288 : }
289 : }
290 : else
291 : {
292 0 : CPLError(CE_Failure, CPLE_AppDefined,
293 : "Did not get expected records for field %d", nFields);
294 0 : CSLDestroy(papszTokens);
295 0 : break;
296 : }
297 58 : bInObjectColumn = false;
298 : }
299 811 : else if (nTokens == 2)
300 : {
301 490 : if (EQUAL(papszTokens[0], "PDS_VERSION_ID"))
302 : {
303 0 : CSLDestroy(papszTokens);
304 0 : papszTokens = nullptr;
305 : while (true)
306 : {
307 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
308 0 : pszLine = CPLReadLine2L(fpStructure, 256, nullptr);
309 0 : CPLPopErrorHandler();
310 0 : CPLErrorReset();
311 0 : if (pszLine == nullptr)
312 0 : break;
313 : papszTokens =
314 0 : CSLTokenizeString2(pszLine, " =", CSLT_HONOURSTRINGS);
315 0 : int nTokens2 = CSLCount(papszTokens);
316 0 : if (nTokens2 == 2 && EQUAL(papszTokens[0], "OBJECT") &&
317 0 : EQUAL(papszTokens[1], osTableID.c_str()))
318 : {
319 0 : break;
320 : }
321 0 : CSLDestroy(papszTokens);
322 0 : papszTokens = nullptr;
323 0 : }
324 0 : CSLDestroy(papszTokens);
325 0 : papszTokens = nullptr;
326 0 : if (pszLine == nullptr)
327 0 : break;
328 : }
329 490 : else if (EQUAL(papszTokens[0], "ROW_BYTES"))
330 : {
331 1 : nRowBytes = atoi(papszTokens[1]);
332 1 : if (nRowBytes < 0 || nRowBytes > 10 * 1024 * 1024)
333 : {
334 0 : CPLError(CE_Failure, CPLE_NotSupported,
335 : "Invalid value of ROW_BYTES");
336 0 : CSLDestroy(papszTokens);
337 0 : break;
338 : }
339 : }
340 489 : else if (EQUAL(papszTokens[0], "ROW_SUFFIX_BYTES"))
341 : {
342 : try
343 : {
344 : nRowBytes =
345 0 : (CPLSM(nRowBytes) + CPLSM(atoi(papszTokens[1]))).v();
346 : }
347 0 : catch (const CPLSafeIntOverflow &)
348 : {
349 0 : CPLError(CE_Failure, CPLE_NotSupported,
350 : "Invalid value of ROW_SUFFIX_BYTES");
351 0 : CSLDestroy(papszTokens);
352 0 : break;
353 : }
354 0 : if (nRowBytes < 0 || nRowBytes > 10 * 1024 * 1024)
355 : {
356 0 : CPLError(CE_Failure, CPLE_NotSupported,
357 : "Invalid value of ROW_SUFFIX_BYTES");
358 0 : CSLDestroy(papszTokens);
359 0 : break;
360 : }
361 : }
362 489 : else if (EQUAL(papszTokens[0], "OBJECT") &&
363 58 : EQUAL(papszTokens[1], "COLUMN"))
364 : {
365 58 : if (nRowBytes > nRecordSize)
366 : {
367 0 : nRecordSize = nRowBytes;
368 0 : VSIFree(pabyRecord);
369 0 : pabyRecord = (GByte *)CPLMalloc(nRecordSize + 1);
370 0 : pabyRecord[nRecordSize] = 0;
371 : }
372 : else
373 58 : nRecordSize = nRowBytes;
374 :
375 58 : nExpectedColumnNumber++;
376 58 : bInObjectColumn = true;
377 58 : osColumnName = "";
378 58 : osColumnDataType = "";
379 58 : osColumnStartByte = "";
380 58 : osColumnBytes = "";
381 58 : osColumnItems = "";
382 58 : osColumnItemBytes = "";
383 58 : osColumnFormat = "";
384 58 : osColumnUnit = "";
385 : }
386 431 : else if (bInObjectColumn && EQUAL(papszTokens[0], "COLUMN_NUMBER"))
387 : {
388 58 : int nColumnNumber = atoi(papszTokens[1]);
389 58 : if (nColumnNumber != nExpectedColumnNumber)
390 : {
391 0 : CPLError(CE_Failure, CPLE_AppDefined,
392 : "Did not get expected column number");
393 0 : CSLDestroy(papszTokens);
394 0 : break;
395 58 : }
396 : }
397 373 : else if (bInObjectColumn && EQUAL(papszTokens[0], "NAME"))
398 : {
399 58 : osColumnName = "\"";
400 58 : osColumnName += papszTokens[1];
401 58 : osColumnName += "\"";
402 58 : OGRPDSDataSource::CleanString(osColumnName);
403 : }
404 315 : else if (bInObjectColumn && EQUAL(papszTokens[0], "DATA_TYPE"))
405 : {
406 58 : osColumnDataType = papszTokens[1];
407 58 : OGRPDSDataSource::CleanString(osColumnDataType);
408 : }
409 257 : else if (bInObjectColumn && EQUAL(papszTokens[0], "START_BYTE"))
410 : {
411 58 : osColumnStartByte = papszTokens[1];
412 : }
413 199 : else if (bInObjectColumn && EQUAL(papszTokens[0], "BYTES"))
414 : {
415 58 : osColumnBytes = papszTokens[1];
416 : }
417 141 : else if (bInObjectColumn && EQUAL(papszTokens[0], "ITEMS"))
418 : {
419 7 : osColumnItems = papszTokens[1];
420 : }
421 134 : else if (bInObjectColumn && EQUAL(papszTokens[0], "ITEM_BYTES"))
422 : {
423 7 : osColumnItemBytes = papszTokens[1];
424 : }
425 127 : else if (bInObjectColumn && EQUAL(papszTokens[0], "FORMAT"))
426 : {
427 25 : osColumnFormat = papszTokens[1];
428 : }
429 102 : else if (bInObjectColumn && EQUAL(papszTokens[0], "UNIT"))
430 : {
431 11 : osColumnUnit = papszTokens[1];
432 : }
433 : }
434 869 : CSLDestroy(papszTokens);
435 869 : }
436 2 : VSIFCloseL(fpStructure);
437 : }
438 :
439 : /************************************************************************/
440 : /* ResetReading() */
441 : /************************************************************************/
442 :
443 2 : void OGRPDSLayer::ResetReading()
444 :
445 : {
446 2 : nNextFID = 0;
447 2 : VSIFSeekL(fpPDS, nStartBytes, SEEK_SET);
448 2 : }
449 :
450 : /************************************************************************/
451 : /* GetNextRawFeature() */
452 : /************************************************************************/
453 :
454 3 : OGRFeature *OGRPDSLayer::GetNextRawFeature()
455 : {
456 3 : if (nNextFID == nRecords)
457 0 : return nullptr;
458 3 : int nRead = (int)VSIFReadL(pabyRecord, 1, nRecordSize, fpPDS);
459 3 : if (nRead != nRecordSize)
460 0 : return nullptr;
461 :
462 3 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
463 3 : int nFieldCount = poFeatureDefn->GetFieldCount();
464 3 : if (pasFieldDesc != nullptr)
465 : {
466 86 : for (int i = 0; i < nFieldCount; i++)
467 : {
468 83 : if (pasFieldDesc[i].eFormat == ASCII_REAL ||
469 55 : pasFieldDesc[i].eFormat == ASCII_INTEGER ||
470 33 : pasFieldDesc[i].eFormat == CHARACTER)
471 : {
472 52 : char *pchEnd = reinterpret_cast<char *>(
473 52 : &pabyRecord[pasFieldDesc[i].nStartByte +
474 52 : pasFieldDesc[i].nByteCount]);
475 52 : char chSaved = *pchEnd;
476 52 : *pchEnd = 0;
477 52 : const char *pszValue =
478 52 : (const char *)(pabyRecord + pasFieldDesc[i].nStartByte);
479 52 : if (pasFieldDesc[i].eFormat == CHARACTER)
480 : {
481 2 : poFeature->SetField(i, pszValue);
482 : }
483 : else
484 : {
485 50 : poFeature->SetField(i, CPLString(pszValue).Trim().c_str());
486 : }
487 52 : *pchEnd = chSaved;
488 : }
489 31 : else if (pasFieldDesc[i].eFormat == MSB_UNSIGNED_INTEGER &&
490 11 : pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
491 11 : pasFieldDesc[i].nItems <=
492 11 : nRecordSize)
493 : {
494 11 : if (pasFieldDesc[i].nItemBytes == 1)
495 : {
496 0 : if (pasFieldDesc[i].nItems > 1)
497 : {
498 : int *panValues = static_cast<int *>(
499 0 : CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems));
500 0 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
501 : {
502 0 : panValues[j] =
503 0 : pabyRecord[pasFieldDesc[i].nStartByte + j];
504 : }
505 0 : poFeature->SetField(i, pasFieldDesc[i].nItems,
506 : panValues);
507 0 : CPLFree(panValues);
508 : }
509 : else
510 : {
511 0 : poFeature->SetField(
512 0 : i, pabyRecord[pasFieldDesc[i].nStartByte]);
513 : }
514 : }
515 11 : else if (pasFieldDesc[i].nItemBytes == 2)
516 : {
517 9 : if (pasFieldDesc[i].nItems > 1)
518 : {
519 0 : int *panValues = (int *)CPLMalloc(
520 0 : sizeof(int) * pasFieldDesc[i].nItems);
521 0 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
522 : {
523 0 : unsigned short sVal = 0;
524 0 : memcpy(&sVal,
525 0 : pabyRecord + pasFieldDesc[i].nStartByte +
526 0 : 2 * j,
527 : 2);
528 0 : CPL_MSBPTR16(&sVal);
529 0 : panValues[j] = sVal;
530 : }
531 0 : poFeature->SetField(i, pasFieldDesc[i].nItems,
532 : panValues);
533 0 : CPLFree(panValues);
534 : }
535 : else
536 : {
537 9 : unsigned short sVal = 0;
538 9 : memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte,
539 : 2);
540 9 : CPL_MSBPTR16(&sVal);
541 9 : poFeature->SetField(i, (int)sVal);
542 : }
543 : }
544 2 : else if (pasFieldDesc[i].nItemBytes == 4)
545 : {
546 2 : if (pasFieldDesc[i].nItems > 1)
547 : {
548 0 : double *padfValues = (double *)CPLMalloc(
549 0 : sizeof(double) * pasFieldDesc[i].nItems);
550 0 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
551 : {
552 0 : unsigned int nVal = 0;
553 0 : memcpy(&nVal,
554 0 : pabyRecord + pasFieldDesc[i].nStartByte +
555 0 : 4 * j,
556 : 4);
557 0 : CPL_MSBPTR32(&nVal);
558 0 : padfValues[j] = (double)nVal;
559 : }
560 0 : poFeature->SetField(i, pasFieldDesc[i].nItems,
561 : padfValues);
562 0 : CPLFree(padfValues);
563 : }
564 : else
565 : {
566 2 : unsigned int nVal = 0;
567 2 : memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte,
568 : 4);
569 2 : CPL_MSBPTR32(&nVal);
570 2 : poFeature->SetField(i, (double)nVal);
571 : }
572 11 : }
573 : }
574 20 : else if (pasFieldDesc[i].eFormat == MSB_INTEGER &&
575 4 : pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
576 4 : pasFieldDesc[i].nItems <=
577 4 : nRecordSize)
578 : {
579 4 : if (pasFieldDesc[i].nItemBytes == 1)
580 : {
581 0 : if (pasFieldDesc[i].nItems > 1)
582 : {
583 0 : int *panValues = (int *)CPLMalloc(
584 0 : sizeof(int) * pasFieldDesc[i].nItems);
585 0 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
586 : {
587 0 : panValues[j] = ((
588 0 : char *)pabyRecord)[pasFieldDesc[i].nStartByte +
589 0 : j];
590 : }
591 0 : poFeature->SetField(i, pasFieldDesc[i].nItems,
592 : panValues);
593 0 : CPLFree(panValues);
594 : }
595 : else
596 : {
597 0 : poFeature->SetField(
598 : i,
599 0 : ((char *)pabyRecord)[pasFieldDesc[i].nStartByte]);
600 : }
601 : }
602 4 : else if (pasFieldDesc[i].nItemBytes == 2)
603 : {
604 0 : if (pasFieldDesc[i].nItems > 1)
605 : {
606 0 : int *panValues = (int *)CPLMalloc(
607 0 : sizeof(int) * pasFieldDesc[i].nItems);
608 0 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
609 : {
610 0 : short sVal = 0;
611 0 : memcpy(&sVal,
612 0 : pabyRecord + pasFieldDesc[i].nStartByte +
613 0 : 2 * j,
614 : 2);
615 0 : CPL_MSBPTR16(&sVal);
616 0 : panValues[j] = sVal;
617 : }
618 0 : poFeature->SetField(i, pasFieldDesc[i].nItems,
619 : panValues);
620 0 : CPLFree(panValues);
621 : }
622 : else
623 : {
624 0 : short sVal = 0;
625 0 : memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte,
626 : 2);
627 0 : CPL_MSBPTR16(&sVal);
628 0 : poFeature->SetField(i, (int)sVal);
629 : }
630 : }
631 4 : else if (pasFieldDesc[i].nItemBytes == 4)
632 : {
633 4 : if (pasFieldDesc[i].nItems > 1)
634 : {
635 0 : int *panValues = (int *)CPLMalloc(
636 0 : sizeof(int) * pasFieldDesc[i].nItems);
637 0 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
638 : {
639 0 : int nVal = 0;
640 0 : memcpy(&nVal,
641 0 : pabyRecord + pasFieldDesc[i].nStartByte +
642 0 : 4 * j,
643 : 4);
644 0 : CPL_MSBPTR32(&nVal);
645 0 : panValues[j] = nVal;
646 : }
647 0 : poFeature->SetField(i, pasFieldDesc[i].nItems,
648 : panValues);
649 0 : CPLFree(panValues);
650 : }
651 : else
652 : {
653 4 : int nVal = 0;
654 4 : memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte,
655 : 4);
656 4 : CPL_MSBPTR32(&nVal);
657 4 : poFeature->SetField(i, nVal);
658 : }
659 4 : }
660 : }
661 16 : else if (pasFieldDesc[i].eFormat == IEEE_REAL &&
662 16 : pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
663 16 : pasFieldDesc[i].nItems <=
664 16 : nRecordSize &&
665 16 : pasFieldDesc[i].nItemBytes == 4)
666 : {
667 8 : if (pasFieldDesc[i].nItems > 1)
668 : {
669 10 : double *padfValues = (double *)CPLMalloc(
670 5 : sizeof(double) * pasFieldDesc[i].nItems);
671 2565 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
672 : {
673 2560 : float fVal = 0.0f;
674 2560 : memcpy(&fVal,
675 2560 : pabyRecord + pasFieldDesc[i].nStartByte + 4 * j,
676 : 4);
677 2560 : CPL_MSBPTR32(&fVal);
678 2560 : padfValues[j] = (double)fVal;
679 : }
680 5 : poFeature->SetField(i, pasFieldDesc[i].nItems, padfValues);
681 5 : CPLFree(padfValues);
682 : }
683 : else
684 : {
685 3 : float fVal = 0.0f;
686 3 : memcpy(&fVal, pabyRecord + pasFieldDesc[i].nStartByte, 4);
687 3 : CPL_MSBPTR32(&fVal);
688 3 : poFeature->SetField(i, (double)fVal);
689 8 : }
690 : }
691 8 : else if (pasFieldDesc[i].eFormat == IEEE_REAL &&
692 8 : pasFieldDesc[i].nStartByte + pasFieldDesc[i].nItemBytes *
693 8 : pasFieldDesc[i].nItems <=
694 8 : nRecordSize &&
695 8 : pasFieldDesc[i].nItemBytes == 8)
696 : {
697 8 : if (pasFieldDesc[i].nItems > 1)
698 : {
699 4 : double *padfValues = (double *)CPLMalloc(
700 2 : sizeof(double) * pasFieldDesc[i].nItems);
701 12 : for (int j = 0; j < pasFieldDesc[i].nItems; j++)
702 : {
703 10 : double dfVal = 0.0;
704 10 : memcpy(&dfVal,
705 10 : pabyRecord + pasFieldDesc[i].nStartByte + 8 * j,
706 : 8);
707 10 : CPL_MSBPTR64(&dfVal);
708 10 : padfValues[j] = dfVal;
709 : }
710 2 : poFeature->SetField(i, pasFieldDesc[i].nItems, padfValues);
711 2 : CPLFree(padfValues);
712 : }
713 : else
714 : {
715 6 : double dfVal = 0.0;
716 6 : memcpy(&dfVal, pabyRecord + pasFieldDesc[i].nStartByte, 8);
717 6 : CPL_MSBPTR64(&dfVal);
718 6 : poFeature->SetField(i, dfVal);
719 : }
720 : }
721 : }
722 : }
723 : else
724 : {
725 0 : char **papszTokens = CSLTokenizeString2((const char *)pabyRecord, " ",
726 : CSLT_HONOURSTRINGS);
727 0 : const int nTokens = std::min(CSLCount(papszTokens), nFieldCount);
728 0 : for (int i = 0; i < nTokens; i++)
729 : {
730 0 : poFeature->SetField(i, papszTokens[i]);
731 : }
732 0 : CSLDestroy(papszTokens);
733 : }
734 :
735 3 : if (nLongitudeIndex >= 0 && nLatitudeIndex >= 0)
736 2 : poFeature->SetGeometryDirectly(
737 2 : new OGRPoint(poFeature->GetFieldAsDouble(nLongitudeIndex),
738 2 : poFeature->GetFieldAsDouble(nLatitudeIndex)));
739 :
740 3 : poFeature->SetFID(nNextFID++);
741 :
742 3 : return poFeature;
743 : }
744 :
745 : /************************************************************************/
746 : /* TestCapability() */
747 : /************************************************************************/
748 :
749 1 : int OGRPDSLayer::TestCapability(const char *pszCap)
750 :
751 : {
752 1 : if (EQUAL(pszCap, OLCFastFeatureCount) && m_poFilterGeom == nullptr &&
753 1 : m_poAttrQuery == nullptr)
754 1 : return TRUE;
755 :
756 0 : if (EQUAL(pszCap, OLCRandomRead))
757 0 : return TRUE;
758 :
759 0 : if (EQUAL(pszCap, OLCFastSetNextByIndex) && m_poFilterGeom == nullptr &&
760 0 : m_poAttrQuery == nullptr)
761 0 : return TRUE;
762 :
763 0 : return FALSE;
764 : }
765 :
766 : /************************************************************************/
767 : /* GetFeatureCount() */
768 : /************************************************************************/
769 :
770 1 : GIntBig OGRPDSLayer::GetFeatureCount(int bForce)
771 : {
772 1 : if (TestCapability(OLCFastFeatureCount))
773 1 : return nRecords;
774 :
775 0 : return OGRLayer::GetFeatureCount(bForce);
776 : }
777 :
778 : /************************************************************************/
779 : /* GetFeature() */
780 : /************************************************************************/
781 :
782 1 : OGRFeature *OGRPDSLayer::GetFeature(GIntBig nFID)
783 : {
784 1 : if (nFID < 0 || nFID >= nRecords)
785 0 : return nullptr;
786 :
787 1 : nNextFID = (int)nFID;
788 1 : VSIFSeekL(fpPDS, nStartBytes + nNextFID * nRecordSize, SEEK_SET);
789 1 : return GetNextRawFeature();
790 : }
791 :
792 : /************************************************************************/
793 : /* SetNextByIndex() */
794 : /************************************************************************/
795 :
796 0 : OGRErr OGRPDSLayer::SetNextByIndex(GIntBig nIndex)
797 : {
798 0 : if (!TestCapability(OLCFastSetNextByIndex))
799 0 : return OGRLayer::SetNextByIndex(nIndex);
800 :
801 0 : if (nIndex < 0 || nIndex >= nRecords)
802 0 : return OGRERR_FAILURE;
803 :
804 0 : nNextFID = (int)nIndex;
805 0 : VSIFSeekL(fpPDS, nStartBytes + nNextFID * nRecordSize, SEEK_SET);
806 0 : return OGRERR_NONE;
807 : }
808 :
809 : } // namespace OGRPDS
|