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