annotate foosdk/sdk/foobar2000/helpers/readers.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 class NOVTABLE reader_membuffer_base : public file_readonly {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 reader_membuffer_base() : m_offset(0) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 t_size read(void * p_buffer, t_size p_bytes, abort_callback & p_abort) override;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 void write(const void * p_buffer, t_size p_bytes, abort_callback & p_abort) override { throw exception_io_denied(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 t_filesize get_size(abort_callback & p_abort) override { return get_buffer_size(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 t_filesize get_position(abort_callback & p_abort) override { return m_offset; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 void seek(t_filesize position, abort_callback & p_abort) override;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 void reopen(abort_callback & p_abort) override { seek(0, p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 bool can_seek() override { return true; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 bool is_in_memory() override { return true; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 virtual const void * get_buffer() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 virtual t_size get_buffer_size() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 //virtual t_filetimestamp get_timestamp(abort_callback & p_abort) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 bool get_content_type(pfc::string_base &) override { return false; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 inline void seek_internal(t_size p_offset) { if (p_offset > get_buffer_size()) throw exception_io_seek_out_of_range(); m_offset = p_offset; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 t_size m_offset;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 class reader_membuffer_simple : public reader_membuffer_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 reader_membuffer_simple(pfc::mem_block&& block, t_filetimestamp ts = filetimestamp_invalid, bool is_remote = false) : m_data(std::move(block)), m_ts(ts), m_isRemote(is_remote) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 reader_membuffer_simple(const void * ptr, t_size size, t_filetimestamp ts = filetimestamp_invalid, bool is_remote = false) : m_ts(ts), m_isRemote(is_remote) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 m_data.resize(size);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 if ( ptr != nullptr ) memcpy(m_data.get_ptr(), ptr, size);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 const void * get_buffer() { return m_data.get_ptr(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 void* _get_write_buffer() { return m_data.get_ptr(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 t_size get_buffer_size() { return m_data.get_size(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 t_filetimestamp get_timestamp(abort_callback & p_abort) { return m_ts; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 bool is_remote() { return m_isRemote; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 pfc::mem_block m_data;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 t_filetimestamp m_ts;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 bool m_isRemote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 class reader_membuffer_mirror : public reader_membuffer_base
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 t_filetimestamp get_timestamp(abort_callback & p_abort) { return m_timestamp; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 bool is_remote() { return m_remote; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 //! Returns false when the object could not be mirrored (too big) or did not need mirroring.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 static bool g_create(service_ptr_t<file> & p_out, const service_ptr_t<file> & p_src, abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 service_ptr_t<reader_membuffer_mirror> ptr = new service_impl_t<reader_membuffer_mirror>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 if (!ptr->init(p_src, p_abort)) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 p_out = ptr.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 bool get_content_type(pfc::string_base & out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 if (m_contentType.is_empty()) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 out = m_contentType; return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 const void * get_buffer() { return m_buffer.get_ptr(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 t_size get_buffer_size() { return m_buffer.get_size(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 bool init(const service_ptr_t<file> & p_src, abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 if (p_src->is_in_memory()) return false;//already buffered
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 if (!p_src->get_content_type(m_contentType)) m_contentType.reset();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 m_remote = p_src->is_remote();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 t_size size = pfc::downcast_guarded<t_size>(p_src->get_size(p_abort));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 m_buffer.set_size(size);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 p_src->reopen(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 p_src->read_object(m_buffer.get_ptr(), size, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 m_timestamp = p_src->get_timestamp(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 t_filetimestamp m_timestamp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 pfc::array_t<char> m_buffer;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 bool m_remote;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 pfc::string8 m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 class reader_limited : public file_readonly_t<file_v2> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 service_ptr_t<file> r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 t_filesize begin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 t_filesize end;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 static file::ptr g_create(file::ptr base, t_filesize offset, t_filesize size, abort_callback & abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 service_ptr_t<reader_limited> r = new service_impl_t<reader_limited>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 if (offset + size < offset) throw pfc::exception_overflow();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 r->init(base, offset, offset + size, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 return r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 reader_limited() { begin = 0;end = 0; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 reader_limited(const service_ptr_t<file> & p_r, t_filesize p_begin, t_filesize p_end, abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 r = p_r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 begin = p_begin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 end = p_end;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 reopen(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 void init(const service_ptr_t<file> & p_r, t_filesize p_begin, t_filesize p_end, abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 r = p_r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 begin = p_begin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 end = p_end;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 reopen(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 service_ptr get_metadata(abort_callback& a) override {return r->get_metadata_(a);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 t_filestats2 get_stats2(uint32_t f, abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 auto ret = r->get_stats2_(f, a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 ret.m_size = this->get_size(a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 t_filetimestamp get_timestamp(abort_callback & p_abort) override { return r->get_timestamp(p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 t_size read(void *p_buffer, t_size p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 t_filesize pos;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 pos = r->get_position(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 if (p_bytes > end - pos) p_bytes = (t_size)(end - pos);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 return r->read(p_buffer, p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 t_filesize get_size(abort_callback & p_abort) override { return end - begin; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 t_filesize get_position(abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 return r->get_position(p_abort) - begin;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 void seek(t_filesize position, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 if (position > end) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 r->seek(position + begin, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 bool can_seek() override { return r->can_seek(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 bool is_remote() override { return r->is_remote(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 bool get_content_type(pfc::string_base & out) override { return r->get_content_type(out); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 void reopen(abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 seekInternal(begin, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 void seekInternal(t_filesize position, abort_callback & abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 if (r->can_seek()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 r->seek(position, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 t_filesize positionWas = r->get_position(abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 if (positionWas == filesize_invalid || positionWas > position) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 r->reopen(abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 try { r->skip_object(position, abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 catch (exception_io_data const &) { throw exception_io_seek_out_of_range(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 t_filesize skipMe = position - positionWas;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 if (skipMe > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 try { r->skip_object(skipMe, abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 catch (exception_io_data const &) { throw exception_io_seek_out_of_range(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 // A more clever version of reader_membuffer_*.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 // Behaves more nicely with large files within 32bit address space.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 class reader_bigmem : public file_readonly_t<file_v2> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 reader_bigmem() : m_offset() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 t_size read(void * p_buffer, t_size p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 pfc::min_acc(p_bytes, remaining());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 m_mem.read(p_buffer, p_bytes, m_offset);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 m_offset += p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 return p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 void read_object(void * p_buffer, t_size p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 if (p_bytes > remaining()) throw exception_io_data_truncation();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 m_mem.read(p_buffer, p_bytes, m_offset);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 m_offset += p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 t_filesize skip(t_filesize p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 pfc::min_acc(p_bytes, (t_filesize)remaining());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 m_offset += (size_t)p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 return p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 void skip_object(t_filesize p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 if (p_bytes > remaining()) throw exception_io_data_truncation();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 m_offset += (size_t)p_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 t_filesize get_size(abort_callback & p_abort) override { p_abort.check(); return m_mem.size(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 t_filesize get_position(abort_callback & p_abort) override { p_abort.check(); return m_offset; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 void seek(t_filesize p_position, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 if (p_position > m_mem.size()) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 m_offset = (size_t)p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 bool can_seek() override { return true; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 bool is_in_memory() override { return true; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 void reopen(abort_callback & p_abort) override { seek(0, p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 // To be overridden by individual derived classes
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 bool get_content_type(pfc::string_base & p_out) override { return false; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 bool is_remote() override { return false; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 service_ptr get_metadata(abort_callback&) override { return nullptr; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 t_filestats2 get_stats2(uint32_t f, abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 t_filestats2 ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 ret.set_file();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 ret.m_size = get_size(a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 if ( f & stats2_timestamp ) ret.m_timestamp = this->get_timestamp(a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 void resize(size_t newSize) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 m_offset = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 m_mem.resize(newSize);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 size_t remaining() const { return m_mem.size() - m_offset; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 pfc::bigmem m_mem;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 size_t m_offset;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 class reader_bigmem_mirror : public reader_bigmem {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 reader_bigmem_mirror() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 void init(file::ptr source, abort_callback & abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 source->reopen(abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 m_metadata = source->get_metadata_(abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 t_filesize fs = source->get_size(abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 if (fs > 1024 * 1024 * 1024) { // reject > 1GB
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 throw std::bad_alloc();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 size_t s = (size_t)fs;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 resize(s);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 for (size_t walk = 0; walk < m_mem._sliceCount(); ++walk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 source->read(m_mem._slicePtr(walk), m_mem._sliceSize(walk), abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 if (!source->get_content_type(m_contentType)) m_contentType.reset();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 m_isRemote = source->is_remote();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 m_stats2 = source->get_stats2_(stats2_all, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 bool get_content_type(pfc::string_base & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 if (m_contentType.is_empty()) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 p_out = m_contentType; return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 t_filetimestamp get_timestamp(abort_callback & p_abort) override { return m_stats2.m_timestamp; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 bool is_remote() override { return m_isRemote; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 service_ptr get_metadata(abort_callback&) override { return m_metadata; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 t_filestats2 get_stats2(uint32_t f, abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 a.check(); (void)f; return m_stats2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 service_ptr m_metadata;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 t_filestats2 m_stats2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 pfc::string8 m_contentType;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 bool m_isRemote = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 class file_chain : public file_v2 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 service_ptr get_metadata(abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 return m_file->get_metadata_(a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 t_filestats2 get_stats2(uint32_t f, abort_callback& a) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 return m_file->get_stats2_(f, a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 t_size read(void * p_buffer, t_size p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 return m_file->read(p_buffer, p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 void read_object(void * p_buffer, t_size p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 m_file->read_object(p_buffer, p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 t_filesize skip(t_filesize p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 return m_file->skip(p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 void skip_object(t_filesize p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 m_file->skip_object(p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 void write(const void * p_buffer, t_size p_bytes, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 m_file->write(p_buffer, p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 t_filesize get_size(abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 return m_file->get_size(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 t_filesize get_position(abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 return m_file->get_position(p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 void resize(t_filesize p_size, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 m_file->resize(p_size, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 void seek(t_filesize p_position, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 m_file->seek(p_position, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 void seek_ex(t_sfilesize p_position, t_seek_mode p_mode, abort_callback & p_abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 m_file->seek_ex(p_position, p_mode, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 bool can_seek() override { return m_file->can_seek(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 bool get_content_type(pfc::string_base & p_out) override { return m_file->get_content_type(p_out); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 bool is_in_memory() override { return m_file->is_in_memory(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 void on_idle(abort_callback & p_abort) override { m_file->on_idle(p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 t_filetimestamp get_timestamp(abort_callback & p_abort) override { return m_file->get_timestamp(p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 void reopen(abort_callback & p_abort) override { m_file->reopen(p_abort); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 bool is_remote() override { return m_file->is_remote(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 file_chain(file::ptr chain) : m_file(chain) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 file::ptr m_file;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 class file_chain_readonly : public file_chain {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 void write(const void * p_buffer, t_size p_bytes, abort_callback & p_abort) override { throw exception_io_denied(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 void resize(t_filesize p_size, abort_callback & p_abort) override { throw exception_io_denied(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 file_chain_readonly(file::ptr chain) : file_chain(chain) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 static file::ptr create(file::ptr chain) { return new service_impl_t< file_chain_readonly >(chain); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 };