Plug more leaks (in the test, not the core)
[gnash.git] / libbase / tu_file.cpp
blob17159d037b71ebb0ca8f5962cff6a557d40d77b2
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 boost::uint32_t read_le32()
39 // read_byte() is boost::uint8_t, so no masks with 0xff are required.
40 boost::uint32_t result = static_cast<boost::uint32_t>(read_byte());
41 result |= static_cast<boost::uint32_t>(read_byte()) << 8;
42 result |= static_cast<boost::uint32_t>(read_byte()) << 16;
43 result |= static_cast<boost::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 boost::uint16_t read_le16()
54 boost::uint16_t result = static_cast<boost::uint16_t>(read_byte());
55 result |= static_cast<boost::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 boost::uint8_t read_byte() {
65 boost::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 (static_cast<size_t>(pos) > 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;
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::auto_ptr<IOChannel>
244 makeFileChannel(FILE* fp, bool close)
246 std::auto_ptr<IOChannel> ret(new tu_file(fp, close));
247 return ret;
250 } // end namespace gnash
252 // Local Variables:
253 // mode: C++
254 // indent-tabs-mode: t
255 // End: