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.
11 #include <boost/format.hpp>
14 #include "GnashFileUtilities.h"
16 #include "IOChannel.h"
21 /// An IOChannel that works on a C stdio file.
22 class tu_file
: public IOChannel
26 // Make a file from an ordinary FILE*.
27 tu_file(FILE* fp
, bool autoclose
);
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.
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;
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().
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;
59 /// \brief Read a single byte from the stream
61 /// TODO: define what happens when the stream
62 /// is in error condition, see bad().
64 boost::uint8_t read_byte() {
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().
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().
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().
89 std::streampos
tell() const;
91 /// \brief Seek to the specified position
94 /// TODO: define what happens when an error occurs, or
95 /// when we're already in an error condition
97 /// @return true on success, or false on failure.
99 bool seek(std::streampos p
);
101 /// \brief Seek to the end of the stream
103 /// TODO: define what happens when an error occurs
107 /// \brief Return true if the end of the stream has been reached.
109 /// TODO: define what to return when in error condition
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.
124 /// Get the size of the stream
138 //// Create a file from a standard file pointer.
139 tu_file::tu_file(FILE* fp
, bool autoclose
= false)
142 _autoclose(autoclose
)
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".
156 tu_file::read(void* dst
, std::streamsize bytes
)
159 return std::fread(dst
, 1, bytes
, _data
);
162 // Return the number of bytes actually written.
164 tu_file::write(const void* src
, std::streamsize bytes
)
167 return std::fwrite(src
, 1, bytes
, _data
);
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
);
182 assert (std::ftell(_data
) == pos
);
190 const int err
= std::fseek(_data
, 0, SEEK_END
);
192 boost::format fmt
= boost::format(
193 _("Error while seeking to end: %1%")) % strerror(errno
);
194 throw IOException(fmt
.str());
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());
211 return std::feof(_data
);
217 if (!_data
) return true;
218 return std::ferror(_data
);
222 tu_file::size() const
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
;
243 std::auto_ptr
<IOChannel
>
244 makeFileChannel(FILE* fp
, bool close
)
246 std::auto_ptr
<IOChannel
> ret(new tu_file(fp
, close
));
250 } // end namespace gnash
254 // indent-tabs-mode: t