1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#include <foundation/platform.h>
#include <foundation/types.h>
#include <trace/detail/data.h>
//------------------------------------------------------------------------------
#ifdef _WIN32
DataSource::DataSource(const Path& path)
{
HANDLE handle = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (handle == INVALID_HANDLE_VALUE)
throw std::runtime_error("Failed to open file");
_handle = uintptr(handle);
}
DataSource::~DataSource()
{
auto handle = HANDLE(_handle);
CloseHandle(handle);
}
int32 DataSource::read(void* out, uint32 size)
{
auto handle = HANDLE(_handle);
DWORD bytes_read;
if (!ReadFile(handle, out, size, &bytes_read, nullptr))
throw std::runtime_error("Read error");
return bytes_read;
}
int64 DataSource::get_size() const
{
if (_size >= 0)
return _size;
auto handle = HANDLE(_handle);
LARGE_INTEGER out;
GetFileSizeEx(handle, &out);
return _size = out.QuadPart;
}
#else // POSIX
DataSource::DataSource(const Path& path)
{
int fd = ::open(path.string().c_str(), O_RDONLY);
if (fd < 0)
throw std::runtime_error("Failed to open file");
_handle = uintptr(fd);
}
DataSource::~DataSource()
{
::close(int(_handle));
}
int32 DataSource::read(void* out, uint32 size)
{
ssize_t bytes_read = ::read(int(_handle), out, size);
if (bytes_read < 0)
throw std::runtime_error("Read error");
return int32(bytes_read);
}
int64 DataSource::get_size() const
{
if (_size >= 0)
return _size;
struct stat st;
if (fstat(int(_handle), &st) < 0)
return _size = 0;
return _size = st.st_size;
}
#endif
//------------------------------------------------------------------------------
DataStream::DataStream(DataSource& data_source, Allocator& allocator)
: _data_source(data_source)
, _allocator(allocator)
{
}
//------------------------------------------------------------------------------
uint64 DataStream::tell() const
{
return _position;
}
//------------------------------------------------------------------------------
uint32 DataStream::get_available() const
{
return _stream.get_remaining();
}
//------------------------------------------------------------------------------
Buffer DataStream::read(uint32 size)
{
const uint8* ptr = _read(size);
return _buffer.create_sub_buffer(ptr, size);
}
//------------------------------------------------------------------------------
const uint8* DataStream::_read(uint32 size)
{
_position += size;
if (_stream.get_remaining() >= size)
return _stream.read(size);
MutableBuffer buffer = _allocator.create_buffer(BUFFER_SIZE);
uint8* cursor = buffer.get_pointer();
uint32 buffer_size = buffer.get_size();
if (uint32 remaining = _stream.get_remaining())
{
const void* src = _stream.read(remaining);
std::memcpy(cursor, src, remaining);
cursor += remaining;
buffer_size -= remaining;
}
uint32 read_size = 0;
while (true)
{
int32 i = _data_source.read(cursor + read_size, buffer_size - read_size);
if (i <= 0)
throw Eof();
if ((read_size += i) >= size)
break;
}
if (read_size < buffer_size)
{
buffer_size = BUFFER_SIZE - buffer_size + read_size;
_buffer = buffer.create_sub_buffer(0u, buffer_size);
}
else
_buffer = std::move(buffer);
_stream = _buffer.create_stream();
return _stream.read(size);
}
//------------------------------------------------------------------------------
template <> int8 DataStream::read< int8 >() { return *( int8 *)_read(sizeof( int8 )); }
template <> int16 DataStream::read< int16>() { return *( int16*)_read(sizeof( int16)); }
template <> int32 DataStream::read< int32>() { return *( int32*)_read(sizeof( int32)); }
template <> int64 DataStream::read< int64>() { return *( int64*)_read(sizeof( int64)); }
template <> uint8 DataStream::read<uint8 >() { return *(uint8 *)_read(sizeof(uint8 )); }
template <> uint16 DataStream::read<uint16>() { return *(uint16*)_read(sizeof(uint16)); }
template <> uint32 DataStream::read<uint32>() { return *(uint32*)_read(sizeof(uint32)); }
template <> uint64 DataStream::read<uint64>() { return *(uint64*)_read(sizeof(uint64)); }
|