SatCat5
file_io.cc
1 // Copyright 2021-2024 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <hal_posix/file_io.h>
8 
9 #if SATCAT5_WIN32
10  #include <io.h> // Windows file I/O
11  #undef ERROR // Deconflict Windows "ERROR" macro
12 #else
13  #include <unistd.h> // For "ftruncate"
14 #endif
15 
18 
19 FileWriter::FileWriter(const char* filename, bool close_on_finalize)
20  : m_close_on_finalize(close_on_finalize)
21  , m_file(0)
22  , m_last_commit(0)
23 {
24  // Open file if specified, otherwise remain idle.
25  if (filename) open(filename);
26 }
27 
28 FileWriter::~FileWriter()
29 {
30  close();
31 }
32 
33 void FileWriter::open(const char* filename)
34 {
35  // Cleanup before attempting to open the new file.
36  close();
37  if (filename) m_file = fopen(filename, "wb");
38 }
39 
40 void FileWriter::close()
41 {
42  // Close file object and revert to idle state.
43  if (m_file) fclose(m_file);
44  m_file = 0;
45  m_last_commit = 0;
46 }
47 
48 void FileWriter::seek(unsigned offset)
49 {
50  if (m_file) fseek(m_file, m_last_commit + offset, SEEK_SET);
51 }
52 
54 {
55  // If a file is open, max write length is effectively unlimited.
56  return m_file ? UINT32_MAX : 0;
57 }
58 
59 void FileWriter::write_bytes(unsigned nbytes, const void* src)
60 {
61  if (m_file) fwrite(src, 1, nbytes, m_file);
62 }
63 
65 {
66  // Close current file or just keep writing?
67  if (m_file) m_last_commit = (unsigned)ftell(m_file);
68  if (m_close_on_finalize) close();
69  return true;
70 }
71 
73 {
74  if (!m_file) return;
75  fflush(m_file);
76 #if SATCAT5_WIN32
77  _chsize(fileno(m_file), m_last_commit);
78 #else
79  ftruncate(fileno(m_file), m_last_commit);
80 #endif
81  fseek(m_file, m_last_commit, SEEK_SET);
82 }
83 
85 {
86  if (m_file) fputc(data, m_file);
87 }
88 
89 FileReader::FileReader(const char* filename, bool close_on_finalize)
90  : m_close_on_finalize(close_on_finalize)
91  , m_file(0)
92  , m_rem(0)
93 {
94  // Open filename if specified, otherwise remain idle.
95  if (filename) open(filename);
96 }
97 
98 FileReader::~FileReader()
99 {
100  close();
101 }
102 
103 void FileReader::open(const char* filename, unsigned len)
104 {
105  // Close current input file before attempting to open the new one.
106  close();
107  if (filename) m_file = fopen(filename, "rb");
108 
109  // Specified length, or auto-sense from file size?
110  if (len) {
111  m_rem = len;
112  } else if (m_file) {
113  fseek(m_file, 0, SEEK_END);
114  m_rem = (unsigned)ftell(m_file);
115  fseek(m_file, 0, SEEK_SET);
116  }
117 }
118 
119 void FileReader::close()
120 {
121  // Close file object and revert to idle state.
122  if (m_file) fclose(m_file);
123  m_file = 0;
124  m_rem = 0;
125 }
126 
128 {
129  return m_file ? m_rem : 0;
130 }
131 
132 bool FileReader::read_bytes(unsigned nbytes, void* dst)
133 {
134  size_t result = 0;
135  if (m_file && m_rem >= nbytes) {
136  result = fread(dst, 1, nbytes, m_file);
137  m_rem -= result;
138  }
139  return (result == nbytes);
140 }
141 
142 bool FileReader::read_consume(unsigned nbytes)
143 {
144  if (m_file && m_rem >= nbytes) {
145  fseek(m_file, (int)nbytes, SEEK_CUR);
146  m_rem -= nbytes;
147  return true;
148  } else {
149  return false;
150  }
151 }
152 
154 {
155  // Close current file or just keep reading?
156  if (m_close_on_finalize) close();
157 }
158 
160 {
161  if (m_file && m_rem) {
162  --m_rem;
163  return (u8)fgetc(m_file);
164  } else {
165  return 0;
166  }
167 }
Read bytes or packets from a file.
Definition: file_io.h:48
FileReader(const char *filename=0, bool close_on_finalize=false)
Create the FileWriter object.
Definition: file_io.cc:89
void read_finalize() override
Consume any remaining bytes in this frame, if applicable.
Definition: file_io.cc:153
void open(const char *filename, unsigned len=0)
Open the specified file to read the next frame.
Definition: file_io.cc:103
bool read_bytes(unsigned nbytes, void *dst)
Read 0 or more bytes into a buffer.
Definition: file_io.cc:132
unsigned get_read_ready() const override
How many bytes can be read without blocking?
Definition: file_io.cc:127
bool read_consume(unsigned nbytes)
Read and discard 0 or more bytes.
Definition: file_io.cc:142
u8 read_next() override
Read the next byte from the underlying buffer or device.
Definition: file_io.cc:159
Write bytes or packets to a file.
Definition: file_io.h:16
unsigned get_write_space() const override
How many bytes can be written without blocking?
Definition: file_io.cc:53
void write_bytes(unsigned nbytes, const void *src)
Write 0 or more bytes from a buffer.
Definition: file_io.cc:59
void write_abort() override
If possible, abort the current partially-written packet.
Definition: file_io.cc:72
bool write_finalize() override
Mark end of frame and release temporary working data.
Definition: file_io.cc:64
void write_next(u8 data) override
Write the next byte to the underlying buffer or device.
Definition: file_io.cc:84
void open(const char *filename)
Open the specified file.
Definition: file_io.cc:33
void seek(unsigned offset)
Move write cursor to the specified absolute offset.
Definition: file_io.cc:48
Miscellaneous POSIX wrappers (e.g., heap allocation, log to console...)