77
88#include < array>
99
10+ AutoFile::AutoFile (std::FILE* file, std::vector<std::byte> data_xor)
11+ : m_file{file}, m_xor{std::move (data_xor)}
12+ {
13+ if (!IsNull ()) {
14+ auto pos{std::ftell (m_file)};
15+ if (pos >= 0 ) m_position = pos;
16+ }
17+ }
18+
1019std::size_t AutoFile::detail_fread (Span<std::byte> dst)
1120{
1221 if (!m_file) throw std::ios_base::failure (" AutoFile::read: file handle is nullptr" );
13- if (m_xor.empty ()) {
14- return std::fread (dst.data (), 1 , dst.size (), m_file);
15- } else {
16- const auto init_pos{std::ftell (m_file)};
17- if (init_pos < 0 ) throw std::ios_base::failure (" AutoFile::read: ftell failed" );
18- std::size_t ret{std::fread (dst.data (), 1 , dst.size (), m_file)};
19- util::Xor (dst.subspan (0 , ret), m_xor, init_pos);
20- return ret;
22+ size_t ret = std::fread (dst.data (), 1 , dst.size (), m_file);
23+ if (!m_xor.empty ()) {
24+ if (!m_position.has_value ()) throw std::ios_base::failure (" AutoFile::read: position unknown" );
25+ util::Xor (dst.subspan (0 , ret), m_xor, *m_position);
2126 }
27+ if (m_position.has_value ()) *m_position += ret;
28+ return ret;
2229}
2330
2431void AutoFile::seek (int64_t offset, int origin)
@@ -29,18 +36,23 @@ void AutoFile::seek(int64_t offset, int origin)
2936 if (std::fseek (m_file, offset, origin) != 0 ) {
3037 throw std::ios_base::failure (feof () ? " AutoFile::seek: end of file" : " AutoFile::seek: fseek failed" );
3138 }
39+ if (origin == SEEK_SET) {
40+ m_position = offset;
41+ } else if (origin == SEEK_CUR && m_position.has_value ()) {
42+ *m_position += offset;
43+ } else {
44+ int64_t r{std::ftell (m_file)};
45+ if (r < 0 ) {
46+ throw std::ios_base::failure (" AutoFile::seek: ftell failed" );
47+ }
48+ m_position = r;
49+ }
3250}
3351
3452int64_t AutoFile::tell ()
3553{
36- if (IsNull ()) {
37- throw std::ios_base::failure (" AutoFile::tell: file handle is nullptr" );
38- }
39- int64_t r{std::ftell (m_file)};
40- if (r < 0 ) {
41- throw std::ios_base::failure (" AutoFile::tell: ftell failed" );
42- }
43- return r;
54+ if (!m_position.has_value ()) throw std::ios_base::failure (" AutoFile::tell: position unknown" );
55+ return *m_position;
4456}
4557
4658void AutoFile::read (Span<std::byte> dst)
@@ -60,6 +72,7 @@ void AutoFile::ignore(size_t nSize)
6072 throw std::ios_base::failure (feof () ? " AutoFile::ignore: end of file" : " AutoFile::ignore: fread failed" );
6173 }
6274 nSize -= nNow;
75+ if (m_position.has_value ()) *m_position += nNow;
6376 }
6477}
6578
@@ -70,19 +83,19 @@ void AutoFile::write(Span<const std::byte> src)
7083 if (std::fwrite (src.data (), 1 , src.size (), m_file) != src.size ()) {
7184 throw std::ios_base::failure (" AutoFile::write: write failed" );
7285 }
86+ if (m_position.has_value ()) *m_position += src.size ();
7387 } else {
74- auto current_pos{std::ftell (m_file)};
75- if (current_pos < 0 ) throw std::ios_base::failure (" AutoFile::write: ftell failed" );
88+ if (!m_position.has_value ()) throw std::ios_base::failure (" AutoFile::write: position unknown" );
7689 std::array<std::byte, 4096 > buf;
7790 while (src.size () > 0 ) {
7891 auto buf_now{Span{buf}.first (std::min<size_t >(src.size (), buf.size ()))};
7992 std::copy (src.begin (), src.begin () + buf_now.size (), buf_now.begin ());
80- util::Xor (buf_now, m_xor, current_pos );
93+ util::Xor (buf_now, m_xor, *m_position );
8194 if (std::fwrite (buf_now.data (), 1 , buf_now.size (), m_file) != buf_now.size ()) {
8295 throw std::ios_base::failure{" XorFile::write: failed" };
8396 }
8497 src = src.subspan (buf_now.size ());
85- current_pos += buf_now.size ();
98+ *m_position += buf_now.size ();
8699 }
87100 }
88101}
0 commit comments