1 : /******************************************************************************
2 : * $Id: iso8211.h 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: ISO 8211 Access
5 : * Purpose: Main declarations for ISO 8211.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com>
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 : #ifndef _ISO8211_H_INCLUDED
31 : #define _ISO8211_H_INCLUDED
32 :
33 : #include "cpl_port.h"
34 :
35 : /**
36 : General data type
37 : */
38 : typedef enum {
39 : DDFInt,
40 : DDFFloat,
41 : DDFString,
42 : DDFBinaryString
43 : } DDFDataType;
44 :
45 : /************************************************************************/
46 : /* These should really be private to the library ... they are */
47 : /* mostly conveniences. */
48 : /************************************************************************/
49 :
50 : long CPL_ODLL DDFScanInt( const char *pszString, int nMaxChars );
51 : int CPL_ODLL DDFScanVariable( const char * pszString, int nMaxChars, int nDelimChar );
52 : char CPL_ODLL *DDFFetchVariable( const char *pszString, int nMaxChars,
53 : int nDelimChar1, int nDelimChar2,
54 : int *pnConsumedChars );
55 :
56 : #define DDF_FIELD_TERMINATOR 30
57 : #define DDF_UNIT_TERMINATOR 31
58 :
59 : /************************************************************************/
60 : /* Predeclarations */
61 : /************************************************************************/
62 :
63 : class DDFFieldDefn;
64 : class DDFSubfieldDefn;
65 : class DDFRecord;
66 : class DDFField;
67 :
68 : /************************************************************************/
69 : /* DDFModule */
70 : /************************************************************************/
71 :
72 : /**
73 : The primary class for reading ISO 8211 files. This class contains all
74 : the information read from the DDR record, and is used to read records
75 : from the file.
76 :
77 : */
78 :
79 : class CPL_ODLL DDFModule
80 : {
81 : public:
82 : DDFModule();
83 : ~DDFModule();
84 :
85 : int Open( const char * pszFilename, int bFailQuietly = FALSE );
86 : int Create( const char *pszFilename );
87 : void Close();
88 :
89 : int Initialize( char chInterchangeLevel = '3',
90 : char chLeaderIden = 'L',
91 : char chCodeExtensionIndicator = 'E',
92 : char chVersionNumber = '1',
93 : char chAppIndicator = ' ',
94 : const char *pszExtendedCharSet = " ! ",
95 : int nSizeFieldLength = 3,
96 : int nSizeFieldPos = 4,
97 : int nSizeFieldTag = 4 );
98 :
99 : void Dump( FILE * fp );
100 :
101 : DDFRecord *ReadRecord( void );
102 : void Rewind( long nOffset = -1 );
103 :
104 : DDFFieldDefn *FindFieldDefn( const char * );
105 :
106 : /** Fetch the number of defined fields. */
107 :
108 : int GetFieldCount() { return nFieldDefnCount; }
109 : DDFFieldDefn *GetField(int);
110 : void AddField( DDFFieldDefn *poNewFDefn );
111 :
112 : // This is really just for internal use.
113 472 : int GetFieldControlLength() { return _fieldControlLength; }
114 : void AddCloneRecord( DDFRecord * );
115 : void RemoveCloneRecord( DDFRecord * );
116 :
117 : // This is just for DDFRecord.
118 2797 : FILE *GetFP() { return fpDDF; }
119 :
120 : private:
121 : FILE *fpDDF;
122 : int bReadOnly;
123 : long nFirstRecordOffset;
124 :
125 : char _interchangeLevel;
126 : char _inlineCodeExtensionIndicator;
127 : char _versionNumber;
128 : char _appIndicator;
129 : int _fieldControlLength;
130 : char _extendedCharSet[4];
131 :
132 : long _recLength;
133 : char _leaderIden;
134 : long _fieldAreaStart;
135 : long _sizeFieldLength;
136 : long _sizeFieldPos;
137 : long _sizeFieldTag;
138 :
139 : // One DirEntry per field.
140 : int nFieldDefnCount;
141 : DDFFieldDefn **papoFieldDefns;
142 :
143 : DDFRecord *poRecord;
144 :
145 : int nCloneCount;
146 : int nMaxCloneCount;
147 : DDFRecord **papoClones;
148 : };
149 :
150 : /************************************************************************/
151 : /* DDFFieldDefn */
152 : /************************************************************************/
153 :
154 : typedef enum { dsc_elementary, dsc_vector, dsc_array, dsc_concatenated } DDF_data_struct_code;
155 : typedef enum { dtc_char_string,
156 : dtc_implicit_point,
157 : dtc_explicit_point,
158 : dtc_explicit_point_scaled,
159 : dtc_char_bit_string,
160 : dtc_bit_string,
161 : dtc_mixed_data_type } DDF_data_type_code;
162 :
163 : /**
164 : * Information from the DDR defining one field. Note that just because
165 : * a field is defined for a DDFModule doesn't mean that it actually occurs
166 : * on any records in the module. DDFFieldDefns are normally just significant
167 : * as containers of the DDFSubfieldDefns.
168 : */
169 :
170 : class CPL_ODLL DDFFieldDefn
171 : {
172 : public:
173 : DDFFieldDefn();
174 : ~DDFFieldDefn();
175 :
176 : int Create( const char *pszTag, const char *pszFieldName,
177 : const char *pszDescription,
178 : DDF_data_struct_code eDataStructCode,
179 : DDF_data_type_code eDataTypeCode,
180 : const char *pszFormat = NULL );
181 : void AddSubfield( DDFSubfieldDefn *poNewSFDefn,
182 : int bDontAddToFormat = FALSE );
183 : void AddSubfield( const char *pszName, const char *pszFormat );
184 : int GenerateDDREntry( char **ppachData, int *pnLength );
185 :
186 : int Initialize( DDFModule * poModule, const char *pszTag,
187 : int nSize, const char * pachRecord );
188 :
189 : void Dump( FILE * fp );
190 :
191 : /** Fetch a pointer to the field name (tag).
192 : * @return this is an internal copy and shouldn't be freed.
193 : */
194 30148 : const char *GetName() { return pszTag; }
195 :
196 : /** Fetch a longer descriptio of this field.
197 : * @return this is an internal copy and shouldn't be freed.
198 : */
199 : const char *GetDescription() { return _fieldName; }
200 :
201 : /** Get the number of subfields. */
202 37444 : int GetSubfieldCount() { return nSubfieldCount; }
203 :
204 : DDFSubfieldDefn *GetSubfield( int i );
205 : DDFSubfieldDefn *FindSubfieldDefn( const char * );
206 :
207 : /**
208 : * Get the width of this field. This function isn't normally used
209 : * by applications.
210 : *
211 : * @return The width of the field in bytes, or zero if the field is not
212 : * apparently of a fixed width.
213 : */
214 446 : int GetFixedWidth() { return nFixedWidth; }
215 :
216 : /**
217 : * Fetch repeating flag.
218 : * @see DDFField::GetRepeatCount()
219 : * @return TRUE if the field is marked as repeating.
220 : */
221 77 : int IsRepeating() { return bRepeatingSubfields; }
222 :
223 : static char *ExpandFormat( const char * );
224 :
225 : /** this is just for an S-57 hack for swedish data */
226 0 : void SetRepeatingFlag( int n ) { bRepeatingSubfields = n; }
227 :
228 : char *GetDefaultValue( int *pnSize );
229 :
230 : private:
231 :
232 : static char *ExtractSubstring( const char * );
233 :
234 : DDFModule * poModule;
235 : char * pszTag;
236 :
237 : char * _fieldName;
238 : char * _arrayDescr;
239 : char * _formatControls;
240 :
241 : int bRepeatingSubfields;
242 : int nFixedWidth; // zero if variable.
243 :
244 : int BuildSubfields();
245 : int ApplyFormats();
246 :
247 : DDF_data_struct_code _data_struct_code;
248 :
249 : DDF_data_type_code _data_type_code;
250 :
251 : int nSubfieldCount;
252 : DDFSubfieldDefn **papoSubfields;
253 : };
254 :
255 : /************************************************************************/
256 : /* DDFSubfieldDefn */
257 : /* */
258 : /* Information from the DDR record for one subfield of a */
259 : /* particular field. */
260 : /************************************************************************/
261 :
262 : /**
263 : * Information from the DDR record describing one subfield of a DDFFieldDefn.
264 : * All subfields of a field will occur in each occurance of that field
265 : * (as a DDFField) in a DDFRecord. Subfield's actually contain formatted
266 : * data (as instances within a record).
267 : */
268 :
269 : class CPL_ODLL DDFSubfieldDefn
270 : {
271 : public:
272 :
273 : DDFSubfieldDefn();
274 : ~DDFSubfieldDefn();
275 :
276 : void SetName( const char * pszName );
277 :
278 : /** Get pointer to subfield name. */
279 9268 : const char *GetName() { return pszName; }
280 :
281 : /** Get pointer to subfield format string */
282 241 : const char *GetFormat() { return pszFormatString; }
283 : int SetFormat( const char * pszFormat );
284 :
285 : /**
286 : * Get the general type of the subfield. This can be used to
287 : * determine which of ExtractFloatData(), ExtractIntData() or
288 : * ExtractStringData() should be used.
289 : * @return The subfield type. One of DDFInt, DDFFloat, DDFString or
290 : * DDFBinaryString.
291 : */
292 :
293 2896 : DDFDataType GetType() { return eType; }
294 :
295 : double ExtractFloatData( const char *pachData, int nMaxBytes,
296 : int * pnConsumedBytes );
297 : int ExtractIntData( const char *pachData, int nMaxBytes,
298 : int * pnConsumedBytes );
299 : const char *ExtractStringData( const char *pachData, int nMaxBytes,
300 : int * pnConsumedBytes );
301 : int GetDataLength( const char *, int, int * );
302 : void DumpData( const char *pachData, int nMaxBytes, FILE * fp );
303 :
304 : int FormatStringValue( char *pachData, int nBytesAvailable,
305 : int *pnBytesUsed, const char *pszValue,
306 : int nValueLength = -1 );
307 :
308 : int FormatIntValue( char *pachData, int nBytesAvailable,
309 : int *pnBytesUsed, int nNewValue );
310 :
311 : int FormatFloatValue( char *pachData, int nBytesAvailable,
312 : int *pnBytesUsed, double dfNewValue );
313 :
314 : /** Get the subfield width (zero for variable). */
315 5052 : int GetWidth() { return nFormatWidth; } // zero for variable.
316 :
317 : int GetDefaultValue( char *pachData, int nBytesAvailable,
318 : int *pnBytesUsed );
319 :
320 : void Dump( FILE * fp );
321 :
322 : /**
323 : Binary format: this is the digit immediately following the B or b for
324 : binary formats.
325 : */
326 : typedef enum {
327 : NotBinary=0,
328 : UInt=1,
329 : SInt=2,
330 : FPReal=3,
331 : FloatReal=4,
332 : FloatComplex=5
333 : } DDFBinaryFormat;
334 :
335 0 : DDFBinaryFormat GetBinaryFormat(void) const { return eBinaryFormat; }
336 :
337 :
338 : private:
339 :
340 : char *pszName; // a.k.a. subfield mnemonic
341 : char *pszFormatString;
342 :
343 : DDFDataType eType;
344 : DDFBinaryFormat eBinaryFormat;
345 :
346 : /* -------------------------------------------------------------------- */
347 : /* bIsVariable determines whether we using the */
348 : /* chFormatDelimeter (TRUE), or the fixed width (FALSE). */
349 : /* -------------------------------------------------------------------- */
350 : int bIsVariable;
351 :
352 : char chFormatDelimeter;
353 : int nFormatWidth;
354 :
355 : /* -------------------------------------------------------------------- */
356 : /* Fetched string cache. This is where we hold the values */
357 : /* returned from ExtractStringData(). */
358 : /* -------------------------------------------------------------------- */
359 : int nMaxBufChars;
360 : char *pachBuffer;
361 : };
362 :
363 : /************************************************************************/
364 : /* DDFRecord */
365 : /* */
366 : /* Class that contains one DR record from a file. We read into */
367 : /* the same record object repeatedly to ensure that repeated */
368 : /* leaders can be easily preserved. */
369 : /************************************************************************/
370 :
371 : /**
372 : * Contains instance data from one data record (DR). The data is contained
373 : * as a list of DDFField instances partitioning the raw data into fields.
374 : */
375 :
376 : class CPL_ODLL DDFRecord
377 : {
378 : public:
379 : DDFRecord( DDFModule * );
380 : ~DDFRecord();
381 :
382 : DDFRecord *Clone();
383 : DDFRecord *CloneOn( DDFModule * );
384 :
385 : void Dump( FILE * );
386 :
387 : /** Get the number of DDFFields on this record. */
388 1855 : int GetFieldCount() { return nFieldCount; }
389 :
390 : DDFField *FindField( const char *, int = 0 );
391 : DDFField *GetField( int );
392 :
393 : int GetIntSubfield( const char *, int, const char *, int,
394 : int * = NULL );
395 : double GetFloatSubfield( const char *, int, const char *, int,
396 : int * = NULL );
397 : const char *GetStringSubfield( const char *, int, const char *, int,
398 : int * = NULL );
399 :
400 : int SetIntSubfield( const char *pszField, int iFieldIndex,
401 : const char *pszSubfield, int iSubfieldIndex,
402 : int nValue );
403 : int SetStringSubfield( const char *pszField, int iFieldIndex,
404 : const char *pszSubfield, int iSubfieldIndex,
405 : const char *pszValue, int nValueLength=-1 );
406 : int SetFloatSubfield( const char *pszField, int iFieldIndex,
407 : const char *pszSubfield, int iSubfieldIndex,
408 : double dfNewValue );
409 :
410 : /** Fetch size of records raw data (GetData()) in bytes. */
411 : int GetDataSize() { return nDataSize; }
412 :
413 : /**
414 : * Fetch the raw data for this record. The returned pointer is effectively
415 : * to the data for the first field of the record, and is of size
416 : * GetDataSize().
417 : */
418 0 : const char *GetData() { return pachData; }
419 :
420 : /**
421 : * Fetch the DDFModule with which this record is associated.
422 : */
423 :
424 : DDFModule * GetModule() { return poModule; }
425 :
426 : int ResizeField( DDFField *poField, int nNewDataSize );
427 : int DeleteField( DDFField *poField );
428 : DDFField* AddField( DDFFieldDefn * );
429 :
430 : int CreateDefaultFieldInstance( DDFField *poField, int iIndexWithinField );
431 :
432 : int SetFieldRaw( DDFField *poField, int iIndexWithinField,
433 : const char *pachRawData, int nRawDataSize );
434 : int UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
435 : int nStartOffset, int nOldSize,
436 : const char *pachRawData, int nRawDataSize );
437 :
438 : int Write();
439 :
440 : // This is really just for the DDFModule class.
441 : int Read();
442 : void Clear();
443 : int ResetDirectory();
444 :
445 : private:
446 :
447 : int ReadHeader();
448 :
449 : DDFModule *poModule;
450 :
451 : int nReuseHeader;
452 :
453 : int nFieldOffset; // field data area, not dir entries.
454 :
455 : int _sizeFieldTag;
456 : int _sizeFieldPos;
457 : int _sizeFieldLength;
458 :
459 : int nDataSize; // Whole record except leader with header
460 : char *pachData;
461 :
462 : int nFieldCount;
463 : DDFField *paoFields;
464 :
465 : int bIsClone;
466 : };
467 :
468 : /************************************************************************/
469 : /* DDFField */
470 : /* */
471 : /* This object represents one field in a DDFRecord. */
472 : /************************************************************************/
473 :
474 : /**
475 : * This object represents one field in a DDFRecord. This
476 : * models an instance of the fields data, rather than it's data definition
477 : * which is handled by the DDFFieldDefn class. Note that a DDFField
478 : * doesn't have DDFSubfield children as you would expect. To extract
479 : * subfield values use GetSubfieldData() to find the right data pointer and
480 : * then use ExtractIntData(), ExtractFloatData() or ExtractStringData().
481 : */
482 :
483 : class CPL_ODLL DDFField
484 : {
485 : public:
486 : void Initialize( DDFFieldDefn *, const char *pszData,
487 : int nSize );
488 :
489 : void Dump( FILE * fp );
490 :
491 : const char *GetSubfieldData( DDFSubfieldDefn *,
492 : int * = NULL, int = 0 );
493 :
494 : const char *GetInstanceData( int nInstance, int *pnSize );
495 :
496 : /**
497 : * Return the pointer to the entire data block for this record. This
498 : * is an internal copy, and shouldn't be freed by the application.
499 : */
500 3621 : const char *GetData() { return pachData; }
501 :
502 : /** Return the number of bytes in the data block returned by GetData(). */
503 2874 : int GetDataSize() { return nDataSize; }
504 :
505 : int GetRepeatCount();
506 :
507 : /** Fetch the corresponding DDFFieldDefn. */
508 13813 : DDFFieldDefn *GetFieldDefn() { return poDefn; }
509 :
510 : private:
511 : DDFFieldDefn *poDefn;
512 :
513 : int nDataSize;
514 :
515 : const char *pachData;
516 : };
517 :
518 :
519 : #endif /* ndef _ISO8211_H_INCLUDED */
|