Update with current status
[gnash.git] / libbase / tu_file.cpp
blob0091cb7af1a04cfda87145936a11b625b134ccae
1 // tu_file.cpp -- Ignacio CastaƱo, Thatcher Ulrich <tu@tulrich.com> 2003
3 // This source code has been donated to the Public Domain. Do
4 // whatever you want with it.
6 // A file class that can be customized with callbacks.
8 #include "tu_file.h"
10 #include <cstdio>
11 #include <boost/format.hpp>
12 #include <cerrno>
14 #include "GnashFileUtilities.h"
15 #include "utility.h"
16 #include "IOChannel.h"
17 #include "log.h"
19 namespace gnash {
21 /// An IOChannel that works on a C stdio file.
22 class tu_file : public IOChannel
24 public:
26 // Make a file from an ordinary FILE*.
27 tu_file(FILE* fp, bool autoclose);
29 ~tu_file();
31 /// \brief Read a 32-bit word from a little-endian stream.
32 /// returning it as a native-endian word.
34 /// TODO: define what happens when the stream
35 /// is in error condition.
36 ///
37 std::uint32_t read_le32()
39 // read_byte() is std::uint8_t, so no masks with 0xff are required.
40 std::uint32_t result = static_cast<std::uint32_t>(read_byte());
41 result |= static_cast<std::uint32_t>(read_byte()) << 8;
42 result |= static_cast<std::uint32_t>(read_byte()) << 16;
43 result |= static_cast<std::uint32_t>(read_byte()) << 24;
44 return(result);
47 /// \brief Read a 16-bit word from a little-endian stream.
49 /// TODO: define what happens when the stream
50 /// is in error condition, see bad().
51 ///
52 std::uint16_t read_le16()
54 std::uint16_t result = static_cast<std::uint16_t>(read_byte());
55 result |= static_cast<std::uint16_t>(read_byte()) << 8;
56 return(result);
59 /// \brief Read a single byte from the stream
61 /// TODO: define what happens when the stream
62 /// is in error condition, see bad().
63 ///
64 std::uint8_t read_byte() {
65 std::uint8_t u;
66 read(&u, 1);
67 return u;
70 /// \brief Read the given number of bytes from the stream
72 /// TODO: define what happens when the stream
73 /// is in error condition, see bad().
74 ///
75 std::streamsize read(void* dst, std::streamsize num);
77 /// \brief Write the given number of bytes to the stream
79 /// TODO: define what happens when the stream
80 /// is in error condition, see bad().
81 ///
82 std::streamsize write(const void* src, std::streamsize num);
84 /// \brief Return current stream position
86 /// TODO: define what to return when the stream
87 /// is in error condition, see bad().
88 ///
89 std::streampos tell() const;
91 /// \brief Seek to the specified position
93 ///
94 /// TODO: define what happens when an error occurs, or
95 /// when we're already in an error condition
96 ///
97 /// @return true on success, or false on failure.
98 ///
99 bool seek(std::streampos p);
101 /// \brief Seek to the end of the stream
103 /// TODO: define what happens when an error occurs
105 void go_to_end();
107 /// \brief Return true if the end of the stream has been reached.
109 /// TODO: define what to return when in error condition
110 /// see bad().
112 bool eof() const;
114 /// \brief Return non-zero if the stream is in an error state
116 /// When the stream is in an error state there's nothing
117 /// you can do about it, just delete it and log the error.
119 /// There are some rough meaning for possible returned values
120 /// but I don't think they make much sense currently.
122 bool bad() const;
124 /// Get the size of the stream
125 size_t size() const;
127 private:
129 void close();
131 FILE* _data;
133 bool _autoclose;
138 //// Create a file from a standard file pointer.
139 tu_file::tu_file(FILE* fp, bool autoclose = false)
141 _data(fp),
142 _autoclose(autoclose)
146 tu_file::~tu_file()
148 // Close this file when destroyed unless not requested.
149 if (_autoclose) close();
153 // Return the number of bytes actually read. EOF or an error would
154 // cause that to not be equal to "bytes".
155 std::streamsize
156 tu_file::read(void* dst, std::streamsize bytes)
158 assert(dst);
159 return std::fread(dst, 1, bytes, _data);
162 // Return the number of bytes actually written.
163 std::streamsize
164 tu_file::write(const void* src, std::streamsize bytes)
166 assert(src);
167 return std::fwrite(src, 1, bytes, _data);
170 bool
171 tu_file::seek(std::streampos pos)
173 // TODO: optimize this by caching total stream size ?
174 if (pos > static_cast<std::streampos>(size())) return false;
176 std::clearerr(_data); // make sure EOF flag is cleared.
177 const int result = std::fseek(_data, pos, SEEK_SET);
178 if (result == EOF) {
179 return false;
181 assert (pos < std::numeric_limits<long>::max());
182 assert (std::ftell(_data) == pos);
184 return true;
187 void
188 tu_file::go_to_end()
190 const int err = std::fseek(_data, 0, SEEK_END);
191 if (err == -1) {
192 boost::format fmt = boost::format(
193 _("Error while seeking to end: %1%")) % strerror(errno);
194 throw IOException(fmt.str());
198 std::streampos
199 tu_file::tell() const
201 std::streampos ret = std::ftell(_data);
202 if (ret < 0) throw IOException("Error getting stream position");
204 assert(static_cast<size_t>(ret) <= size());
205 return ret;
208 bool
209 tu_file::eof() const
211 return std::feof(_data);
214 bool
215 tu_file::bad() const
217 if (!_data) return true;
218 return std::ferror(_data);
221 size_t
222 tu_file::size() const
224 assert(_data);
226 struct stat statbuf;
227 if (fstat(fileno(_data), &statbuf) < 0)
229 log_error(_("Could not fstat file"));
230 return static_cast<size_t>(-1);
232 return statbuf.st_size;
236 void
237 tu_file::close()
239 assert(_data);
240 std::fclose(_data);
243 std::unique_ptr<IOChannel>
244 makeFileChannel(FILE* fp, bool close)
246 std::unique_ptr<IOChannel> ret(new tu_file(fp, close));
247 return ret;
250 std::unique_ptr<IOChannel>
251 makeFileChannel(const char* filepath, const char* mode)
253 FILE* fp = fopen(filepath, mode);
254 if ( fp == nullptr ) { return std::unique_ptr<IOChannel>(); }
256 return makeFileChannel(fp, true);
260 } // end namespace gnash
262 // Local Variables:
263 // mode: C++
264 // indent-tabs-mode: t
265 // End: