ISO8211Lib
iso8211.h
00001 /******************************************************************************
00002  * $Id: iso8211.h 20996 2010-10-28 18:38:15Z rouault $
00003  *
00004  * Project:  ISO 8211 Access
00005  * Purpose:  Main declarations for ISO 8211.
00006  * Author:   Frank Warmerdam, warmerdam@pobox.com
00007  *
00008  ******************************************************************************
00009  * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com>
00010  *
00011  * Permission is hereby granted, free of charge, to any person obtaining a
00012  * copy of this software and associated documentation files (the "Software"),
00013  * to deal in the Software without restriction, including without limitation
00014  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00015  * and/or sell copies of the Software, and to permit persons to whom the
00016  * Software is furnished to do so, subject to the following conditions:
00017  *
00018  * The above copyright notice and this permission notice shall be included
00019  * in all copies or substantial portions of the Software.
00020  *
00021  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00022  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00024  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00026  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00027  * DEALINGS IN THE SOFTWARE.
00028  ****************************************************************************/
00029 
00030 #ifndef _ISO8211_H_INCLUDED
00031 #define _ISO8211_H_INCLUDED
00032 
00033 #include "cpl_port.h"
00034 #include "cpl_vsi.h"
00035 
00039 typedef enum {
00040     DDFInt,
00041     DDFFloat,
00042     DDFString,
00043     DDFBinaryString
00044 } DDFDataType;
00045   
00046 /************************************************************************/
00047 /*      These should really be private to the library ... they are      */
00048 /*      mostly conveniences.                                            */
00049 /************************************************************************/
00050 
00051 long CPL_ODLL DDFScanInt( const char *pszString, int nMaxChars );
00052 int  CPL_ODLL DDFScanVariable( const char * pszString, int nMaxChars, int nDelimChar );
00053 char CPL_ODLL *DDFFetchVariable( const char *pszString, int nMaxChars,
00054                         int nDelimChar1, int nDelimChar2,
00055                         int *pnConsumedChars );
00056 
00057 #define DDF_FIELD_TERMINATOR    30
00058 #define DDF_UNIT_TERMINATOR     31
00059 
00060 /************************************************************************/
00061 /*                           Predeclarations                            */
00062 /************************************************************************/
00063 
00064 class DDFFieldDefn;
00065 class DDFSubfieldDefn;
00066 class DDFRecord;
00067 class DDFField;
00068 
00069 /************************************************************************/
00070 /*                              DDFModule                               */
00071 /************************************************************************/
00072 
00080 class CPL_ODLL DDFModule
00081 {
00082   public:
00083                 DDFModule();
00084                 ~DDFModule();
00085                 
00086     int         Open( const char * pszFilename, int bFailQuietly = FALSE );
00087     int         Create( const char *pszFilename );
00088     void        Close();
00089 
00090     int         Initialize( char chInterchangeLevel = '3',
00091                             char chLeaderIden = 'L', 
00092                             char chCodeExtensionIndicator = 'E',
00093                             char chVersionNumber = '1',
00094                             char chAppIndicator = ' ',
00095                             const char *pszExtendedCharSet = " ! ",
00096                             int nSizeFieldLength = 3,
00097                             int nSizeFieldPos = 4,
00098                             int nSizeFieldTag = 4 );
00099 
00100     void        Dump( FILE * fp );
00101 
00102     DDFRecord   *ReadRecord( void );
00103     void        Rewind( long nOffset = -1 );
00104 
00105     DDFFieldDefn *FindFieldDefn( const char * );
00106 
00109     int         GetFieldCount() { return nFieldDefnCount; }
00110     DDFFieldDefn *GetField(int);
00111     void        AddField( DDFFieldDefn *poNewFDefn );
00112     
00113     // This is really just for internal use.
00114     int         GetFieldControlLength() { return _fieldControlLength; }
00115     void        AddCloneRecord( DDFRecord * );
00116     void        RemoveCloneRecord( DDFRecord * );
00117     
00118     // This is just for DDFRecord.
00119     VSILFILE   *GetFP() { return fpDDF; }
00120     
00121   private:
00122     VSILFILE    *fpDDF;
00123     int         bReadOnly;
00124     long        nFirstRecordOffset;
00125 
00126     char        _interchangeLevel;
00127     char        _inlineCodeExtensionIndicator;
00128     char        _versionNumber;
00129     char        _appIndicator;
00130     int         _fieldControlLength;
00131     char        _extendedCharSet[4];
00132 
00133     long _recLength;
00134     char _leaderIden;
00135     long _fieldAreaStart;
00136     long _sizeFieldLength;
00137     long _sizeFieldPos;
00138     long _sizeFieldTag;
00139 
00140     // One DirEntry per field.  
00141     int         nFieldDefnCount;
00142     DDFFieldDefn **papoFieldDefns;
00143 
00144     DDFRecord   *poRecord;
00145 
00146     int         nCloneCount;
00147     int         nMaxCloneCount;
00148     DDFRecord   **papoClones;
00149 };
00150 
00151 /************************************************************************/
00152 /*                             DDFFieldDefn                             */
00153 /************************************************************************/
00154 
00155   typedef enum { dsc_elementary, dsc_vector, dsc_array, dsc_concatenated } DDF_data_struct_code;
00156   typedef enum { dtc_char_string, 
00157                  dtc_implicit_point, 
00158                  dtc_explicit_point, 
00159                  dtc_explicit_point_scaled, 
00160                  dtc_char_bit_string, 
00161                  dtc_bit_string, 
00162                  dtc_mixed_data_type } DDF_data_type_code;
00163 
00171 class CPL_ODLL DDFFieldDefn
00172 {
00173   public:
00174                 DDFFieldDefn();
00175                 ~DDFFieldDefn();
00176 
00177     int         Create( const char *pszTag, const char *pszFieldName,
00178                         const char *pszDescription,
00179                         DDF_data_struct_code eDataStructCode,
00180                         DDF_data_type_code   eDataTypeCode,
00181                         const char *pszFormat = NULL );
00182     void        AddSubfield( DDFSubfieldDefn *poNewSFDefn,
00183                              int bDontAddToFormat = FALSE );
00184     void        AddSubfield( const char *pszName, const char *pszFormat );
00185     int         GenerateDDREntry( char **ppachData, int *pnLength ); 
00186                             
00187     int         Initialize( DDFModule * poModule, const char *pszTag,
00188                             int nSize, const char * pachRecord );
00189     
00190     void        Dump( FILE * fp );
00191 
00195     const char  *GetName() { return pszTag; }
00196 
00200     const char  *GetDescription() { return _fieldName; }
00201 
00203     int         GetSubfieldCount() { return nSubfieldCount; }
00204     
00205     DDFSubfieldDefn *GetSubfield( int i );
00206     DDFSubfieldDefn *FindSubfieldDefn( const char * );
00207 
00215     int         GetFixedWidth() { return nFixedWidth; }
00216 
00222     int         IsRepeating() { return bRepeatingSubfields; }
00223 
00224     static char       *ExpandFormat( const char * );
00225 
00227     void SetRepeatingFlag( int n ) { bRepeatingSubfields = n; }
00228 
00229     char        *GetDefaultValue( int *pnSize );
00230     
00231   private:
00232 
00233     static char       *ExtractSubstring( const char * );
00234 
00235     DDFModule * poModule;
00236     char *      pszTag;
00237 
00238     char *      _fieldName;
00239     char *      _arrayDescr;
00240     char *      _formatControls;
00241 
00242     int         bRepeatingSubfields;
00243     int         nFixedWidth;    // zero if variable. 
00244 
00245     int         BuildSubfields();
00246     int         ApplyFormats();
00247 
00248     DDF_data_struct_code _data_struct_code;
00249 
00250     DDF_data_type_code   _data_type_code;
00251 
00252     int         nSubfieldCount;
00253     DDFSubfieldDefn **papoSubfields;
00254 };
00255 
00256 /************************************************************************/
00257 /*                           DDFSubfieldDefn                            */
00258 /*                                                                      */
00259 /*      Information from the DDR record for one subfield of a           */
00260 /*      particular field.                                               */
00261 /************************************************************************/
00262 
00270 class CPL_ODLL DDFSubfieldDefn
00271 {
00272 public:
00273 
00274                 DDFSubfieldDefn();
00275                 ~DDFSubfieldDefn();
00276 
00277     void        SetName( const char * pszName );
00278 
00280     const char  *GetName() { return pszName; }
00281     
00283     const char  *GetFormat() { return pszFormatString; }
00284     int         SetFormat( const char * pszFormat );
00285 
00294     DDFDataType GetType() { return eType; }
00295 
00296     double      ExtractFloatData( const char *pachData, int nMaxBytes,
00297                                   int * pnConsumedBytes );
00298     int         ExtractIntData( const char *pachData, int nMaxBytes,
00299                                 int * pnConsumedBytes );
00300     const char  *ExtractStringData( const char *pachData, int nMaxBytes,
00301                                     int * pnConsumedBytes );
00302     int         GetDataLength( const char *, int, int * );
00303     void        DumpData( const char *pachData, int nMaxBytes, FILE * fp );
00304 
00305     int         FormatStringValue( char *pachData, int nBytesAvailable, 
00306                                    int *pnBytesUsed, const char *pszValue, 
00307                                    int nValueLength = -1 );
00308 
00309     int         FormatIntValue( char *pachData, int nBytesAvailable, 
00310                                 int *pnBytesUsed, int nNewValue );
00311 
00312     int         FormatFloatValue( char *pachData, int nBytesAvailable, 
00313                                   int *pnBytesUsed, double dfNewValue );
00314 
00316     int         GetWidth() { return nFormatWidth; } // zero for variable.
00317 
00318     int         GetDefaultValue( char *pachData, int nBytesAvailable, 
00319                                  int *pnBytesUsed );
00320     
00321     void        Dump( FILE * fp );
00322 
00327 typedef enum {
00328     NotBinary=0,
00329     UInt=1,
00330     SInt=2,
00331     FPReal=3,
00332     FloatReal=4,
00333     FloatComplex=5
00334 } DDFBinaryFormat;
00335 
00336     DDFBinaryFormat GetBinaryFormat(void) const { return eBinaryFormat; }
00337     
00338 
00339 private:
00340 
00341   char      *pszName;   // a.k.a. subfield mnemonic
00342   char      *pszFormatString; 
00343 
00344   DDFDataType           eType;
00345   DDFBinaryFormat       eBinaryFormat;
00346 
00347 /* -------------------------------------------------------------------- */
00348 /*      bIsVariable determines whether we using the                     */
00349 /*      chFormatDelimeter (TRUE), or the fixed width (FALSE).           */
00350 /* -------------------------------------------------------------------- */
00351   int        bIsVariable;
00352   
00353   char       chFormatDelimeter;
00354   int        nFormatWidth;
00355 
00356 /* -------------------------------------------------------------------- */
00357 /*      Fetched string cache.  This is where we hold the values         */
00358 /*      returned from ExtractStringData().                              */
00359 /* -------------------------------------------------------------------- */
00360   int        nMaxBufChars;
00361   char       *pachBuffer;
00362 };
00363 
00364 /************************************************************************/
00365 /*                              DDFRecord                               */
00366 /*                                                                      */
00367 /*      Class that contains one DR record from a file.  We read into    */
00368 /*      the same record object repeatedly to ensure that repeated       */
00369 /*      leaders can be easily preserved.                                */
00370 /************************************************************************/
00371 
00377 class CPL_ODLL DDFRecord
00378 {
00379   public:
00380                 DDFRecord( DDFModule * );
00381                 ~DDFRecord();
00382 
00383     DDFRecord  *Clone();
00384     DDFRecord  *CloneOn( DDFModule * );
00385     
00386     void        Dump( FILE * );
00387 
00389     int         GetFieldCount() { return nFieldCount; }
00390 
00391     DDFField    *FindField( const char *, int = 0 );
00392     DDFField    *GetField( int );
00393 
00394     int         GetIntSubfield( const char *, int, const char *, int,
00395                                 int * = NULL );
00396     double      GetFloatSubfield( const char *, int, const char *, int,
00397                                   int * = NULL );
00398     const char *GetStringSubfield( const char *, int, const char *, int,
00399                                    int * = NULL );
00400 
00401     int         SetIntSubfield( const char *pszField, int iFieldIndex, 
00402                                 const char *pszSubfield, int iSubfieldIndex,
00403                                 int nValue );
00404     int         SetStringSubfield( const char *pszField, int iFieldIndex, 
00405                                    const char *pszSubfield, int iSubfieldIndex,
00406                                    const char *pszValue, int nValueLength=-1 );
00407     int         SetFloatSubfield( const char *pszField, int iFieldIndex, 
00408                                   const char *pszSubfield, int iSubfieldIndex,
00409                                   double dfNewValue );
00410 
00412     int         GetDataSize() { return nDataSize; }
00413 
00419     const char  *GetData() { return pachData; }
00420 
00425     DDFModule * GetModule() { return poModule; }
00426 
00427     int ResizeField( DDFField *poField, int nNewDataSize );
00428     int DeleteField( DDFField *poField );
00429     DDFField* AddField( DDFFieldDefn * );
00430 
00431     int CreateDefaultFieldInstance( DDFField *poField, int iIndexWithinField );
00432 
00433     int SetFieldRaw( DDFField *poField, int iIndexWithinField, 
00434                      const char *pachRawData, int nRawDataSize );
00435     int UpdateFieldRaw( DDFField *poField, int iIndexWithinField, 
00436                         int nStartOffset, int nOldSize,
00437                         const char *pachRawData, int nRawDataSize );
00438 
00439     int         Write();
00440     
00441     // This is really just for the DDFModule class.
00442     int         Read();
00443     void        Clear();
00444     int         ResetDirectory();
00445     
00446   private:
00447 
00448     int         ReadHeader();
00449     
00450     DDFModule   *poModule;
00451 
00452     int         nReuseHeader;   
00453 
00454     int         nFieldOffset;   // field data area, not dir entries.
00455 
00456     int         _sizeFieldTag;
00457     int         _sizeFieldPos;
00458     int         _sizeFieldLength;
00459 
00460     int         nDataSize;      // Whole record except leader with header
00461     char        *pachData;
00462 
00463     int         nFieldCount;
00464     DDFField    *paoFields;
00465 
00466     int         bIsClone;
00467 };
00468 
00469 /************************************************************************/
00470 /*                               DDFField                               */
00471 /*                                                                      */
00472 /*      This object represents one field in a DDFRecord.                */
00473 /************************************************************************/
00474 
00484 class CPL_ODLL DDFField
00485 {
00486   public:
00487     void                Initialize( DDFFieldDefn *, const char *pszData,
00488                                     int nSize );
00489 
00490     void                Dump( FILE * fp );
00491 
00492     const char         *GetSubfieldData( DDFSubfieldDefn *,
00493                                          int * = NULL, int = 0 );
00494 
00495     const char         *GetInstanceData( int nInstance, int *pnSize );
00496 
00501     const char         *GetData() { return pachData; }
00502 
00504     int                 GetDataSize() { return nDataSize; }
00505 
00506     int                 GetRepeatCount();
00507 
00509     DDFFieldDefn        *GetFieldDefn() { return poDefn; }
00510     
00511   private:
00512     DDFFieldDefn        *poDefn;
00513 
00514     int                 nDataSize;
00515 
00516     const char          *pachData;
00517 };
00518 
00519 
00520 #endif /* ndef _ISO8211_H_INCLUDED */