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		fOverflow(false)
23	{
24	}
25
26	DataReader(const void* data, off_t size, uint8 addressSize)
27	{
28		SetTo(data, size, addressSize);
29	}
30
31	void SetTo(const void* data, off_t size, uint8 addressSize)
32	{
33		fData = (const uint8*)data;
34		fInitialSize = fSize = size;
35		fAddressSize = addressSize;
36		fOverflow = false;
37	}
38
39	DataReader RestrictedReader()
40	{
41		return *this;
42	}
43
44	DataReader RestrictedReader(off_t maxLength)
45	{
46		return DataReader(fData, maxLength, fAddressSize);
47	}
48
49	DataReader RestrictedReader(off_t relativeOffset, off_t maxLength)
50	{
51		return DataReader(fData + relativeOffset, maxLength, fAddressSize);
52	}
53
54	bool HasData() const
55	{
56		return fSize > 0;
57	}
58
59	uint32 AddressSize() const
60	{
61		return fAddressSize;
62	}
63
64	void SetAddressSize(uint8 addressSize)
65	{
66		fAddressSize = addressSize;
67	}
68
69	bool HasOverflow() const
70	{
71		return fOverflow;
72	}
73
74	const void* Data() const
75	{
76		return fData;
77	}
78
79	off_t BytesRemaining() const
80	{
81		return fSize;
82	}
83
84	off_t Offset() const
85	{
86		return fInitialSize - fSize;
87	}
88
89	void SeekAbsolute(off_t offset)
90	{
91		if (offset < 0)
92			offset = 0;
93		else if (offset > fInitialSize)
94			offset = fInitialSize;
95
96		fData += offset - Offset();
97		fSize = fInitialSize - offset;
98	}
99
100	template<typename Type>
101	Type Read(const Type& defaultValue)
102	{
103		if (fSize < (off_t)sizeof(Type)) {
104			fOverflow = true;
105			fSize = 0;
106			return defaultValue;
107		}
108
109		Type data;
110		memcpy(&data, fData, sizeof(Type));
111
112		fData += sizeof(Type);
113		fSize -= sizeof(Type);
114
115		return data;
116	}
117
118	target_addr_t ReadAddress(target_addr_t defaultValue)
119	{
120		return fAddressSize == 4
121			? (target_addr_t)Read<uint32>(defaultValue)
122			: (target_addr_t)Read<uint64>(defaultValue);
123	}
124
125	uint64 ReadUnsignedLEB128(uint64 defaultValue)
126	{
127		uint64 result = 0;
128		int shift = 0;
129		while (true) {
130			uint8 byte = Read<uint8>(0);
131			result |= uint64(byte & 0x7f) << shift;
132			if ((byte & 0x80) == 0)
133				break;
134			shift += 7;
135		}
136
137		return fOverflow ? defaultValue : result;
138	}
139
140	int64 ReadSignedLEB128(int64 defaultValue)
141	{
142		int64 result = 0;
143		int shift = 0;
144		while (true) {
145			uint8 byte = Read<uint8>(0);
146			result |= uint64(byte & 0x7f) << shift;
147			shift += 7;
148
149			if ((byte & 0x80) == 0) {
150				// sign extend
151				if ((byte & 0x40) != 0 && shift < 64)
152					result |= -((uint64)1 << shift);
153				break;
154			}
155		}
156
157		return fOverflow ? defaultValue : result;
158	}
159
160	const char* ReadString()
161	{
162		const char* string = (const char*)fData;
163		while (fSize > 0) {
164			fData++;
165			fSize--;
166
167			if (fData[-1] == 0)
168				return string;
169		}
170
171		fOverflow = true;
172		return NULL;
173	}
174
175	uint64 ReadInitialLength(bool& _dwarf64)
176	{
177		uint64 length = Read<uint32>(0);
178		_dwarf64 = (length == 0xffffffff);
179		if (_dwarf64)
180			length = Read<uint64>(0);
181		return length;
182	}
183
184	bool Skip(off_t bytes)
185	{
186		if (bytes < 0)
187			return false;
188
189		if (bytes > fSize) {
190			fSize = 0;
191			fOverflow = true;
192			return false;
193		}
194
195		fData += bytes;
196		fSize -= bytes;
197
198		return true;
199	}
200
201private:
202	const uint8*	fData;
203	off_t			fSize;
204	off_t			fInitialSize;
205	uint8			fAddressSize;
206	bool			fOverflow;
207};
208
209
210#endif	// DATA_READER_H
211