1 /*
2 * Copyright 2004-2008, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef READ_HELPER_H
6 #define READ_HELPER_H
7
8
9 #include "TIFF.h"
10
11 #include <BufferIO.h>
12 #include <ByteOrder.h>
13
14
15 template<class T>
16 inline void
byte_swap(T &)17 byte_swap(T &/*data*/)
18 {
19 // Specialize for data types which actually swap
20 // printf("DEAD MEAT!\n");
21 // exit(1);
22 }
23
24
25 template<>
26 inline void
byte_swap(float & data)27 byte_swap(float &data)
28 {
29 data = __swap_float(data);
30 }
31
32
33 template<>
34 inline void
byte_swap(int32 & data)35 byte_swap(int32 &data)
36 {
37 data = __swap_int32(data);
38 }
39
40
41 template<>
42 inline void
byte_swap(uint32 & data)43 byte_swap(uint32 &data)
44 {
45 data = __swap_int32(data);
46 }
47
48
49 template<>
50 inline void
byte_swap(int16 & data)51 byte_swap(int16 &data)
52 {
53 data = __swap_int16(data);
54 }
55
56
57 template<>
58 inline void
byte_swap(uint16 & data)59 byte_swap(uint16 &data)
60 {
61 data = __swap_int16(data);
62 }
63
64
65 class TReadHelper {
66 public:
TReadHelper(BPositionIO & stream)67 TReadHelper(BPositionIO& stream)
68 :
69 fStream(&stream, 65536, false),
70 fError(B_OK),
71 fSwap(false)
72 {
73 }
74
75 template<class T> inline void
operator()76 operator()(T &data)
77 {
78 fError = fStream.Read((void *)&data, sizeof(T));
79 if (fError >= B_OK) {
80 if (IsSwapping())
81 byte_swap(data);
82 return;
83 }
84
85 if (fError == 0)
86 fError = B_ERROR;
87 throw fError;
88 }
89
90 template<class T> inline void
operator()91 operator()(T data, size_t length)
92 {
93 fError = fStream.Read((void *)data, length);
94 if (fError < (ssize_t)length)
95 fError = B_ERROR;
96
97 if (fError >= B_OK)
98 return;
99
100 throw fError;
101 }
102
103 template<class T> inline T
Next()104 Next()
105 {
106 T value;
107 fError = fStream.Read((void *)&value, sizeof(T));
108 if (fError > B_OK) {
109 if (IsSwapping())
110 byte_swap(value);
111 return value;
112 }
113
114 if (fError == 0)
115 fError = B_ERROR;
116 throw fError;
117 }
118
119 inline uint32
Next(uint16 type)120 Next(uint16 type)
121 {
122 if (type == TIFF_UINT16_TYPE || type == TIFF_INT16_TYPE)
123 return Next<uint16>();
124
125 return Next<uint32>();
126 }
127
128 inline double
NextDouble(uint16 type)129 NextDouble(uint16 type)
130 {
131 switch (type) {
132 case TIFF_UINT16_TYPE:
133 return Next<uint16>();
134 case TIFF_UINT32_TYPE:
135 return Next<uint32>();
136 case TIFF_UFRACTION_TYPE:
137 {
138 double value = Next<uint32>();
139 return value / Next<uint32>();
140 }
141 case TIFF_INT16_TYPE:
142 return Next<int16>();
143 case TIFF_INT32_TYPE:
144 return Next<int32>();
145 case TIFF_FRACTION_TYPE:
146 {
147 double value = Next<int32>();
148 return value / Next<int32>();
149 }
150 case TIFF_FLOAT_TYPE:
151 return Next<float>();
152 case TIFF_DOUBLE_TYPE:
153 return Next<double>();
154
155 default:
156 return Next<uint8>();
157 }
158 }
159
160 inline void
NextShorts(uint16 * data,size_t length)161 NextShorts(uint16* data, size_t length)
162 {
163 fError = fStream.Read(data, length * 2);
164 if (fError < (ssize_t)length * 2)
165 fError = B_ERROR;
166
167 if (fError >= B_OK) {
168 if (IsSwapping())
169 swap_data(B_INT16_TYPE, data, length * 2, B_SWAP_ALWAYS);
170 return;
171 }
172
173 throw fError;
174 }
175
Status()176 status_t Status() const
177 { return fError >= B_OK ? B_OK : fError; };
178
Seek(off_t offset,int32 mode)179 off_t Seek(off_t offset, int32 mode)
180 { return fStream.Seek(offset, mode); }
Position()181 off_t Position() const
182 { return fStream.Position(); }
183
SetSwap(bool yesNo)184 void SetSwap(bool yesNo) { fSwap = yesNo; };
IsSwapping()185 bool IsSwapping() const { return fSwap; };
186
Stream()187 BPositionIO& Stream() { return fStream; }
188
189 private:
190 BBufferIO fStream;
191 status_t fError;
192 bool fSwap;
193 };
194
195 #endif // READ_HELPER_H
196