44
55#include < span.h>
66#include < streams.h>
7+ #include < util/fs_helpers.h>
78
89#include < array>
910
11+ AutoFile::AutoFile (std::FILE* file, std::vector<std::byte> data_xor)
12+ : m_file{file}, m_xor{std::move (data_xor)}
13+ {
14+ if (!IsNull ()) {
15+ auto pos{std::ftell (m_file)};
16+ if (pos >= 0 ) m_position = pos;
17+ }
18+ }
19+
1020std::size_t AutoFile::detail_fread (Span<std::byte> dst)
1121{
1222 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;
23+ size_t ret = std::fread (dst.data (), 1 , dst.size (), m_file);
24+ if (!m_xor.empty ()) {
25+ if (!m_position.has_value ()) throw std::ios_base::failure (" AutoFile::read: position unknown" );
26+ util::Xor (dst.subspan (0 , ret), m_xor, *m_position);
2127 }
28+ if (m_position.has_value ()) *m_position += ret;
29+ return ret;
2230}
2331
2432void AutoFile::seek (int64_t offset, int origin)
@@ -29,18 +37,23 @@ void AutoFile::seek(int64_t offset, int origin)
2937 if (std::fseek (m_file, offset, origin) != 0 ) {
3038 throw std::ios_base::failure (feof () ? " AutoFile::seek: end of file" : " AutoFile::seek: fseek failed" );
3139 }
40+ if (origin == SEEK_SET) {
41+ m_position = offset;
42+ } else if (origin == SEEK_CUR && m_position.has_value ()) {
43+ *m_position += offset;
44+ } else {
45+ int64_t r{std::ftell (m_file)};
46+ if (r < 0 ) {
47+ throw std::ios_base::failure (" AutoFile::seek: ftell failed" );
48+ }
49+ m_position = r;
50+ }
3251}
3352
3453int64_t AutoFile::tell ()
3554{
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;
55+ if (!m_position.has_value ()) throw std::ios_base::failure (" AutoFile::tell: position unknown" );
56+ return *m_position;
4457}
4558
4659void AutoFile::read (Span<std::byte> dst)
@@ -60,6 +73,7 @@ void AutoFile::ignore(size_t nSize)
6073 throw std::ios_base::failure (feof () ? " AutoFile::ignore: end of file" : " AutoFile::ignore: fread failed" );
6174 }
6275 nSize -= nNow;
76+ if (m_position.has_value ()) *m_position += nNow;
6377 }
6478}
6579
@@ -70,19 +84,34 @@ void AutoFile::write(Span<const std::byte> src)
7084 if (std::fwrite (src.data (), 1 , src.size (), m_file) != src.size ()) {
7185 throw std::ios_base::failure (" AutoFile::write: write failed" );
7286 }
87+ if (m_position.has_value ()) *m_position += src.size ();
7388 } else {
74- auto current_pos{std::ftell (m_file)};
75- if (current_pos < 0 ) throw std::ios_base::failure (" AutoFile::write: ftell failed" );
89+ if (!m_position.has_value ()) throw std::ios_base::failure (" AutoFile::write: position unknown" );
7690 std::array<std::byte, 4096 > buf;
7791 while (src.size () > 0 ) {
7892 auto buf_now{Span{buf}.first (std::min<size_t >(src.size (), buf.size ()))};
7993 std::copy (src.begin (), src.begin () + buf_now.size (), buf_now.begin ());
80- util::Xor (buf_now, m_xor, current_pos );
94+ util::Xor (buf_now, m_xor, *m_position );
8195 if (std::fwrite (buf_now.data (), 1 , buf_now.size (), m_file) != buf_now.size ()) {
8296 throw std::ios_base::failure{" XorFile::write: failed" };
8397 }
8498 src = src.subspan (buf_now.size ());
85- current_pos += buf_now.size ();
99+ *m_position += buf_now.size ();
86100 }
87101 }
88102}
103+
104+ bool AutoFile::Commit ()
105+ {
106+ return ::FileCommit (m_file);
107+ }
108+
109+ bool AutoFile::IsError ()
110+ {
111+ return ferror (m_file);
112+ }
113+
114+ bool AutoFile::Truncate (unsigned size)
115+ {
116+ return ::TruncateFile (m_file, size);
117+ }
0 commit comments