1/*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef DATA_READER_H
6#define DATA_READER_H
7
8
9#include <string.h>
10
11#include "Types.h"
12
13
14class DataReader {
15public:
16	DataReader()
17		:
18		fData(NULL),
19		fSize(0),
20		fInitialSize(0),
21		fAddressSize(4),
22		fIsBigEndian(false),
23		fOverflow(false)
24	{
25	}
26
27	DataReader(const void* data, off_t size, uint8 addressSize, bool isBigEndian)
28	{
29		SetTo(data, size, addressSize, isBigEndian);
30	}
31
32	void SetTo(const void* data, off_t size, uint8 addressSize, bool isBigEndian)
33	{
34		fData = (const uint8*)data;
35		fInitialSize = fSize = size;
36		fAddressSize = addressSize;
37		fIsBigEndian = isBigEndian;
38		fOverflow = false;
39	}
40
41	DataReader RestrictedReader()
42	{
43		return *this;
44	}
45
46	DataReader RestrictedReader(off_t maxLength)
47	{
48		return DataReader(fData, maxLength, fAddressSize, fIsBigEndian);
49	}
50
51	DataReader RestrictedReader(off_t relativeOffset, off_t maxLength)
52	{
53		return DataReader(fData + relativeOffset, maxLength, fAddressSize, fIsBigEndian);
54	}
55
56	bool HasData() const
57	{
58		return fSize > 0;
59	}
60
61	uint32 AddressSize() const
62	{
63		return fAddressSize;
64	}
65
66	bool IsBigEndian() const
67	{
68		return fIsBigEndian;
69	}
70
71	void SetAddressSize(uint8 addressSize)
72	{
73		fAddressSize = addressSize;
74	}
75
76	bool HasOverflow() const
77	{
78		return fOverflow;
79	}
80
81	const void* Data() const
82	{
83		return fData;
84	}
85
86	off_t BytesRemaining() const
87	{
88		return fSize;
89	}
90
91	off_t Offset() const
92	{
93		return fInitialSize - fSize;
94	}
95
96	void SeekAbsolute(off_t offset)
97	{
98		if (offset < 0)
99			offset = 0;
100		else if (offset > fInitialSize)
101			offset = fInitialSize;
102
103		fData += offset - Offset();
104		fSize = fInitialSize - offset;
105	}
106
107	//TODO: take care of host vs target endianness
108	template<typename Type>
109	Type Read(const Type& defaultValue)
110	{
111		if (fSize < (off_t)sizeof(Type)) {
112			fOverflow = true;
113			fSize = 0;
114			return defaultValue;
115		}
116
117		Type data;
118		memcpy(&data, fData, sizeof(Type));
119
120		fData += sizeof(Type);
121		fSize -= sizeof(Type);
122
123		return data;
124	}
125
126	target_addr_t ReadAddress(target_addr_t defaultValue)
127	{
128		return fAddressSize == 4
129			? (target_addr_t)Read<uint32>(defaultValue)
130			: (target_addr_t)Read<uint64>(defaultValue);
131	}
132
133	uint64 ReadUnsignedLEB128(uint64 defaultValue)
134	{
135		uint64 result = 0;
136		int shift = 0;
137		while (true) {
138			uint8 byte = Read<uint8>(0);
139			result |= uint64(byte & 0x7f) << shift;
140			if ((byte & 0x80) == 0)
141				break;
142			shift += 7;
143		}
144
145		return fOverflow ? defaultValue : result;
146	}
147
148	int64 ReadSignedLEB128(int64 defaultValue)
149	{
150		int64 result = 0;
151		int shift = 0;
152		while (true) {
153			uint8 byte = Read<uint8>(0);
154			result |= uint64(byte & 0x7f) << shift;
155			shift += 7;
156
157			if ((byte & 0x80) == 0) {
158				// sign extend
159				if ((byte & 0x40) != 0 && shift < 64)
160					result |= -((uint64)1 << shift);
161				break;
162			}
163		}
164
165		return fOverflow ? defaultValue : result;
166	}
167
168	uint64 ReadUInt(size_t numBytes, uint64 defaultValue)
169	{
170		uint64 result = 0;
171		if (fIsBigEndian) {
172			for (size_t i = 0; i < numBytes; i++) {
173				uint8 byte = Read<uint8>(0);
174				result <<= 8;
175				result |= (uint64)byte;
176			}
177		} else {
178			int shift = 0;
179			for (size_t i = 0; i < numBytes; i++) {
180				uint8 byte = Read<uint8>(0);
181				result |= (uint64)byte << shift;
182				shift += 8;
183			}
184		}
185
186		return fOverflow ? defaultValue : result;
187	}
188
189	uint32 ReadU24(uint32 defaultValue)
190	{
191		return ReadUInt(3, defaultValue);
192	}
193
194	const char* ReadString()
195	{
196		const char* string = (const char*)fData;
197		while (fSize > 0) {
198			fData++;
199			fSize--;
200
201			if (fData[-1] == 0)
202				return string;
203		}
204
205		fOverflow = true;
206		return NULL;
207	}
208
209	uint64 ReadInitialLength(bool& _dwarf64)
210	{
211		uint64 length = Read<uint32>(0);
212		_dwarf64 = (length == 0xffffffff);
213		if (_dwarf64)
214			length = Read<uint64>(0);
215		return length;
216	}
217
218	bool Skip(off_t bytes)
219	{
220		if (bytes < 0)
221			return false;
222
223		if (bytes > fSize) {
224			fSize = 0;
225			fOverflow = true;
226			return false;
227		}
228
229		fData += bytes;
230		fSize -= bytes;
231
232		return true;
233	}
234
235private:
236	const uint8*	fData;
237	off_t			fSize;
238	off_t			fInitialSize;
239	uint8			fAddressSize;
240	bool			fIsBigEndian;
241	bool			fOverflow;
242};
243
244
245#endif	// DATA_READER_H
246