xref: /haiku/src/add-ons/translators/raw/ReadHelper.h (revision 93a78ecaa45114d68952d08c4778f073515102f2)
1 /*
2  * Copyright 2004-2007, 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
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
27 byte_swap(float &data)
28 {
29 	data = __swap_float(data);
30 }
31 
32 
33 template<>
34 inline void
35 byte_swap(int32 &data)
36 {
37 	data = __swap_int32(data);
38 }
39 
40 
41 template<>
42 inline void
43 byte_swap(uint32 &data)
44 {
45 	data = __swap_int32(data);
46 }
47 
48 
49 template<>
50 inline void
51 byte_swap(int16 &data)
52 {
53 	data = __swap_int16(data);
54 }
55 
56 
57 template<>
58 inline void
59 byte_swap(uint16 &data)
60 {
61 	data = __swap_int16(data);
62 }
63 
64 
65 class TReadHelper {
66 	public:
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
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
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
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
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
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
161 		NextShorts(uint16* data, size_t length)
162 		{
163 			fError = fStream.Read(data, length);
164 			if (fError < (ssize_t)length)
165 				fError = B_ERROR;
166 
167 			if (fError >= B_OK) {
168 				if (IsSwapping())
169 					swap_data(B_INT16_TYPE, data, length, B_SWAP_ALWAYS);
170 				return;
171 			}
172 
173 			throw fError;
174 		}
175 
176 		status_t Status() const
177 			{ return fError >= B_OK ? B_OK : fError; };
178 
179 		off_t Seek(off_t offset, int32 mode)
180 			{ return fStream.Seek(offset, mode); }
181 		off_t Position() const
182 			{ return fStream.Position(); }
183 
184 		void SetSwap(bool yesNo) { fSwap = yesNo; };
185 		bool IsSwapping() const { return fSwap; };
186 
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