OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimDdfrecord.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * Copied from "gdal" project. See licence below.
3  *
4  * Project: ISO 8211 Access
5  * Purpose: Implements the DDFRecord class.
6  * Author: Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 1999, Frank Warmerdam
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  * $Id: ossimDdfrecord.cpp 15833 2009-10-29 01:41:53Z eshirschorn $
30  */
31 
32 #include <cstring>
36 
37 // CPL_CVSID("$Id: ossimDdfrecord.cpp 15833 2009-10-29 01:41:53Z eshirschorn $");
38 
39 static const size_t nLeaderSize = 24;
40 
41 /************************************************************************/
42 /* DDFRecord() */
43 /************************************************************************/
44 
46 
47 {
48  poModule = poModuleIn;
49 
50  nReuseHeader = false;
51 
52  nFieldOffset = 0;
53 
54  nDataSize = 0;
55  pachData = NULL;
56 
57  nFieldCount = 0;
58  paoFields = NULL;
59 
60  bIsClone = false;
61 
62  _sizeFieldTag = 4;
63  _sizeFieldPos = 0;
64  _sizeFieldLength = 0;
65 }
66 
67 /************************************************************************/
68 /* ~DDFRecord() */
69 /************************************************************************/
70 
72 
73 {
74  Clear();
75 
76  if( bIsClone )
77  poModule->RemoveCloneRecord( this );
78 }
79 
80 /************************************************************************/
81 /* Dump() */
82 /************************************************************************/
83 
94 void ossimDDFRecord::Dump( FILE * fp )
95 
96 {
97  fprintf( fp, "DDFRecord:\n" );
98  fprintf( fp, " nReuseHeader = %d\n", nReuseHeader );
99  fprintf( fp, " nDataSize = %d\n", nDataSize );
100  fprintf( fp,
101  " _sizeFieldLength=%d, _sizeFieldPos=%d, _sizeFieldTag=%d\n",
103 
104  for( int i = 0; i < nFieldCount; i++ )
105  {
106  paoFields[i].Dump( fp );
107  }
108 }
109 
110 /************************************************************************/
111 /* Read() */
112 /* */
113 /* Read a record of data from the file, and parse the header to */
114 /* build a field list for the record (or reuse the existing one */
115 /* if reusing headers). It is expected that the file pointer */
116 /* will be positioned at the beginning of a data record. It is */
117 /* the DDFModule's responsibility to do so. */
118 /* */
119 /* This method should only be called by the DDFModule class. */
120 /************************************************************************/
121 
123 
124 {
125 /* -------------------------------------------------------------------- */
126 /* Redefine the record on the basis of the header if needed. */
127 /* As a side effect this will read the data for the record as well.*/
128 /* -------------------------------------------------------------------- */
129  if( !nReuseHeader )
130  {
131  return( ReadHeader() );
132  }
133 
134 /* -------------------------------------------------------------------- */
135 /* Otherwise we read just the data and carefully overlay it on */
136 /* the previous records data without disturbing the rest of the */
137 /* record. */
138 /* -------------------------------------------------------------------- */
139  size_t nReadBytes;
140 
141  nReadBytes = fread( pachData + nFieldOffset, 1,
143  poModule->GetFP() );
144  if( nReadBytes != (size_t) (nDataSize - nFieldOffset)
145  && nReadBytes == 0
146  && feof( poModule->GetFP() ) )
147  {
148  return false;
149  }
150  else if( nReadBytes != (size_t) (nDataSize - nFieldOffset) )
151  {
153  << "Data record is short on DDF file.\n" << std::endl;
154 
155  return false;
156  }
157 
158  // notdef: eventually we may have to do something at this point to
159  // notify the DDFField's that their data values have changed.
160 
161  return true;
162 }
163 
164 /************************************************************************/
165 /* Write() */
166 /************************************************************************/
167 
182 
183 {
184  if( !ResetDirectory() )
185  return false;
186 
187 /* -------------------------------------------------------------------- */
188 /* Prepare leader. */
189 /* -------------------------------------------------------------------- */
190  char szLeader[nLeaderSize+1];
191 
192  memset( szLeader, ' ', nLeaderSize );
193 
194  sprintf( szLeader+0, "%05d",
195  static_cast<int>(nDataSize + nLeaderSize) );
196  szLeader[5] = ' ';
197  szLeader[6] = 'D';
198 
199  sprintf( szLeader + 12, "%05d",
200  static_cast<int>(nFieldOffset + nLeaderSize) );
201  szLeader[17] = ' ';
202 
203  szLeader[20] = (char) ('0' + _sizeFieldLength);
204  szLeader[21] = (char) ('0' + _sizeFieldPos);
205  szLeader[22] = '0';
206  szLeader[23] = (char) ('0' + _sizeFieldTag);
207 
208  /* notdef: lots of stuff missing */
209 
210 /* -------------------------------------------------------------------- */
211 /* Write the leader. */
212 /* -------------------------------------------------------------------- */
213  fwrite( szLeader, nLeaderSize, 1, poModule->GetFP() );
214 
215 /* -------------------------------------------------------------------- */
216 /* Write the remainder of the record. */
217 /* -------------------------------------------------------------------- */
218  fwrite( pachData, nDataSize, 1, poModule->GetFP() );
219 
220  return true;
221 }
222 
223 /************************************************************************/
224 /* Clear() */
225 /* */
226 /* Clear any information associated with the last header in */
227 /* preparation for reading a new header. */
228 /************************************************************************/
229 
231 
232 {
233  if( paoFields != NULL )
234  delete[] paoFields;
235 
236  paoFields = NULL;
237  nFieldCount = 0;
238 
239  if( pachData != NULL )
240  free( pachData );
241 
242  pachData = NULL;
243  nDataSize = 0;
244  nReuseHeader = false;
245 }
246 
247 /************************************************************************/
248 /* ReadHeader() */
249 /* */
250 /* This perform the header reading and parsing job for the */
251 /* Read() method. It reads the header, and builds a field */
252 /* list. */
253 /************************************************************************/
254 
256 
257 {
258 /* -------------------------------------------------------------------- */
259 /* Clear any existing information. */
260 /* -------------------------------------------------------------------- */
261  Clear();
262 
263 /* -------------------------------------------------------------------- */
264 /* Read the 24 byte leader. */
265 /* -------------------------------------------------------------------- */
266  char achLeader[nLeaderSize];
267  int nReadBytes;
268 
269  nReadBytes = (int)fread(achLeader,1,(int)nLeaderSize,poModule->GetFP());
270  if( nReadBytes == 0 && feof( poModule->GetFP() ) )
271  {
272  return false;
273  }
274  else if( nReadBytes != (int) nLeaderSize )
275  {
277  << "Leader is short on DDF file." << std::endl;
278 
279  return false;
280  }
281 
282 /* -------------------------------------------------------------------- */
283 /* Extract information from leader. */
284 /* -------------------------------------------------------------------- */
285  int _recLength, _fieldAreaStart;
286  char _leaderIden;
287 
288  _recLength = ossimDDFScanInt( achLeader+0, 5 );
289  _leaderIden = achLeader[6];
290  _fieldAreaStart = ossimDDFScanInt(achLeader+12,5);
291 
292  _sizeFieldLength = achLeader[20] - '0';
293  _sizeFieldPos = achLeader[21] - '0';
294  _sizeFieldTag = achLeader[23] - '0';
295 
296  if( _sizeFieldLength < 0 || _sizeFieldLength > 9
297  || _sizeFieldPos < 0 || _sizeFieldPos > 9
298  || _sizeFieldTag < 0 || _sizeFieldTag > 9 )
299  {
301  << "ISO8211 record leader appears to be corrupt." << std::endl;
302  return false;
303  }
304 
305  if( _leaderIden == 'R' )
306  nReuseHeader = true;
307 
308  nFieldOffset = _fieldAreaStart - nLeaderSize;
309 
310 /* -------------------------------------------------------------------- */
311 /* Is there anything seemly screwy about this record? */
312 /* -------------------------------------------------------------------- */
313  if(( _recLength < 24 || _recLength > 100000000
314  || _fieldAreaStart < 24 || _fieldAreaStart > 100000 )
315  && (_recLength != 0))
316  {
318  << "Data record appears to be corrupt on DDF file.\n"
319  << " -- ensure that the files were uncompressed without modifying\n"
320  << "carriage return/linefeeds (by default WINZIP does this)."
321  << std::endl;
322 
323  return false;
324  }
325 
326 /* ==================================================================== */
327 /* Handle the normal case with the record length available. */
328 /* ==================================================================== */
329  if(_recLength != 0) {
330 /* -------------------------------------------------------------------- */
331 /* Read the remainder of the record. */
332 /* -------------------------------------------------------------------- */
333  nDataSize = _recLength - nLeaderSize;
334  pachData = (char *) malloc(nDataSize);
335 
336  if( fread( pachData, 1, nDataSize, poModule->GetFP()) !=
337  (size_t) nDataSize )
338  {
340  << "Data record is short on DDF file."
341  << std::endl;
342 
343  return false;
344  }
345 
346 /* -------------------------------------------------------------------- */
347 /* If we don't find a field terminator at the end of the record */
348 /* we will read extra bytes till we get to it. */
349 /* -------------------------------------------------------------------- */
351  {
352  nDataSize++;
354 
355  if( fread( pachData + nDataSize - 1, 1, 1, poModule->GetFP() )
356  != 1 )
357  {
359  << "Data record is short on DDF file."
360  << std::endl;
361 
362  return false;
363  }
365  << "Didn't find field terminator, read one more byte."
366  << std::endl;
367  }
368 
369 /* -------------------------------------------------------------------- */
370 /* Loop over the directory entries, making a pass counting them. */
371 /* -------------------------------------------------------------------- */
372  int i;
373  int nFieldEntryWidth;
374 
375  nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag;
376  nFieldCount = 0;
377  for( i = 0; i < nDataSize; i += nFieldEntryWidth )
378  {
380  break;
381 
382  nFieldCount++;
383  }
384 
385 /* -------------------------------------------------------------------- */
386 /* Allocate, and read field definitions. */
387 /* -------------------------------------------------------------------- */
389 
390  for( i = 0; i < nFieldCount; i++ )
391  {
392  char szTag[128];
393  int nEntryOffset = i*nFieldEntryWidth;
394  int nFieldLength, nFieldPos;
395 
396 /* -------------------------------------------------------------------- */
397 /* Read the position information and tag. */
398 /* -------------------------------------------------------------------- */
399  strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag );
400  szTag[_sizeFieldTag] = '\0';
401 
402  nEntryOffset += _sizeFieldTag;
403  nFieldLength = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldLength );
404 
405  nEntryOffset += _sizeFieldLength;
406  nFieldPos = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldPos );
407 
408 /* -------------------------------------------------------------------- */
409 /* Find the corresponding field in the module directory. */
410 /* -------------------------------------------------------------------- */
411  ossimDDFFieldDefn *poFieldDefn = poModule->FindFieldDefn( szTag );
412 
413  if( poFieldDefn == NULL )
414  {
416  << "Undefined field `%s' encountered in data record."
417  << szTag << std::endl;
418  return false;
419  }
420 
421 /* -------------------------------------------------------------------- */
422 /* Assign info the DDFField. */
423 /* -------------------------------------------------------------------- */
424  paoFields[i].Initialize( poFieldDefn,
425  pachData + _fieldAreaStart + nFieldPos - nLeaderSize,
426  nFieldLength );
427  }
428 
429  return true;
430  }
431 /* ==================================================================== */
432 /* Handle the exceptional case where the record length is */
433 /* zero. In this case we have to read all the data based on */
434 /* the size of data items as per ISO8211 spec Annex C, 1.5.1. */
435 /* */
436 /* See Bugzilla bug 181 and test with file US4CN21M.000. */
437 /* ==================================================================== */
438  else {
440  << "Record with zero length, use variant (C.1.5.1) logic."
441  << std::endl;
442 
443  /* ----------------------------------------------------------------- */
444  /* _recLength == 0, handle the large record. */
445  /* */
446  /* Read the remainder of the record. */
447  /* ----------------------------------------------------------------- */
448  nDataSize = 0;
449  pachData = NULL;
450 
451  /* ----------------------------------------------------------------- */
452  /* Loop over the directory entries, making a pass counting them. */
453  /* ----------------------------------------------------------------- */
454  int nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag;
455  nFieldCount = 0;
456  int i=0;
457  char *tmpBuf = (char*)malloc(nFieldEntryWidth);
458 
459  // while we're not at the end, store this entry,
460  // and keep on reading...
461  do {
462  // read an Entry:
463  if(nFieldEntryWidth !=
464  (int) fread(tmpBuf, 1, nFieldEntryWidth, poModule->GetFP())) {
466  << "Data record is short on DDF file." << std::endl;
467  return false;
468  }
469 
470  // move this temp buffer into more permanent storage:
471  char *newBuf = (char*)malloc(nDataSize+nFieldEntryWidth);
472  if(pachData!=NULL) {
473  memcpy(newBuf, pachData, nDataSize);
474  free(pachData);
475  }
476  memcpy(&newBuf[nDataSize], tmpBuf, nFieldEntryWidth);
477  pachData = newBuf;
478  nDataSize += nFieldEntryWidth;
479 
480  if(OSSIM_DDF_FIELD_TERMINATOR != tmpBuf[0]) {
481  nFieldCount++;
482  }
483  }
484  while(OSSIM_DDF_FIELD_TERMINATOR != tmpBuf[0]);
485 
486  // Now, rewind a little. Only the TERMINATOR should have been read:
487  int rewindSize = nFieldEntryWidth - 1;
488  FILE *fp = poModule->GetFP();
489  long pos = ftell(fp) - rewindSize;
490  fseek(fp, pos, SEEK_SET);
491  nDataSize -= rewindSize;
492 
493  // --------------------------------------------------------------------
494  // Okay, now let's populate the heck out of pachData...
495  // --------------------------------------------------------------------
496  for(i=0; i<nFieldCount; i++) {
497  int nEntryOffset = (i*nFieldEntryWidth) + _sizeFieldTag;
498  int nFieldLength = ossimDDFScanInt(pachData + nEntryOffset,
500  char *tmpBuf = (char*)malloc(nFieldLength);
501 
502  // read an Entry:
503  if(nFieldLength !=
504  (int) fread(tmpBuf, 1, nFieldLength, poModule->GetFP())) {
506  << "Data record is short on DDF file." << std::endl;
507  return false;
508  }
509 
510  // move this temp buffer into more permanent storage:
511  char *newBuf = (char*)malloc(nDataSize+nFieldLength);
512  memcpy(newBuf, pachData, nDataSize);
513  free(pachData);
514  memcpy(&newBuf[nDataSize], tmpBuf, nFieldLength);
515  free(tmpBuf);
516  pachData = newBuf;
517  nDataSize += nFieldLength;
518  }
519 
520  /* ----------------------------------------------------------------- */
521  /* Allocate, and read field definitions. */
522  /* ----------------------------------------------------------------- */
524 
525  for( i = 0; i < nFieldCount; i++ )
526  {
527  char szTag[128];
528  int nEntryOffset = i*nFieldEntryWidth;
529  int nFieldLength, nFieldPos;
530 
531  /* ------------------------------------------------------------- */
532  /* Read the position information and tag. */
533  /* ------------------------------------------------------------- */
534  strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag );
535  szTag[_sizeFieldTag] = '\0';
536 
537  nEntryOffset += _sizeFieldTag;
538  nFieldLength = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldLength );
539 
540  nEntryOffset += _sizeFieldLength;
541  nFieldPos = ossimDDFScanInt( pachData+nEntryOffset, _sizeFieldPos );
542 
543  /* ------------------------------------------------------------- */
544  /* Find the corresponding field in the module directory. */
545  /* ------------------------------------------------------------- */
546  ossimDDFFieldDefn *poFieldDefn = poModule->FindFieldDefn( szTag );
547 
548  if( poFieldDefn == NULL )
549  {
551  << "Undefined field `%s' encountered in data record."
552  << szTag << std::endl;
553  return false;
554  }
555 
556  /* ------------------------------------------------------------- */
557  /* Assign info the DDFField. */
558  /* ------------------------------------------------------------- */
559 
560  paoFields[i].Initialize( poFieldDefn,
561  pachData + _fieldAreaStart
562  + nFieldPos - nLeaderSize,
563  nFieldLength );
564  }
565 
566  return true;
567  }
568 }
569 
570 /************************************************************************/
571 /* FindField() */
572 /************************************************************************/
573 
587 ossimDDFField * ossimDDFRecord::FindField( const char * pszName, int iFieldIndex )
588 
589 {
590  for( int i = 0; i < nFieldCount; i++ )
591  {
593  if( s == pszName)
594  {
595  if( iFieldIndex == 0 )
596  return paoFields + i;
597  else
598  iFieldIndex--;
599  }
600  }
601 
602  return NULL;
603 }
604 
605 /************************************************************************/
606 /* GetField() */
607 /************************************************************************/
608 
618 
619 {
620  if( i < 0 || i >= nFieldCount )
621  return NULL;
622  else
623  return paoFields + i;
624 }
625 
626 /************************************************************************/
627 /* GetIntSubfield() */
628 /************************************************************************/
629 
646 int ossimDDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex,
647  const char * pszSubfield, int iSubfieldIndex,
648  int * pnSuccess )
649 
650 {
651  ossimDDFField *poField;
652  int nDummyErr;
653 
654  if( pnSuccess == NULL )
655  pnSuccess = &nDummyErr;
656 
657  *pnSuccess = false;
658 
659 /* -------------------------------------------------------------------- */
660 /* Fetch the field. If this fails, return zero. */
661 /* -------------------------------------------------------------------- */
662  poField = FindField( pszField, iFieldIndex );
663  if( poField == NULL )
664  return 0;
665 
666 /* -------------------------------------------------------------------- */
667 /* Get the subfield definition */
668 /* -------------------------------------------------------------------- */
669  ossimDDFSubfieldDefn *poSFDefn;
670 
671  poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
672  if( poSFDefn == NULL )
673  return 0;
674 
675 /* -------------------------------------------------------------------- */
676 /* Get a pointer to the data. */
677 /* -------------------------------------------------------------------- */
678  int nBytesRemaining;
679 
680  const char *pachData = poField->GetSubfieldData(poSFDefn,
681  &nBytesRemaining,
682  iSubfieldIndex);
683 
684 /* -------------------------------------------------------------------- */
685 /* Return the extracted value. */
686 /* -------------------------------------------------------------------- */
687  *pnSuccess = true;
688 
689  return( poSFDefn->ExtractIntData( pachData, nBytesRemaining, NULL ) );
690 }
691 
692 /************************************************************************/
693 /* GetFloatSubfield() */
694 /************************************************************************/
695 
712 double ossimDDFRecord::GetFloatSubfield( const char * pszField, int iFieldIndex,
713  const char * pszSubfield, int iSubfieldIndex,
714  int * pnSuccess )
715 
716 {
717  ossimDDFField *poField;
718  int nDummyErr;
719 
720  if( pnSuccess == NULL )
721  pnSuccess = &nDummyErr;
722 
723  *pnSuccess = false;
724 
725 /* -------------------------------------------------------------------- */
726 /* Fetch the field. If this fails, return zero. */
727 /* -------------------------------------------------------------------- */
728  poField = FindField( pszField, iFieldIndex );
729  if( poField == NULL )
730  return 0;
731 
732 /* -------------------------------------------------------------------- */
733 /* Get the subfield definition */
734 /* -------------------------------------------------------------------- */
735  ossimDDFSubfieldDefn *poSFDefn;
736 
737  poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
738  if( poSFDefn == NULL )
739  return 0;
740 
741 /* -------------------------------------------------------------------- */
742 /* Get a pointer to the data. */
743 /* -------------------------------------------------------------------- */
744  int nBytesRemaining;
745 
746  const char *pachData = poField->GetSubfieldData(poSFDefn,
747  &nBytesRemaining,
748  iSubfieldIndex);
749 
750 /* -------------------------------------------------------------------- */
751 /* Return the extracted value. */
752 /* -------------------------------------------------------------------- */
753  *pnSuccess = true;
754 
755  return( poSFDefn->ExtractFloatData( pachData, nBytesRemaining, NULL ) );
756 }
757 
758 /************************************************************************/
759 /* GetStringSubfield() */
760 /************************************************************************/
761 
780 const char *
781 ossimDDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
782  const char * pszSubfield, int iSubfieldIndex,
783  int * pnSuccess )
784 
785 {
786  ossimDDFField *poField;
787  int nDummyErr;
788 
789  if( pnSuccess == NULL )
790  pnSuccess = &nDummyErr;
791 
792  *pnSuccess = false;
793 
794 /* -------------------------------------------------------------------- */
795 /* Fetch the field. If this fails, return zero. */
796 /* -------------------------------------------------------------------- */
797  poField = FindField( pszField, iFieldIndex );
798  if( poField == NULL )
799  return NULL;
800 
801 /* -------------------------------------------------------------------- */
802 /* Get the subfield definition */
803 /* -------------------------------------------------------------------- */
804  ossimDDFSubfieldDefn *poSFDefn;
805 
806  poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
807  if( poSFDefn == NULL )
808  return NULL;
809 
810 /* -------------------------------------------------------------------- */
811 /* Get a pointer to the data. */
812 /* -------------------------------------------------------------------- */
813  int nBytesRemaining;
814 
815  const char *pachData = poField->GetSubfieldData(poSFDefn,
816  &nBytesRemaining,
817  iSubfieldIndex);
818 
819 /* -------------------------------------------------------------------- */
820 /* Return the extracted value. */
821 /* -------------------------------------------------------------------- */
822  *pnSuccess = true;
823 
824  return( poSFDefn->ExtractStringData( pachData, nBytesRemaining, NULL ) );
825 }
826 
827 /************************************************************************/
828 /* Clone() */
829 /************************************************************************/
830 
848 
849 {
850  ossimDDFRecord *poNR;
851 
852  poNR = new ossimDDFRecord( poModule );
853 
854  poNR->nReuseHeader = false;
855  poNR->nFieldOffset = nFieldOffset;
856 
857  poNR->nDataSize = nDataSize;
858  poNR->pachData = (char *) malloc(nDataSize);
859  memcpy( poNR->pachData, pachData, nDataSize );
860 
861  poNR->nFieldCount = nFieldCount;
862  poNR->paoFields = new ossimDDFField[nFieldCount];
863  for( int i = 0; i < nFieldCount; i++ )
864  {
865  int nOffset;
866 
867  nOffset = (paoFields[i].GetData() - pachData);
868  poNR->paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
869  poNR->pachData + nOffset,
870  paoFields[i].GetDataSize() );
871  }
872 
873  poNR->bIsClone = true;
874  poModule->AddCloneRecord( poNR );
875 
876  return poNR;
877 }
878 
879 /************************************************************************/
880 /* CloneOn() */
881 /************************************************************************/
882 
904 
905 {
906 /* -------------------------------------------------------------------- */
907 /* Verify that all fields have a corresponding field definition */
908 /* on the target module. */
909 /* -------------------------------------------------------------------- */
910  int i;
911 
912  for( i = 0; i < nFieldCount; i++ )
913  {
915 
916  if( poTargetModule->FindFieldDefn( poDefn->GetName() ) == NULL )
917  return NULL;
918  }
919 
920 /* -------------------------------------------------------------------- */
921 /* Create a clone. */
922 /* -------------------------------------------------------------------- */
923  ossimDDFRecord *poClone;
924 
925  poClone = Clone();
926 
927 /* -------------------------------------------------------------------- */
928 /* Update all internal information to reference other module. */
929 /* -------------------------------------------------------------------- */
930  for( i = 0; i < nFieldCount; i++ )
931  {
932  ossimDDFField *poField = poClone->paoFields+i;
933  ossimDDFFieldDefn *poDefn;
934 
935  poDefn = poTargetModule->FindFieldDefn(
936  poField->GetFieldDefn()->GetName() );
937 
938  poField->Initialize( poDefn, poField->GetData(),
939  poField->GetDataSize() );
940  }
941 
942  poModule->RemoveCloneRecord( poClone );
943  poClone->poModule = poTargetModule;
944  poTargetModule->AddCloneRecord( poClone );
945 
946  return poClone;
947 }
948 
949 
950 /************************************************************************/
951 /* DeleteField() */
952 /************************************************************************/
953 
973 
974 {
975  int iTarget, i;
976 
977 /* -------------------------------------------------------------------- */
978 /* Find which field we are to delete. */
979 /* -------------------------------------------------------------------- */
980  for( iTarget = 0; iTarget < nFieldCount; iTarget++ )
981  {
982  if( paoFields + iTarget == poTarget )
983  break;
984  }
985 
986  if( iTarget == nFieldCount )
987  return false;
988 
989 /* -------------------------------------------------------------------- */
990 /* Change the target fields data size to zero. This takes care */
991 /* of repacking the data array, and updating all the following */
992 /* field data pointers. */
993 /* -------------------------------------------------------------------- */
994  ResizeField( poTarget, 0 );
995 
996 /* -------------------------------------------------------------------- */
997 /* remove the target field, moving down all the other fields */
998 /* one step in the field list. */
999 /* -------------------------------------------------------------------- */
1000  for( i = iTarget; i < nFieldCount-1; i++ )
1001  {
1002  paoFields[i] = paoFields[i+1];
1003  }
1004 
1005  nFieldCount--;
1006 
1007  return true;
1008 }
1009 
1010 /************************************************************************/
1011 /* ResizeField() */
1012 /************************************************************************/
1013 
1029 int ossimDDFRecord::ResizeField( ossimDDFField *poField, int nNewDataSize )
1030 
1031 {
1032  int iTarget, i;
1033  int nBytesToMove;
1034 
1035 /* -------------------------------------------------------------------- */
1036 /* Find which field we are to resize. */
1037 /* -------------------------------------------------------------------- */
1038  for( iTarget = 0; iTarget < nFieldCount; iTarget++ )
1039  {
1040  if( paoFields + iTarget == poField )
1041  break;
1042  }
1043 
1044  if( iTarget == nFieldCount )
1045  {
1046  // CPLAssert( false );
1047  return false;
1048  }
1049 
1050 /* -------------------------------------------------------------------- */
1051 /* Reallocate the data buffer accordingly. */
1052 /* -------------------------------------------------------------------- */
1053  int nBytesToAdd = nNewDataSize - poField->GetDataSize();
1054  const char *pachOldData = pachData;
1055 
1056  // Don't realloc things smaller ... we will cut off some data.
1057  if( nBytesToAdd > 0 )
1058  pachData = (char *) ossimCPLRealloc(pachData, nDataSize + nBytesToAdd );
1059 
1060  nDataSize += nBytesToAdd;
1061 
1062 /* -------------------------------------------------------------------- */
1063 /* How much data needs to be shifted up or down after this field? */
1064 /* -------------------------------------------------------------------- */
1065  nBytesToMove = nDataSize
1066  - (poField->GetData()+poField->GetDataSize()-pachOldData+nBytesToAdd);
1067 
1068 /* -------------------------------------------------------------------- */
1069 /* Update fields to point into newly allocated buffer. */
1070 /* -------------------------------------------------------------------- */
1071  for( i = 0; i < nFieldCount; i++ )
1072  {
1073  int nOffset;
1074 
1075  nOffset = paoFields[i].GetData() - pachOldData;
1076  paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
1077  pachData + nOffset,
1078  paoFields[i].GetDataSize() );
1079  }
1080 
1081 /* -------------------------------------------------------------------- */
1082 /* Shift the data beyond this field up or down as needed. */
1083 /* -------------------------------------------------------------------- */
1084  if( nBytesToMove > 0 )
1085  memmove( (char *)poField->GetData()+poField->GetDataSize()+nBytesToAdd,
1086  (char *)poField->GetData()+poField->GetDataSize(),
1087  nBytesToMove );
1088 
1089 /* -------------------------------------------------------------------- */
1090 /* Update the target fields info. */
1091 /* -------------------------------------------------------------------- */
1092  poField->Initialize( poField->GetFieldDefn(),
1093  poField->GetData(),
1094  poField->GetDataSize() + nBytesToAdd );
1095 
1096 /* -------------------------------------------------------------------- */
1097 /* Shift all following fields down, and update their data */
1098 /* locations. */
1099 /* -------------------------------------------------------------------- */
1100  if( nBytesToAdd < 0 )
1101  {
1102  for( i = iTarget+1; i < nFieldCount; i++ )
1103  {
1104  char *pszOldDataLocation;
1105 
1106  pszOldDataLocation = (char *) paoFields[i].GetData();
1107 
1108  paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
1109  pszOldDataLocation + nBytesToAdd,
1110  paoFields[i].GetDataSize() );
1111  }
1112  }
1113  else
1114  {
1115  for( i = nFieldCount-1; i > iTarget; i-- )
1116  {
1117  char *pszOldDataLocation;
1118 
1119  pszOldDataLocation = (char *) paoFields[i].GetData();
1120 
1121  paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
1122  pszOldDataLocation + nBytesToAdd,
1123  paoFields[i].GetDataSize() );
1124  }
1125  }
1126 
1127  return true;
1128 }
1129 
1130 /************************************************************************/
1131 /* AddField() */
1132 /************************************************************************/
1133 
1152 
1153 {
1154 /* -------------------------------------------------------------------- */
1155 /* Reallocate the fields array larger by one, and initialize */
1156 /* the new field. */
1157 /* -------------------------------------------------------------------- */
1158  ossimDDFField *paoNewFields;
1159 
1160  paoNewFields = new ossimDDFField[nFieldCount+1];
1161  if( nFieldCount > 0 )
1162  {
1163  memcpy( paoNewFields, paoFields, sizeof(ossimDDFField) * nFieldCount );
1164  delete[] paoFields;
1165  }
1166  paoFields = paoNewFields;
1167  nFieldCount++;
1168 
1169 /* -------------------------------------------------------------------- */
1170 /* Initialize the new field properly. */
1171 /* -------------------------------------------------------------------- */
1172  if( nFieldCount == 1 )
1173  {
1174  paoFields[0].Initialize( poDefn, GetData(), 0 );
1175  }
1176  else
1177  {
1179  poDefn,
1182  0 );
1183  }
1184 
1185 /* -------------------------------------------------------------------- */
1186 /* Initialize field. */
1187 /* -------------------------------------------------------------------- */
1189 
1190  return paoFields + (nFieldCount - 1);
1191 }
1192 
1193 /************************************************************************/
1194 /* SetFieldRaw() */
1195 /************************************************************************/
1196 
1210 int
1211 ossimDDFRecord::SetFieldRaw( ossimDDFField *poField, int iIndexWithinField,
1212  const char *pachRawData, int nRawDataSize )
1213 
1214 {
1215  int iTarget, nRepeatCount;
1216 
1217 /* -------------------------------------------------------------------- */
1218 /* Find which field we are to update. */
1219 /* -------------------------------------------------------------------- */
1220  for( iTarget = 0; iTarget < nFieldCount; iTarget++ )
1221  {
1222  if( paoFields + iTarget == poField )
1223  break;
1224  }
1225 
1226  if( iTarget == nFieldCount )
1227  return false;
1228 
1229  nRepeatCount = poField->GetRepeatCount();
1230 
1231  if( iIndexWithinField < 0 || iIndexWithinField > nRepeatCount )
1232  return false;
1233 
1234 /* -------------------------------------------------------------------- */
1235 /* Are we adding an instance? This is easier and different */
1236 /* than replacing an existing instance. */
1237 /* -------------------------------------------------------------------- */
1238  if( iIndexWithinField == nRepeatCount
1239  || !poField->GetFieldDefn()->IsRepeating() )
1240  {
1241  char *pachFieldData;
1242  int nOldSize;
1243 
1244  if( !poField->GetFieldDefn()->IsRepeating() && iIndexWithinField != 0 )
1245  return false;
1246 
1247  nOldSize = poField->GetDataSize();
1248  if( nOldSize == 0 )
1249  nOldSize++; // for added DDF_FIELD_TERMINATOR.
1250 
1251  if( !ResizeField( poField, nOldSize + nRawDataSize ) )
1252  return false;
1253 
1254  pachFieldData = (char *) poField->GetData();
1255  memcpy( pachFieldData + nOldSize - 1,
1256  pachRawData, nRawDataSize );
1257  pachFieldData[nOldSize+nRawDataSize-1] = OSSIM_DDF_FIELD_TERMINATOR;
1258 
1259  return true;
1260  }
1261 
1262 /* -------------------------------------------------------------------- */
1263 /* Get a pointer to the start of the existing data for this */
1264 /* iteration of the field. */
1265 /* -------------------------------------------------------------------- */
1266  const char *pachWrkData;
1267  int nInstanceSize;
1268 
1269  // We special case this to avoid alot of warnings when initializing
1270  // the field the first time.
1271  if( poField->GetDataSize() == 0 )
1272  {
1273  pachWrkData = poField->GetData();
1274  nInstanceSize = 0;
1275  }
1276  else
1277  {
1278  pachWrkData = poField->GetInstanceData( iIndexWithinField,
1279  &nInstanceSize );
1280  }
1281 
1282 /* -------------------------------------------------------------------- */
1283 /* Create new image of this whole field. */
1284 /* -------------------------------------------------------------------- */
1285  char *pachNewImage;
1286  int nPreBytes, nPostBytes, nNewFieldSize;
1287 
1288  nNewFieldSize = poField->GetDataSize() - nInstanceSize + nRawDataSize;
1289 
1290  pachNewImage = (char *) malloc(nNewFieldSize);
1291 
1292  nPreBytes = pachWrkData - poField->GetData();
1293  nPostBytes = poField->GetDataSize() - nPreBytes - nInstanceSize;
1294 
1295  memcpy( pachNewImage, poField->GetData(), nPreBytes );
1296  memcpy( pachNewImage + nPreBytes + nRawDataSize,
1297  poField->GetData() + nPreBytes + nInstanceSize,
1298  nPostBytes );
1299  memcpy( pachNewImage + nPreBytes, pachRawData, nRawDataSize );
1300 
1301 /* -------------------------------------------------------------------- */
1302 /* Resize the field to the desired new size. */
1303 /* -------------------------------------------------------------------- */
1304  ResizeField( poField, nNewFieldSize );
1305 
1306  memcpy( (void *) poField->GetData(), pachNewImage, nNewFieldSize );
1307  free( pachNewImage );
1308 
1309  return true;
1310 }
1311 
1312 /************************************************************************/
1313 /* UpdateFieldRaw() */
1314 /************************************************************************/
1315 
1316 int
1317 ossimDDFRecord::UpdateFieldRaw( ossimDDFField *poField, int iIndexWithinField,
1318  int nStartOffset, int nOldSize,
1319  const char *pachRawData, int nRawDataSize )
1320 
1321 {
1322  int iTarget, nRepeatCount;
1323 
1324 /* -------------------------------------------------------------------- */
1325 /* Find which field we are to update. */
1326 /* -------------------------------------------------------------------- */
1327  for( iTarget = 0; iTarget < nFieldCount; iTarget++ )
1328  {
1329  if( paoFields + iTarget == poField )
1330  break;
1331  }
1332 
1333  if( iTarget == nFieldCount )
1334  return false;
1335 
1336  nRepeatCount = poField->GetRepeatCount();
1337 
1338  if( iIndexWithinField < 0 || iIndexWithinField >= nRepeatCount )
1339  return false;
1340 
1341 /* -------------------------------------------------------------------- */
1342 /* Figure out how much pre and post data there is. */
1343 /* -------------------------------------------------------------------- */
1344  char *pachWrkData;
1345  int nInstanceSize, nPostBytes, nPreBytes;
1346 
1347  pachWrkData = (char *) poField->GetInstanceData( iIndexWithinField,
1348  &nInstanceSize );
1349  nPreBytes = pachWrkData - poField->GetData() + nStartOffset;
1350  nPostBytes = poField->GetDataSize() - nPreBytes - nOldSize;
1351 
1352 /* -------------------------------------------------------------------- */
1353 /* If we aren't changing the size, just copy over the existing */
1354 /* data. */
1355 /* -------------------------------------------------------------------- */
1356  if( nOldSize == nRawDataSize )
1357  {
1358  memcpy( pachWrkData + nStartOffset, pachRawData, nRawDataSize );
1359  return true;
1360  }
1361 
1362 /* -------------------------------------------------------------------- */
1363 /* If we are shrinking, move in the new data, and shuffle down */
1364 /* the old before resizing. */
1365 /* -------------------------------------------------------------------- */
1366  if( nRawDataSize < nOldSize )
1367  {
1368  memcpy( ((char*) poField->GetData()) + nPreBytes,
1369  pachRawData, nRawDataSize );
1370  memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize,
1371  ((char *) poField->GetData()) + nPreBytes + nOldSize,
1372  nPostBytes );
1373  }
1374 
1375 /* -------------------------------------------------------------------- */
1376 /* Resize the whole buffer. */
1377 /* -------------------------------------------------------------------- */
1378  if( !ResizeField( poField,
1379  poField->GetDataSize() - nOldSize + nRawDataSize ) )
1380  return false;
1381 
1382 /* -------------------------------------------------------------------- */
1383 /* If we growing the buffer, shuffle up the post data, and */
1384 /* move in our new values. */
1385 /* -------------------------------------------------------------------- */
1386  if( nRawDataSize >= nOldSize )
1387  {
1388  memmove( ((char *) poField->GetData()) + nPreBytes + nRawDataSize,
1389  ((char *) poField->GetData()) + nPreBytes + nOldSize,
1390  nPostBytes );
1391  memcpy( ((char*) poField->GetData()) + nPreBytes,
1392  pachRawData, nRawDataSize );
1393  }
1394 
1395  return true;
1396 }
1397 
1398 /************************************************************************/
1399 /* ResetDirectory() */
1400 /* */
1401 /* Re-prepares the directory information for the record. */
1402 /************************************************************************/
1403 
1405 
1406 {
1407  int iField;
1408 
1409 /* -------------------------------------------------------------------- */
1410 /* Eventually we should try to optimize the size of offset and */
1411 /* field length. For now we will use 5 for each which is */
1412 /* pretty big. */
1413 /* -------------------------------------------------------------------- */
1414  _sizeFieldPos = 5;
1415  _sizeFieldLength = 5;
1416 
1417 /* -------------------------------------------------------------------- */
1418 /* Compute how large the directory needs to be. */
1419 /* -------------------------------------------------------------------- */
1420  int nEntrySize, nDirSize;
1421 
1422  nEntrySize = _sizeFieldPos + _sizeFieldLength + _sizeFieldTag;
1423  nDirSize = nEntrySize * nFieldCount + 1;
1424 
1425 /* -------------------------------------------------------------------- */
1426 /* If the directory size is different than what is currently */
1427 /* reserved for it, we must resize. */
1428 /* -------------------------------------------------------------------- */
1429  if( nDirSize != nFieldOffset )
1430  {
1431  char *pachNewData;
1432  int nNewDataSize;
1433 
1434  nNewDataSize = nDataSize - nFieldOffset + nDirSize;
1435  pachNewData = (char *) malloc(nNewDataSize);
1436  memcpy( pachNewData + nDirSize,
1438  nNewDataSize - nDirSize );
1439 
1440  for( iField = 0; iField < nFieldCount; iField++ )
1441  {
1442  int nOffset;
1443  ossimDDFField *poField = GetField( iField );
1444 
1445  nOffset = poField->GetData() - pachData - nFieldOffset + nDirSize;
1446  poField->Initialize( poField->GetFieldDefn(),
1447  pachNewData + nOffset,
1448  poField->GetDataSize() );
1449  }
1450 
1451  free( pachData );
1452  pachData = pachNewData;
1453  nDataSize = nNewDataSize;
1454  nFieldOffset = nDirSize;
1455  }
1456 
1457 /* -------------------------------------------------------------------- */
1458 /* Now set each directory entry. */
1459 /* -------------------------------------------------------------------- */
1460  for( iField = 0; iField < nFieldCount; iField++ )
1461  {
1462  ossimDDFField *poField = GetField( iField );
1463  ossimDDFFieldDefn *poDefn = poField->GetFieldDefn();
1464  char szFormat[128];
1465 
1466  sprintf( szFormat, "%%%ds%%0%dd%%0%dd",
1468 
1469  sprintf( pachData + nEntrySize * iField, szFormat,
1470  poDefn->GetName(), poField->GetDataSize(),
1471  poField->GetData() - pachData - nFieldOffset );
1472  }
1473 
1475 
1476  return true;
1477 }
1478 
1479 /************************************************************************/
1480 /* CreateDefaultFieldInstance() */
1481 /************************************************************************/
1482 
1501  int iIndexWithinField )
1502 
1503 {
1504  int nRawSize, nSuccess;
1505  char *pachRawData;
1506 
1507  pachRawData = poField->GetFieldDefn()->GetDefaultValue( &nRawSize );
1508  if( pachRawData == NULL )
1509  return false;
1510 
1511  nSuccess = SetFieldRaw( poField, iIndexWithinField, pachRawData, nRawSize);
1512 
1513  free( pachRawData );
1514 
1515  return nSuccess;
1516 }
1517 
1518 /************************************************************************/
1519 /* SetStringSubfield() */
1520 /************************************************************************/
1521 
1540 int ossimDDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
1541  const char *pszSubfield, int iSubfieldIndex,
1542  const char *pszValue, int nValueLength )
1543 
1544 {
1545 /* -------------------------------------------------------------------- */
1546 /* Fetch the field. If this fails, return zero. */
1547 /* -------------------------------------------------------------------- */
1548  ossimDDFField *poField;
1549 
1550  poField = FindField( pszField, iFieldIndex );
1551  if( poField == NULL )
1552  return false;
1553 
1554 /* -------------------------------------------------------------------- */
1555 /* Get the subfield definition */
1556 /* -------------------------------------------------------------------- */
1557  ossimDDFSubfieldDefn *poSFDefn;
1558 
1559  poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
1560  if( poSFDefn == NULL )
1561  return false;
1562 
1563 /* -------------------------------------------------------------------- */
1564 /* How long will the formatted value be? */
1565 /* -------------------------------------------------------------------- */
1566  int nFormattedLen;
1567 
1568  if( !poSFDefn->FormatStringValue( NULL, 0, &nFormattedLen, pszValue,
1569  nValueLength ) )
1570  return false;
1571 
1572 /* -------------------------------------------------------------------- */
1573 /* Get a pointer to the data. */
1574 /* -------------------------------------------------------------------- */
1575  int nMaxBytes;
1576  char *pachSubfieldData = (char *)
1577  poField->GetSubfieldData(poSFDefn, &nMaxBytes,
1578  iSubfieldIndex);
1579 
1580 /* -------------------------------------------------------------------- */
1581 /* Add new instance if we have run out of data. */
1582 /* -------------------------------------------------------------------- */
1583  if( nMaxBytes == 0
1584  || (nMaxBytes == 1 && pachSubfieldData[0] == OSSIM_DDF_FIELD_TERMINATOR) )
1585  {
1586  CreateDefaultFieldInstance( poField, iSubfieldIndex );
1587 
1588  // Refetch.
1589  pachSubfieldData = (char *)
1590  poField->GetSubfieldData(poSFDefn, &nMaxBytes,
1591  iSubfieldIndex);
1592  }
1593 
1594 /* -------------------------------------------------------------------- */
1595 /* If the new length matches the existing length, just overlay */
1596 /* and return. */
1597 /* -------------------------------------------------------------------- */
1598  int nExistingLength;
1599 
1600  poSFDefn->GetDataLength( pachSubfieldData, nMaxBytes, &nExistingLength );
1601 
1602  if( nExistingLength == nFormattedLen )
1603  {
1604  return poSFDefn->FormatStringValue( pachSubfieldData, nFormattedLen,
1605  NULL, pszValue, nValueLength );
1606  }
1607 
1608 /* -------------------------------------------------------------------- */
1609 /* We will need to resize the raw data. */
1610 /* -------------------------------------------------------------------- */
1611  const char *pachFieldInstData;
1612  int nInstanceSize, nStartOffset, nSuccess;
1613  char *pachNewData;
1614 
1615  pachFieldInstData = poField->GetInstanceData( iFieldIndex,
1616  &nInstanceSize );
1617 
1618  nStartOffset = pachSubfieldData - pachFieldInstData;
1619 
1620  pachNewData = (char *) malloc(nFormattedLen);
1621  poSFDefn->FormatStringValue( pachNewData, nFormattedLen, NULL,
1622  pszValue, nValueLength );
1623 
1624  nSuccess = UpdateFieldRaw( poField, iFieldIndex,
1625  nStartOffset, nExistingLength,
1626  pachNewData, nFormattedLen );
1627 
1628  free( pachNewData );
1629 
1630  return nSuccess;
1631 }
1632 
1633 /************************************************************************/
1634 /* SetIntSubfield() */
1635 /************************************************************************/
1636 
1652 int ossimDDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
1653  const char *pszSubfield, int iSubfieldIndex,
1654  int nNewValue )
1655 
1656 {
1657 /* -------------------------------------------------------------------- */
1658 /* Fetch the field. If this fails, return zero. */
1659 /* -------------------------------------------------------------------- */
1660  ossimDDFField *poField;
1661 
1662  poField = FindField( pszField, iFieldIndex );
1663  if( poField == NULL )
1664  return false;
1665 
1666 /* -------------------------------------------------------------------- */
1667 /* Get the subfield definition */
1668 /* -------------------------------------------------------------------- */
1669  ossimDDFSubfieldDefn *poSFDefn;
1670 
1671  poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
1672  if( poSFDefn == NULL )
1673  return false;
1674 
1675 /* -------------------------------------------------------------------- */
1676 /* How long will the formatted value be? */
1677 /* -------------------------------------------------------------------- */
1678  int nFormattedLen;
1679 
1680  if( !poSFDefn->FormatIntValue( NULL, 0, &nFormattedLen, nNewValue ) )
1681  return false;
1682 
1683 /* -------------------------------------------------------------------- */
1684 /* Get a pointer to the data. */
1685 /* -------------------------------------------------------------------- */
1686  int nMaxBytes;
1687  char *pachSubfieldData = (char *)
1688  poField->GetSubfieldData(poSFDefn, &nMaxBytes,
1689  iSubfieldIndex);
1690 
1691 /* -------------------------------------------------------------------- */
1692 /* Add new instance if we have run out of data. */
1693 /* -------------------------------------------------------------------- */
1694  if( nMaxBytes == 0
1695  || (nMaxBytes == 1 && pachSubfieldData[0] == OSSIM_DDF_FIELD_TERMINATOR) )
1696  {
1697  CreateDefaultFieldInstance( poField, iSubfieldIndex );
1698 
1699  // Refetch.
1700  pachSubfieldData = (char *)
1701  poField->GetSubfieldData(poSFDefn, &nMaxBytes,
1702  iSubfieldIndex);
1703  }
1704 
1705 /* -------------------------------------------------------------------- */
1706 /* If the new length matches the existing length, just overlay */
1707 /* and return. */
1708 /* -------------------------------------------------------------------- */
1709  int nExistingLength;
1710 
1711  poSFDefn->GetDataLength( pachSubfieldData, nMaxBytes, &nExistingLength );
1712 
1713  if( nExistingLength == nFormattedLen )
1714  {
1715  return poSFDefn->FormatIntValue( pachSubfieldData, nFormattedLen,
1716  NULL, nNewValue );
1717  }
1718 
1719 /* -------------------------------------------------------------------- */
1720 /* We will need to resize the raw data. */
1721 /* -------------------------------------------------------------------- */
1722  const char *pachFieldInstData;
1723  int nInstanceSize, nStartOffset, nSuccess;
1724  char *pachNewData;
1725 
1726  pachFieldInstData = poField->GetInstanceData( iFieldIndex,
1727  &nInstanceSize );
1728 
1729  nStartOffset = pachSubfieldData - pachFieldInstData;
1730 
1731  pachNewData = (char *) malloc(nFormattedLen);
1732  poSFDefn->FormatIntValue( pachNewData, nFormattedLen, NULL,
1733  nNewValue );
1734 
1735  nSuccess = UpdateFieldRaw( poField, iFieldIndex,
1736  nStartOffset, nExistingLength,
1737  pachNewData, nFormattedLen );
1738 
1739  free( pachNewData );
1740 
1741  return nSuccess;
1742 }
1743 
1744 /************************************************************************/
1745 /* SetFloatSubfield() */
1746 /************************************************************************/
1747 
1763 int ossimDDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
1764  const char *pszSubfield, int iSubfieldIndex,
1765  double dfNewValue )
1766 
1767 {
1768 /* -------------------------------------------------------------------- */
1769 /* Fetch the field. If this fails, return zero. */
1770 /* -------------------------------------------------------------------- */
1771  ossimDDFField *poField;
1772 
1773  poField = FindField( pszField, iFieldIndex );
1774  if( poField == NULL )
1775  return false;
1776 
1777 /* -------------------------------------------------------------------- */
1778 /* Get the subfield definition */
1779 /* -------------------------------------------------------------------- */
1780  ossimDDFSubfieldDefn *poSFDefn;
1781 
1782  poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
1783  if( poSFDefn == NULL )
1784  return false;
1785 
1786 /* -------------------------------------------------------------------- */
1787 /* How long will the formatted value be? */
1788 /* -------------------------------------------------------------------- */
1789  int nFormattedLen;
1790 
1791  if( !poSFDefn->FormatFloatValue( NULL, 0, &nFormattedLen, dfNewValue ) )
1792  return false;
1793 
1794 /* -------------------------------------------------------------------- */
1795 /* Get a pointer to the data. */
1796 /* -------------------------------------------------------------------- */
1797  int nMaxBytes;
1798  char *pachSubfieldData = (char *)
1799  poField->GetSubfieldData(poSFDefn, &nMaxBytes,
1800  iSubfieldIndex);
1801 
1802 /* -------------------------------------------------------------------- */
1803 /* Add new instance if we have run out of data. */
1804 /* -------------------------------------------------------------------- */
1805  if( nMaxBytes == 0 ||
1806  (nMaxBytes == 1 && pachSubfieldData[0] == OSSIM_DDF_FIELD_TERMINATOR) )
1807  {
1808  CreateDefaultFieldInstance( poField, iSubfieldIndex );
1809 
1810  // Refetch.
1811  pachSubfieldData = (char *)
1812  poField->GetSubfieldData(poSFDefn, &nMaxBytes,
1813  iSubfieldIndex);
1814  }
1815 
1816 /* -------------------------------------------------------------------- */
1817 /* If the new length matches the existing length, just overlay */
1818 /* and return. */
1819 /* -------------------------------------------------------------------- */
1820  int nExistingLength;
1821 
1822  poSFDefn->GetDataLength( pachSubfieldData, nMaxBytes, &nExistingLength );
1823 
1824  if( nExistingLength == nFormattedLen )
1825  {
1826  return poSFDefn->FormatFloatValue( pachSubfieldData, nFormattedLen,
1827  NULL, dfNewValue );
1828  }
1829 
1830 /* -------------------------------------------------------------------- */
1831 /* We will need to resize the raw data. */
1832 /* -------------------------------------------------------------------- */
1833  const char *pachFieldInstData;
1834  int nInstanceSize, nStartOffset, nSuccess;
1835  char *pachNewData;
1836 
1837  pachFieldInstData = poField->GetInstanceData( iFieldIndex,
1838  &nInstanceSize );
1839 
1840  nStartOffset = (int) (pachSubfieldData - pachFieldInstData);
1841 
1842  pachNewData = (char *) malloc(nFormattedLen);
1843  poSFDefn->FormatFloatValue( pachNewData, nFormattedLen, NULL,
1844  dfNewValue );
1845 
1846  nSuccess = UpdateFieldRaw( poField, iFieldIndex,
1847  nStartOffset, nExistingLength,
1848  pachNewData, nFormattedLen );
1849 
1850  free( pachNewData );
1851 
1852  return nSuccess;
1853 }
void Dump(FILE *)
Write out record contents to debugging file.
void Initialize(ossimDDFFieldDefn *, const char *pszData, int nSize)
const char * ExtractStringData(const char *pachData, int nMaxBytes, int *pnConsumedBytes)
Extract a zero terminated string containing the data for this subfield.
void RemoveCloneRecord(ossimDDFRecord *)
Information from the DDR defining one field.
Definition: ossimIso8211.h:179
int FormatFloatValue(char *pachData, int nBytesAvailable, int *pnBytesUsed, double dfNewValue)
Format float subfield value.
int GetDataSize()
Return the number of bytes in the data block returned by GetData().
Definition: ossimIso8211.h:512
double ExtractFloatData(const char *pachData, int nMaxBytes, int *pnConsumedBytes)
Extract a subfield value as a float.
const char * GetName()
Fetch a pointer to the field name (tag).
Definition: ossimIso8211.h:203
char * GetDefaultValue(int *pnSize)
Return default data for field instance.
int FormatStringValue(char *pachData, int nBytesAvailable, int *pnBytesUsed, const char *pszValue, int nValueLength=-1)
Format string subfield value.
int GetDataSize()
Fetch size of records raw data (GetData()) in bytes.
Definition: ossimIso8211.h:420
int UpdateFieldRaw(ossimDDFField *poField, int iIndexWithinField, int nStartOffset, int nOldSize, const char *pachRawData, int nRawDataSize)
ossimDDFField * FindField(const char *, int=0)
Find the named field within this record.
int SetStringSubfield(const char *pszField, int iFieldIndex, const char *pszSubfield, int iSubfieldIndex, const char *pszValue, int nValueLength=-1)
Set a string subfield in record.
ossimDDFRecord * Clone()
Make a copy of a record.
int CreateDefaultFieldInstance(ossimDDFField *poField, int iIndexWithinField)
Initialize default instance.
int SetFloatSubfield(const char *pszField, int iFieldIndex, const char *pszSubfield, int iSubfieldIndex, double dfNewValue)
Set a float subfield in record.
const char * GetSubfieldData(ossimDDFSubfieldDefn *, int *=NULL, int=0)
Fetch raw data pointer for a particular subfield of this field.
ossimDDFFieldDefn * FindFieldDefn(const char *)
Fetch the definition of the named field.
ossimDDFField * GetField(int)
Fetch field object based on index.
int FormatIntValue(char *pachData, int nBytesAvailable, int *pnBytesUsed, int nNewValue)
Format int subfield value.
double GetFloatSubfield(const char *, int, const char *, int, int *=NULL)
Fetch value of a subfield as a float (double).
This object represents one field in a DDFRecord.
Definition: ossimIso8211.h:492
int DeleteField(ossimDDFField *poField)
Delete a field instance from a record.
ossimDDFRecord(ossimDDFModule *)
ossimDDFField * paoFields
Definition: ossimIso8211.h:472
int GetRepeatCount()
How many times do the subfields of this record repeat? This will always be one for non-repeating fie...
int Write()
Write record out to module.
int SetFieldRaw(ossimDDFField *poField, int iIndexWithinField, const char *pachRawData, int nRawDataSize)
Set the raw contents of a field instance.
ossimDDFSubfieldDefn * FindSubfieldDefn(const char *)
Find a subfield definition by it&#39;s mnemonic tag.
ossimDDFField * AddField(ossimDDFFieldDefn *)
Add a new field to record.
const char * GetStringSubfield(const char *, int, const char *, int, int *=NULL)
Fetch value of a subfield as a string.
int ResizeField(ossimDDFField *poField, int nNewDataSize)
Alter field data size within record.
const char * GetData()
Return the pointer to the entire data block for this record.
Definition: ossimIso8211.h:509
ossimDDFModule * poModule
Definition: ossimIso8211.h:458
const char * GetInstanceData(int nInstance, int *pnSize)
Get field instance data and size.
int SetIntSubfield(const char *pszField, int iFieldIndex, const char *pszSubfield, int iSubfieldIndex, int nValue)
Set an integer subfield in record.
void Dump(FILE *fp)
Write out field contents to debugging file.
int GetIntSubfield(const char *, int, const char *, int, int *=NULL)
Fetch value of a subfield as an integer.
ossimDDFFieldDefn * GetFieldDefn()
Fetch the corresponding DDFFieldDefn.
Definition: ossimIso8211.h:517
int ExtractIntData(const char *pachData, int nMaxBytes, int *pnConsumedBytes)
Extract a subfield value as an integer.
The primary class for reading ISO 8211 files.
Definition: ossimIso8211.h:88
int GetDataLength(const char *, int, int *)
Scan for the end of variable length data.
long ossimDDFScanInt(const char *pszString, int nMaxChars)
ossimDDFRecord * CloneOn(ossimDDFModule *)
Recreate a record referencing another module.
Contains instance data from one data record (DR).
Definition: ossimIso8211.h:385
OSSIMDLLEXPORT void * ossimCPLRealloc(void *pData, size_t nNewSize)
void AddCloneRecord(ossimDDFRecord *)
int IsRepeating()
Fetch repeating flag.
Definition: ossimIso8211.h:230
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
Information from the DDR record describing one subfield of a DDFFieldDefn.
Definition: ossimIso8211.h:278
const char * GetData()
Fetch the raw data for this record.
Definition: ossimIso8211.h:427
#define OSSIM_DDF_FIELD_TERMINATOR
Definition: ossimIso8211.h:62
FILE * GetFP()
Definition: ossimIso8211.h:127