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
15template<class T>
16inline void
17byte_swap(T &/*data*/)
18{
19	// Specialize for data types which actually swap
20//	printf("DEAD MEAT!\n");
21//	exit(1);
22}
23
24
25template<>
26inline void
27byte_swap(float &data)
28{
29	data = __swap_float(data);
30}
31
32
33template<>
34inline void
35byte_swap(int32 &data)
36{
37	data = __swap_int32(data);
38}
39
40
41template<>
42inline void
43byte_swap(uint32 &data)
44{
45	data = __swap_int32(data);
46}
47
48
49template<>
50inline void
51byte_swap(int16 &data)
52{
53	data = __swap_int16(data);
54}
55
56
57template<>
58inline void
59byte_swap(uint16 &data)
60{
61	data = __swap_int16(data);
62}
63
64
65class 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 * 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
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