1 /*============================================================================
2   MetaIO
3   Copyright 2000-2010 Insight Software Consortium
4 
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7 
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 /**
13  *    MetaUtils (.h and .cpp)
14  *
15  * Description:
16  *    This file provides generic ascii file parsing capabilities.
17  *    It assumes that the files consist of a set of fields
18  *    Each field is list of variable = value pairs
19  *
20  * Features:
21  *    There can be dependencies between fields, required fields,
22  *       and optional fields.
23  *    Undefined fields are skipped.
24  *    Values must conform to expected types.   There can be default
25  *       values for fields.
26  *
27  * Author:
28  *    Stephen R. Aylward
29  *
30  * Date:
31  *    February 22, 2002
32  *
33  **/
34 #include "metaTypes.h"
35 
36 #ifndef ITKMetaIO_METAUTILS_H
37 #define ITKMetaIO_METAUTILS_H
38 
39 #ifdef _MSC_VER
40 #pragma warning( disable:4251 )
41 #pragma warning( disable:4511 )
42 #pragma warning( disable:4512 )
43 #pragma warning( disable:4284 )
44 #pragma warning( disable:4702 )
45 #pragma warning( disable:4786 )
46 #pragma warning( disable:4996 )
47 #endif
48 
49 #include <vector>
50 #include <string>
51 #include <sstream>
52 #include <iostream>
53 //#include <iomanip>
54 #include <typeinfo>
55 #include <string.h>
56 
57 #if (METAIO_USE_NAMESPACE)
58 namespace METAIO_NAMESPACE {
59 #endif
60 
61 extern int META_DEBUG;
62 
63 // Types used for storing the compression table
64 typedef struct MET_CompressionOffset
65 {
66   std::streamoff uncompressedOffset;
67   std::streamoff compressedOffset;
68 } MET_CompressionOffsetType;
69 
70 typedef std::vector<MET_CompressionOffsetType> MET_CompressionOffsetListType;
71 
72 typedef struct MET_CompressionTable
73 {
74   MET_CompressionOffsetListType offsetList;
75   z_stream* compressedStream;
76   char* buffer;
77   std::streamoff bufferSize;
78 } MET_CompressionTableType;
79 
80 /////////////////////////////////////////////////////////
81 /////////////////////////////////////////////////////////
82 METAIO_EXPORT MET_FieldRecordType *
83 MET_GetFieldRecord(const char * _fieldName, std::vector<MET_FieldRecordType *> * _fields);
84 
85 METAIO_EXPORT
86 int MET_GetFieldRecordNumber(const char * _fieldName, std::vector<MET_FieldRecordType *> * _fields);
87 
88 METAIO_EXPORT
89 bool MET_SizeOfType(MET_ValueEnumType _type, int *_size);
90 
91 /////////////////////////////////////////////////////////
92 // Byte Order
93 /////////////////////////////////////////////////////////
94 METAIO_EXPORT
95 bool MET_SystemByteOrderMSB(void);
96 
97 inline
MET_ByteOrderSwapShort(unsigned short x)98 unsigned short MET_ByteOrderSwapShort(unsigned short x)
99     {
100     return (unsigned short)((unsigned short)(x<<8) | (unsigned short)(x>>8));
101     }
102 
103 inline
MET_ByteOrderSwapLong(unsigned int x)104 unsigned int MET_ByteOrderSwapLong(unsigned int x)
105     {
106     return (((x<<24) & 0xff000000) |
107             ((x<<8)  & 0x00ff0000) |
108             ((x>>8)  & 0x0000ff00) |
109             ((x>>24) & 0x000000ff));
110     }
111 
112 inline
MET_ByteOrderSwap2(void * x)113 void MET_ByteOrderSwap2(void* x)
114     {
115     char one_byte;
116     char *p = reinterpret_cast<char *>(x);
117 
118     one_byte    = p[0];
119     p[0] = p[1];
120     p[1] = one_byte;
121     }
122 
123 inline
MET_ByteOrderSwap4(void * x)124 void MET_ByteOrderSwap4(void* x)
125     {
126     char one_byte;
127     char *p = reinterpret_cast<char *>(x);
128 
129     one_byte    = p[0];
130     p[0] = p[3];
131     p[3] = one_byte;
132 
133     one_byte    = p[1];
134     p[1] = p[2];
135     p[2] = one_byte;
136     }
137 
138 inline
MET_ByteOrderSwap8(void * x)139 void MET_ByteOrderSwap8(void* x)
140     {
141     char one_byte;
142     char* p = reinterpret_cast<char*>(x);
143     one_byte    = p[0];
144     p[0] = p[7];
145     p[7] = one_byte;
146 
147     one_byte    = p[1];
148     p[1] = p[6];
149     p[6] = one_byte;
150 
151     one_byte    = p[2];
152     p[2] = p[5];
153     p[5] = one_byte;
154 
155     one_byte    = p[3];
156     p[3] = p[4];
157     p[4] = one_byte;
158     }
159 
160 /** Make sure that all the byte are read and written as LSB */
161 void MET_SwapByteIfSystemMSB(void* val, MET_ValueEnumType _type);
162 
163 
164 /////////////////////////////////////////////////////////
165 // STRINGS AND TYPES
166 /////////////////////////////////////////////////////////
167 METAIO_EXPORT
168 bool MET_StringToWordArray(const char *s, int *n, char ***val);
169 
170 template <class T>
171 void MET_StringToVector( const std::string & s,
172                          std::vector< T > & vec,
173                          const char separator=',' )
174 {
175   vec.clear();
176 
177   std::string::size_type prevPos = 0;
178   std::string::size_type pos = s.find( separator, prevPos );
179   T tVal;
180   while( pos != std::string::npos )
181     {
182     std::stringstream ss;
183     std::string tmpString = s.substr( prevPos, (pos-prevPos) );
184     ss << tmpString;
185     ss >> tVal;
186     vec.push_back( tVal );
187 
188     prevPos = pos+1;
189     pos = s.find( separator, prevPos );
190     }
191   std::stringstream ss;
192   std::string tmpString = s.substr( prevPos, ( s.size() - prevPos ) );
193   ss << tmpString;
194   ss >> tVal;
195   vec.push_back( tVal );
196 }
197 
198 METAIO_EXPORT
199 bool MET_StringToType(const char *_str, MET_ValueEnumType *_type);
200 
201 METAIO_EXPORT
202 bool MET_TypeToString(MET_ValueEnumType _type, char *_str);
203 
204 METAIO_EXPORT
205 bool MET_StringToInterpolationType(const char * _str, MET_InterpolationEnumType * _type);
206 
207 METAIO_EXPORT
208 bool MET_InterpolationTypeToString(MET_InterpolationEnumType _type, char * _str);
209 
210 inline
MET_GetPixelType(const std::type_info & ptype)211 MET_ValueEnumType MET_GetPixelType(const std::type_info & ptype)
212     {
213     if( ptype == typeid(MET_UCHAR_TYPE) )
214       {
215       return MET_UCHAR;
216       }
217     else if( ptype == typeid(MET_CHAR_TYPE) )
218       {
219       return MET_CHAR;
220       }
221     else if( ptype == typeid(MET_USHORT_TYPE))
222       {
223       return MET_USHORT;
224       }
225     else if( ptype == typeid(MET_SHORT_TYPE) )
226       {
227       return MET_SHORT;
228       }
229     else if( ptype == typeid(MET_UINT_TYPE) )
230       {
231       return MET_UINT;
232       }
233     else if( ptype == typeid(MET_INT_TYPE) )
234       {
235       return MET_INT;
236       }
237     else if( ptype == typeid(MET_ULONG_TYPE))
238       {
239       return MET_ULONG;
240       }
241     else if( ptype == typeid(MET_LONG_TYPE) )
242       {
243       return MET_LONG;
244       }
245     else if( ptype == typeid(MET_ULONG_LONG_TYPE) )
246       {
247       return MET_ULONG_LONG;
248       }
249     else if( ptype == typeid(MET_LONG_LONG_TYPE) )
250       {
251       return MET_LONG_LONG;
252       }
253     else if( ptype == typeid(MET_FLOAT_TYPE) )
254       {
255       return MET_FLOAT;
256       }
257     else if( ptype == typeid(MET_DOUBLE_TYPE) )
258       {
259       return MET_DOUBLE;
260       }
261     else
262       {
263       std::cerr << "MET_GetPixelType: Couldn't convert pixel type : "
264                 << ptype.name() << std::endl;
265       return MET_NONE;
266       }
267     }
268 
269 inline
MET_GetValueEnumType(const std::type_info & ptype)270 MET_ValueEnumType MET_GetValueEnumType(const std::type_info & ptype)
271     {
272     return MET_GetPixelType( ptype );
273     }
274 
275 inline
MET_StringStripEnd(MET_ASCII_CHAR_TYPE * str)276 void MET_StringStripEnd(MET_ASCII_CHAR_TYPE * str)
277     {
278     // note the post-decrement in the condition
279     for(size_t j = strlen(str); j-- > 0;)
280       {
281       if(isprint(str[j]) && !isspace(str[j]))
282         {
283         break;
284         }
285       str[j] = '\0';
286       }
287     }
288 
289 
290 /////////////////////////////////////////////////////////
291 // VALUES
292 /////////////////////////////////////////////////////////
293 METAIO_EXPORT
294 bool MET_ValueToDouble(MET_ValueEnumType _pType,
295                               const void *_data,
296                               std::streamoff _index,
297                               double *_value);
298 
299 METAIO_EXPORT
300 bool MET_DoubleToValue(double _value,
301                               MET_ValueEnumType _type,
302                               void *_data,
303                               std::streamoff _index);
304 
305 METAIO_EXPORT
306 bool MET_ValueToValue(MET_ValueEnumType _fromType,
307                              const void *_fromData,
308                              std::streamoff _index,
309                              MET_ValueEnumType _toType,
310                              void  *_toData,
311                              double _fromMin=0, double _fromMax=0,
312                              double _toMin=0, double _toMax=0);
313 
314 METAIO_EXPORT
315 unsigned char * MET_PerformCompression(const unsigned char * source,
316                                        std::streamoff sourceSize,
317                                        std::streamoff * compressedDataSize,
318                                        int compressionLevel);
319 
320 METAIO_EXPORT
321 bool MET_PerformUncompression(const unsigned char * sourceCompressed,
322                               std::streamoff sourceCompressedSize,
323                               unsigned char * uncompressedData,
324                               std::streamoff uncompressedDataSize);
325 
326 // Uncompress a stream given an uncompressedSeekPosition
327 METAIO_EXPORT
328 std::streamoff MET_UncompressStream(std::ifstream * stream,
329                           std::streamoff uncompressedSeekPosition,
330                           unsigned char * uncompressedData,
331                           std::streamoff uncompressedDataSize,
332                           std::streamoff compressedDataSize,
333                           MET_CompressionTableType * compressionTable);
334 
335 
336 /////////////////////////////////////////////////////////
337 // FILES NAMES
338 /////////////////////////////////////////////////////////
339 METAIO_EXPORT
340 bool MET_GetFilePath(const std::string& _fName, std::string& _fPath);
341 
342 METAIO_EXPORT
343 bool MET_GetFileSuffixPtr(const std::string& _fName, int *i);
344 
345 METAIO_EXPORT
346 bool MET_SetFileSuffix(std::string& _fName, const std::string& _suf);
347 
348 /////////////////////////////////////////////////////////
349 /////////////////////////////////////////////////////////
350 METAIO_EXPORT
351 bool MET_InitWriteField(MET_FieldRecordType * _mf,
352                                    const char *_name,
353                                    MET_ValueEnumType _type,
354                                    double _v=0);
355 
356 template <class T>
MET_InitWriteField(MET_FieldRecordType * _mf,const char * _name,MET_ValueEnumType _type,size_t _length,T * _v)357 bool MET_InitWriteField(MET_FieldRecordType * _mf,
358                                    const char *_name,
359                                    MET_ValueEnumType _type,
360                                    size_t _length,
361                                    T *_v)
362 {
363   strncpy(_mf->name, _name,254);
364   _mf->name[254] = '\0';
365   _mf->type = _type;
366   _mf->defined = true;
367   _mf->length = static_cast<int>(_length);
368   _mf->dependsOn = -1;
369   _mf->required = false;
370   _mf->terminateRead = false;
371   if(_type == MET_FLOAT_MATRIX)
372     {
373     size_t i;
374     for(i=0; i < MET_MAX_NUMBER_OF_FIELD_VALUES && i < _length*_length; i++)
375       {
376       _mf->value[i] = (double)(_v[i]);
377       }
378     }
379   else if(_type != MET_STRING)
380     {
381     size_t i;
382     for(i=0; i < MET_MAX_NUMBER_OF_FIELD_VALUES && i < _length; i++)
383       {
384       _mf->value[i] = (double)(_v[i]);
385       }
386     }
387   else
388     {
389     strncpy((char *)(_mf->value), (const char *)_v,
390             (sizeof(_mf->value)-1));
391     ((char *)(_mf->value))[(sizeof(_mf->value)-1)] = '\0';
392     }
393   return true;
394 }
395 
396 /////////////////////////////////////////////////////////
397 /////////////////////////////////////////////////////////
398 METAIO_EXPORT
399 bool MET_Write(std::ostream &fp,
400             std::vector<MET_FieldRecordType *> * fields,
401             char _sepChar='=');
402 
403 METAIO_EXPORT
404 bool MET_WriteFieldToFile(std::ostream &_fp, const char *_fieldName,
405                        MET_ValueEnumType _pType, size_t _n, const void *_v);
406 
407 METAIO_EXPORT
408 bool MET_WriteFieldToFile(std::ostream &_fp, const char *_fieldName,
409                        MET_ValueEnumType _pType, double _v);
410 
411 
412 /////////////////////////////////////////////////////////
413 /////////////////////////////////////////////////////////
414 METAIO_EXPORT
415 bool MET_InitReadField(MET_FieldRecordType * _mf,
416                                   const char *_name,
417                                   MET_ValueEnumType _type,
418                                   bool _required=true,
419                                   int _dependsOn=-1,
420                                   size_t _length=0);
421 
422 /////////////////////////////////////////////////////////
423 /////////////////////////////////////////////////////////
424 METAIO_EXPORT
425 bool MET_Read(std::istream &fp,
426            std::vector<MET_FieldRecordType *> * fields,
427            char _sepChar='=', bool oneLine=false,
428            bool display_warnings=true,
429            std::vector<MET_FieldRecordType *> * newFields=nullptr);
430 
431 
432 /////////////////////////////////////////////////////////
433 /////////////////////////////////////////////////////////
434 METAIO_EXPORT
435 std::string MET_ReadForm(std::istream & _fp);
436 
437 METAIO_EXPORT
438 std::string MET_ReadType(std::istream & _fp);
439 
440 METAIO_EXPORT
441 char * MET_ReadSubType(std::istream & _fp);
442 
443 #if (METAIO_USE_NAMESPACE)
444 };
445 #endif
446 
447 
448 #endif
449