OpenMW
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
nifstream.hpp
Go to the documentation of this file.
1 
3 #ifndef OPENMW_COMPONENTS_NIF_NIFSTREAM_HPP
4 #define OPENMW_COMPONENTS_NIF_NIFSTREAM_HPP
5 
6 #include <cassert>
7 #include <stdint.h>
8 #include <stdexcept>
9 #include <vector>
10 
12 
13 #include <osg/Vec3f>
14 #include <osg/Vec4f>
15 #include <osg/Quat>
16 
17 #include "niftypes.hpp"
18 
19 namespace Nif
20 {
21 
22 class NIFFile;
23 
24 /*
25  readLittleEndianBufferOfType: This template should only be used with non POD data types
26 */
27 template <uint32_t numInstances, typename T, typename IntegerT> inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest)
28 {
29 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
30  pIStream->read((char*)dest, numInstances * sizeof(T));
31 #else
32  uint8_t* destByteBuffer = (uint8_t*)dest;
33  pIStream->read((char*)dest, numInstances * sizeof(T));
34  /*
35  Due to the loop iterations being known at compile time,
36  this nested loop will most likely be unrolled
37  For example, for 2 instances of a 4 byte data type, you should get the below result
38  */
39  union {
40  IntegerT i;
41  T t;
42  } u;
43  for (uint32_t i = 0; i < numInstances; i++)
44  {
45  u = { 0 };
46  for (uint32_t byte = 0; byte < sizeof(T); byte++)
47  u.i |= (((IntegerT)destByteBuffer[i * sizeof(T) + byte]) << (byte * 8));
48  dest[i] = u.t;
49  }
50 #endif
51 }
52 
53 /*
54  readLittleEndianDynamicBufferOfType: This template should only be used with non POD data types
55 */
56 template <typename T, typename IntegerT> inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, uint32_t numInstances)
57 {
58 #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
59  pIStream->read((char*)dest, numInstances * sizeof(T));
60 #else
61  uint8_t* destByteBuffer = (uint8_t*)dest;
62  pIStream->read((char*)dest, numInstances * sizeof(T));
63  union {
64  IntegerT i;
65  T t;
66  } u;
67  for (uint32_t i = 0; i < numInstances; i++)
68  {
69  u.i = 0;
70  for (uint32_t byte = 0; byte < sizeof(T); byte++)
71  u.i |= ((IntegerT)destByteBuffer[i * sizeof(T) + byte]) << (byte * 8);
72  dest[i] = u.t;
73  }
74 #endif
75 }
76 template<typename type, typename IntegerT> type inline readLittleEndianType(Files::IStreamPtr &pIStream)
77 {
78  type val;
79  readLittleEndianBufferOfType<1,type,IntegerT>(pIStream, (type*)&val);
80  return val;
81 }
82 
83 class NIFStream
84 {
87 
88 public:
89 
90  NIFFile * const file;
91 
92  NIFStream (NIFFile * file, Files::IStreamPtr inp): inp (inp), file (file) {}
93 
94  void skip(size_t size) { inp->ignore(size); }
95 
96  char getChar()
97  {
98  return readLittleEndianType<char,char>(inp);
99  }
100 
101  short getShort()
102  {
103  return readLittleEndianType<short,short>(inp);
104  }
105 
106  unsigned short getUShort()
107  {
108  return readLittleEndianType<unsigned short,unsigned short>(inp);
109  }
110 
111  int getInt()
112  {
113  return readLittleEndianType<int,int>(inp);
114  }
115 
116  unsigned int getUInt()
117  {
118  return readLittleEndianType<unsigned int,unsigned int>(inp);
119  }
120 
121  float getFloat()
122  {
123  return readLittleEndianType<float,uint32_t>(inp);
124  }
125 
126  osg::Vec2f getVector2()
127  {
128  osg::Vec2f vec;
129  readLittleEndianBufferOfType<2,float,uint32_t>(inp, (float*)&vec._v[0]);
130  return vec;
131  }
132 
133  osg::Vec3f getVector3()
134  {
135  osg::Vec3f vec;
136  readLittleEndianBufferOfType<3, float,uint32_t>(inp, (float*)&vec._v[0]);
137  return vec;
138  }
139 
140  osg::Vec4f getVector4()
141  {
142  osg::Vec4f vec;
143  readLittleEndianBufferOfType<4, float,uint32_t>(inp, (float*)&vec._v[0]);
144  return vec;
145  }
146 
148  {
149  Matrix3 mat;
150  readLittleEndianBufferOfType<9, float,uint32_t>(inp, (float*)&mat.mValues);
151  return mat;
152  }
153 
154  osg::Quat getQuaternion();
155 
157 
159  std::string getString(size_t length)
160  {
161  std::vector<char> str(length + 1, 0);
162 
163  inp->read(&str[0], length);
164 
165  return &str[0];
166  }
168  std::string getString()
169  {
170  size_t size = readLittleEndianType<uint32_t,uint32_t>(inp);
171  return getString(size);
172  }
174  std::string getVersionString()
175  {
176  std::string result;
177  std::getline(*inp, result);
178  return result;
179  }
180 
181  void getUShorts(std::vector<unsigned short> &vec, size_t size)
182  {
183  vec.resize(size);
184  readLittleEndianDynamicBufferOfType<unsigned short,unsigned short>(inp, &vec.front(), size);
185  }
186 
187  void getFloats(std::vector<float> &vec, size_t size)
188  {
189  vec.resize(size);
190  readLittleEndianDynamicBufferOfType<float,uint32_t>(inp, &vec.front(), size);
191  }
192 
193  void getVector2s(std::vector<osg::Vec2f> &vec, size_t size)
194  {
195  vec.resize(size);
196  /* The packed storage of each Vec2f is 2 floats exactly */
197  readLittleEndianDynamicBufferOfType<float,uint32_t>(inp,(float*) &vec.front(), size*2);
198  }
199 
200  void getVector3s(std::vector<osg::Vec3f> &vec, size_t size)
201  {
202  vec.resize(size);
203  /* The packed storage of each Vec3f is 3 floats exactly */
204  readLittleEndianDynamicBufferOfType<float,uint32_t>(inp, (float*) &vec.front(), size*3);
205  }
206 
207  void getVector4s(std::vector<osg::Vec4f> &vec, size_t size)
208  {
209  vec.resize(size);
210  /* The packed storage of each Vec4f is 4 floats exactly */
211  readLittleEndianDynamicBufferOfType<float,uint32_t>(inp, (float*) &vec.front(), size*4);
212  }
213 
214  void getQuaternions(std::vector<osg::Quat> &quat, size_t size)
215  {
216  quat.resize(size);
217  for (size_t i = 0;i < quat.size();i++)
218  quat[i] = getQuaternion();
219  }
220 };
221 
222 }
223 
224 #endif
Definition: niffile.hpp:40
float mValues[3][3]
Definition: niftypes.hpp:37
std::string getString(size_t length)
Read in a string of the given length.
Definition: nifstream.hpp:159
int getInt()
Definition: nifstream.hpp:111
osg::Vec4f getVector4()
Definition: nifstream.hpp:140
osg::Quat getQuaternion()
Definition: nifstream.cpp:7
std::shared_ptr< std::istream > IStreamPtr
Definition: constrainedfilestream.hpp:21
void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T *dest, uint32_t numInstances)
Definition: nifstream.hpp:56
NIFFile *const file
Definition: nifstream.hpp:90
void skip(size_t size)
Definition: nifstream.hpp:94
Matrix3 getMatrix3()
Definition: nifstream.hpp:147
std::string getVersionString()
This is special since the version string doesn't start with a number, and ends with "\n"...
Definition: nifstream.hpp:174
unsigned short getUShort()
Definition: nifstream.hpp:106
void getUShorts(std::vector< unsigned short > &vec, size_t size)
Definition: nifstream.hpp:181
void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T *dest)
Definition: nifstream.hpp:27
Transformation getTrafo()
Definition: nifstream.cpp:19
void getQuaternions(std::vector< osg::Quat > &quat, size_t size)
Definition: nifstream.hpp:214
type readLittleEndianType(Files::IStreamPtr &pIStream)
Definition: nifstream.hpp:76
NIFStream(NIFFile *file, Files::IStreamPtr inp)
Definition: nifstream.hpp:92
Definition: niftypes.hpp:56
osg::Vec2f getVector2()
Definition: nifstream.hpp:126
void getVector4s(std::vector< osg::Vec4f > &vec, size_t size)
Definition: nifstream.hpp:207
osg::Vec3f getVector3()
Definition: nifstream.hpp:133
char getChar()
Definition: nifstream.hpp:96
float getFloat()
Definition: nifstream.hpp:121
void getVector2s(std::vector< osg::Vec2f > &vec, size_t size)
Definition: nifstream.hpp:193
Files::IStreamPtr inp
Input stream.
Definition: nifstream.hpp:86
Definition: niftypes.hpp:35
std::string getString()
Read in a string of the length specified in the file.
Definition: nifstream.hpp:168
void getFloats(std::vector< float > &vec, size_t size)
Definition: nifstream.hpp:187
Definition: nifstream.hpp:83
unsigned int getUInt()
Definition: nifstream.hpp:116
short getShort()
Definition: nifstream.hpp:101
void getVector3s(std::vector< osg::Vec3f > &vec, size_t size)
Definition: nifstream.hpp:200