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 <cstring>
56 
57 #  if (METAIO_USE_NAMESPACE)
58 namespace METAIO_NAMESPACE
59 {
60 #  endif
61 
62 extern bool META_DEBUG;
63 
64 #  define META_DEBUG_PRINT(content)                                                                                  \
65       if (META_DEBUG)                                                                                                \
66         {                                                                                                            \
67         std::cout << content << std::endl;                                                                           \
68         }                                                                                                            \
69     static_assert(true, "Compiled away assert that syntactically require semicolon at end of macro.")
70 
71 // Types used for storing the compression table
72 typedef struct MET_CompressionOffset
73 {
74   std::streamoff uncompressedOffset;
75   std::streamoff compressedOffset;
76 } MET_CompressionOffsetType;
77 
78 typedef std::vector<MET_CompressionOffsetType> MET_CompressionOffsetListType;
79 
80 typedef struct MET_CompressionTable
81 {
82   MET_CompressionOffsetListType offsetList;
83   z_stream *                    compressedStream;
84   char *                        buffer;
85   std::streamoff                bufferSize;
86 } MET_CompressionTableType;
87 
88 METAIO_EXPORT MET_FieldRecordType *
89               MET_GetFieldRecord(const char * _fieldName, std::vector<MET_FieldRecordType *> * _fields);
90 
91 METAIO_EXPORT
92 int
93 MET_GetFieldRecordNumber(const char * _fieldName, std::vector<MET_FieldRecordType *> * _fields);
94 
95 METAIO_EXPORT
96 bool
97 MET_SizeOfType(MET_ValueEnumType _vType, int * s);
98 
99 // Byte Order
100 METAIO_EXPORT
101 bool
102 MET_SystemByteOrderMSB();
103 
104 inline unsigned short
MET_ByteOrderSwapShort(unsigned short x)105 MET_ByteOrderSwapShort(unsigned short x)
106 {
107   return x << 8 | x >> 8;
108 }
109 
110 inline unsigned int
MET_ByteOrderSwapLong(unsigned int x)111 MET_ByteOrderSwapLong(unsigned int x)
112 {
113   return (((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff));
114 }
115 
116 inline void
MET_ByteOrderSwap2(void * x)117 MET_ByteOrderSwap2(void * x)
118 {
119   char   one_byte;
120   char * p = reinterpret_cast<char *>(x);
121 
122   one_byte = p[0];
123   p[0] = p[1];
124   p[1] = one_byte;
125 }
126 
127 inline void
MET_ByteOrderSwap4(void * x)128 MET_ByteOrderSwap4(void * x)
129 {
130   char   one_byte;
131   char * p = reinterpret_cast<char *>(x);
132 
133   one_byte = p[0];
134   p[0] = p[3];
135   p[3] = one_byte;
136 
137   one_byte = p[1];
138   p[1] = p[2];
139   p[2] = one_byte;
140 }
141 
142 inline void
MET_ByteOrderSwap8(void * x)143 MET_ByteOrderSwap8(void * x)
144 {
145   char   one_byte;
146   char * p = reinterpret_cast<char *>(x);
147   one_byte = p[0];
148   p[0] = p[7];
149   p[7] = one_byte;
150 
151   one_byte = p[1];
152   p[1] = p[6];
153   p[6] = one_byte;
154 
155   one_byte = p[2];
156   p[2] = p[5];
157   p[5] = one_byte;
158 
159   one_byte = p[3];
160   p[3] = p[4];
161   p[4] = one_byte;
162 }
163 
164 /** Make sure that all the byte are read and written as LSB */
165 void
166 MET_SwapByteIfSystemMSB(void * val, MET_ValueEnumType _type);
167 
168 
169 // STRINGS AND TYPES
170 METAIO_EXPORT
171 bool
172 MET_StringToWordArray(const char * s, int * n, char *** val);
173 
174 template <class T>
175 void
176 MET_StringToVector(const std::string & s, std::vector<T> & vec, const char separator = ',')
177 {
178   vec.clear();
179 
180   std::string::size_type prevPos = 0;
181   std::string::size_type pos = s.find(separator, prevPos);
182   T                      tVal;
183   while (pos != std::string::npos)
184   {
185     std::stringstream ss;
186     std::string       tmpString = s.substr(prevPos, (pos - prevPos));
187     ss << tmpString;
188     ss >> tVal;
189     vec.push_back(tVal);
190 
191     prevPos = pos + 1;
192     pos = s.find(separator, prevPos);
193   }
194   std::stringstream ss;
195   std::string       tmpString = s.substr(prevPos, (s.size() - prevPos));
196   ss << tmpString;
197   ss >> tVal;
198   vec.push_back(tVal);
199 }
200 
201 METAIO_EXPORT
202 bool
203 MET_StringToType(const char * _s, MET_ValueEnumType * _vType);
204 
205 METAIO_EXPORT
206 bool
207 MET_TypeToString(MET_ValueEnumType _vType, char * _s);
208 
209 METAIO_EXPORT
210 bool
211 MET_StringToInterpolationType(const char * _str, MET_InterpolationEnumType * _type);
212 
213 METAIO_EXPORT
214 bool
215 MET_InterpolationTypeToString(MET_InterpolationEnumType _type, char * _str);
216 
217 inline MET_ValueEnumType
MET_GetPixelType(const std::type_info & ptype)218 MET_GetPixelType(const std::type_info & ptype)
219 {
220   if (ptype == typeid(MET_UCHAR_TYPE))
221   {
222     return MET_UCHAR;
223   }
224   else if (ptype == typeid(MET_CHAR_TYPE))
225   {
226     return MET_CHAR;
227   }
228   else if (ptype == typeid(MET_USHORT_TYPE))
229   {
230     return MET_USHORT;
231   }
232   else if (ptype == typeid(MET_SHORT_TYPE))
233   {
234     return MET_SHORT;
235   }
236   else if (ptype == typeid(MET_UINT_TYPE))
237   {
238     return MET_UINT;
239   }
240   else if (ptype == typeid(MET_INT_TYPE))
241   {
242     return MET_INT;
243   }
244   else if (ptype == typeid(MET_ULONG_TYPE))
245   {
246     return MET_ULONG;
247   }
248   else if (ptype == typeid(MET_LONG_TYPE))
249   {
250     return MET_LONG;
251   }
252   else if (ptype == typeid(MET_ULONG_LONG_TYPE))
253   {
254     return MET_ULONG_LONG;
255   }
256   else if (ptype == typeid(MET_LONG_LONG_TYPE))
257   {
258     return MET_LONG_LONG;
259   }
260   else if (ptype == typeid(MET_FLOAT_TYPE))
261   {
262     return MET_FLOAT;
263   }
264   else if (ptype == typeid(MET_DOUBLE_TYPE))
265   {
266     return MET_DOUBLE;
267   }
268   else
269   {
270     std::cerr << "MET_GetPixelType: Couldn't convert pixel type : " << ptype.name() << std::endl;
271     return MET_NONE;
272   }
273 }
274 
275 inline MET_ValueEnumType
MET_GetValueEnumType(const std::type_info & ptype)276 MET_GetValueEnumType(const std::type_info & ptype)
277 {
278   return MET_GetPixelType(ptype);
279 }
280 
281 inline void
MET_StringStripEnd(MET_ASCII_CHAR_TYPE * str)282 MET_StringStripEnd(MET_ASCII_CHAR_TYPE * str)
283 {
284   // note the post-decrement in the condition
285   for (size_t j = strlen(str); j-- > 0;)
286   {
287     if (isprint(str[j]) && !isspace(str[j]))
288     {
289       break;
290     }
291     str[j] = '\0';
292   }
293 }
294 
295 
296 // VALUES
297 METAIO_EXPORT
298 bool
299 MET_ValueToDouble(MET_ValueEnumType _type, const void * _data, std::streamoff _index, double * _value);
300 
301 METAIO_EXPORT
302 bool
303 MET_DoubleToValue(double _value, MET_ValueEnumType _type, void * _data, std::streamoff _index);
304 
305 METAIO_EXPORT
306 bool
307 MET_ValueToValue(MET_ValueEnumType _fromType,
308                  const void *      _fromData,
309                  std::streamoff    _index,
310                  MET_ValueEnumType _toType,
311                  void *            _toData,
312                  double            _fromMin = 0,
313                  double            _fromMax = 0,
314                  double            _toMin = 0,
315                  double            _toMax = 0);
316 
317 METAIO_EXPORT
318 unsigned char *
319 MET_PerformCompression(const unsigned char * source,
320                        std::streamoff        sourceSize,
321                        std::streamoff *      compressedDataSize,
322                        int                   compressionLevel);
323 
324 METAIO_EXPORT
325 bool
326 MET_PerformUncompression(const unsigned char * sourceCompressed,
327                          std::streamoff        sourceCompressedSize,
328                          unsigned char *       uncompressedData,
329                          std::streamoff        uncompressedDataSize);
330 
331 // Uncompress a stream given an uncompressedSeekPosition
332 METAIO_EXPORT
333 std::streamoff
334 MET_UncompressStream(std::ifstream *            stream,
335                      std::streamoff             uncompressedSeekPosition,
336                      unsigned char *            uncompressedData,
337                      std::streamoff             uncompressedDataSize,
338                      std::streamoff             compressedDataSize,
339                      MET_CompressionTableType * compressionTable);
340 
341 
342 // FILES NAMES
343 METAIO_EXPORT
344 bool
345 MET_GetFilePath(const std::string & _fName, std::string & _fPath);
346 
347 METAIO_EXPORT
348 bool
349 MET_GetFileSuffixPtr(const std::string & _fName, int * i);
350 
351 METAIO_EXPORT
352 bool
353 MET_SetFileSuffix(std::string & _fName, const std::string & _suf);
354 
355 METAIO_EXPORT
356 bool
357 MET_InitWriteField(MET_FieldRecordType * _mf, const char * _name, MET_ValueEnumType _type, double _v = 0);
358 
359 template <class T>
360 bool
MET_InitWriteField(MET_FieldRecordType * _mf,const char * _name,MET_ValueEnumType _type,size_t _length,T * _v)361 MET_InitWriteField(MET_FieldRecordType * _mf, const char * _name, MET_ValueEnumType _type, size_t _length, 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, (sizeof(_mf->value) - 1));
390     ((char *)(_mf->value))[(sizeof(_mf->value) - 1)] = '\0';
391   }
392   return true;
393 }
394 
395 METAIO_EXPORT
396 bool
397 MET_Write(std::ostream & fp, std::vector<MET_FieldRecordType *> * fields, char _met_SeperatorChar = '=');
398 
399 METAIO_EXPORT
400 bool
401 MET_WriteFieldToFile(std::ostream & _fp, const char * _fieldName, MET_ValueEnumType _pType, size_t _n, const void * _v);
402 
403 METAIO_EXPORT
404 bool
405 MET_WriteFieldToFile(std::ostream & _fp, const char * _fieldName, MET_ValueEnumType _pType, double _v);
406 
407 
408 METAIO_EXPORT
409 bool
410 MET_InitReadField(MET_FieldRecordType * _mf,
411                   const char *          _name,
412                   MET_ValueEnumType     _type,
413                   bool                  _required = true,
414                   int                   _dependsOn = -1,
415                   size_t                _length = 0);
416 
417 METAIO_EXPORT
418 bool
419 MET_Read(std::istream &                       fp,
420          std::vector<MET_FieldRecordType *> * fields,
421          char                                 _met_SeperatorChar = '=',
422          bool                                 oneLine = false,
423          bool                                 display_warnings = true,
424          std::vector<MET_FieldRecordType *> * newFields = nullptr);
425 
426 
427 METAIO_EXPORT
428 std::string
429 MET_ReadForm(std::istream & _fp);
430 
431 METAIO_EXPORT
432 std::string
433 MET_ReadType(std::istream & _fp);
434 
435 METAIO_EXPORT
436 char *
437 MET_ReadSubType(std::istream & _fp);
438 
439 #  if (METAIO_USE_NAMESPACE)
440 };
441 #  endif
442 
443 
444 #endif
445