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