IO.hpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 #ifndef GOSU_IO_HPP
00005 #define GOSU_IO_HPP
00006 
00007 #include <cstddef>
00008 #include <algorithm>
00009 #include <memory>
00010 #include <string>
00011 #include <vector>
00012 
00013 namespace Gosu
00014 {
00015     class Resource;
00016     
00017     enum ByteOrder { boLittle, boBig, boDontCare };
00018 #ifdef __BIG_ENDIAN__
00019     const ByteOrder nativeByteOrder = boBig, otherByteOrder = boLittle;
00020 #else
00021     const ByteOrder nativeByteOrder = boLittle, otherByteOrder = boBig;
00022 #endif
00023 
00026     class Reader
00027     {
00028         const Resource* res;
00029         std::size_t pos;
00030 
00031     public:
00032         Reader(const Resource& resource, std::size_t position)
00033         : res(&resource), pos(position)
00034         {
00035         }
00036 
00037         const Resource& resource() const
00038         {
00039             return *res;
00040         }
00041 
00042         std::size_t position() const
00043         {
00044             return pos;
00045         }
00046 
00047         void setPosition(std::size_t value)
00048         {
00049             // TODO: Check?
00050             pos = value;
00051         }
00052 
00053         void seek(std::ptrdiff_t offset)
00054         {
00055             // TODO: Check?
00056             pos += offset;
00057         }
00058 
00059         void read(void* destBuffer, std::size_t length);
00060         
00062         template<typename T>
00063         void readPod(T& t, ByteOrder bo = boDontCare)
00064         {
00065             read(&t, sizeof t);
00066             if (bo == otherByteOrder)
00067             {
00068                 char* begin = reinterpret_cast<char*>(&t);
00069                 std::reverse(begin, begin + sizeof t);
00070             }
00071         }
00072 
00074         template<typename T>
00075         T getPod(ByteOrder bo = boDontCare)
00076         {
00077             T t;
00078             readPod<T>(t, bo);
00079             return t;
00080         }
00081     };
00082     
00085     class Writer
00086     {
00087         Resource* res;
00088         std::size_t pos;
00089 
00090     public:
00091         Writer(Resource& resource, std::size_t position)
00092         : res(&resource), pos(position)
00093         {
00094         }
00095 
00096         Resource& resource() const
00097         {
00098             return *res;
00099         }
00100 
00101         std::size_t position() const
00102         {
00103             return pos;
00104         }
00105 
00106         void setPosition(std::size_t value)
00107         {
00108             // TODO: Check?
00109             pos = value;
00110         }
00111 
00112         void seek(std::ptrdiff_t offset)
00113         {
00114             // TODO: Check?
00115             pos += offset;
00116         }
00117 
00118         void write(const void* sourceBuffer, std::size_t length);
00119 
00121         template<typename T>
00122         void writePod(const T& t, ByteOrder bo = boDontCare)
00123         {
00124             if (bo == otherByteOrder)
00125             {
00126                 char buf[sizeof t];
00127                 const char* begin = reinterpret_cast<const char*>(&t);
00128                 std::reverse_copy(begin, begin + sizeof t, buf);
00129                 write(buf, sizeof buf);
00130             }
00131             else
00132                 write(&t, sizeof t);
00133         }
00134     };
00135 
00141     class Resource
00142     {
00143         // Non-copyable
00144         Resource(const Resource&);
00145         Resource& operator=(const Resource&);
00146 
00147     public:
00148         Resource()
00149         {
00150         }
00151         
00152         virtual ~Resource()
00153         {
00154         }
00155 
00158         Reader frontReader() const
00159         {
00160             return Reader(*this, 0);
00161         }
00162 
00165         Writer backWriter()
00166         {
00167             return Writer(*this, size());
00168         }
00169 
00170         virtual std::size_t size() const = 0;
00171 
00172         virtual void resize(std::size_t newSize) = 0;
00173 
00174         virtual void read(std::size_t offset, std::size_t length,
00175             void* destBuffer) const = 0;
00176 
00177         virtual void write(std::size_t offset, std::size_t length,
00178             const void* sourceBuffer) = 0;
00179     };
00180 
00182     class Buffer : public Resource
00183     {
00184         std::vector<char> buf;
00185 
00186     public:
00187         Buffer()
00188         {
00189         }
00190 
00191         Buffer(const Buffer& other)
00192         : buf(other.buf)
00193         {
00194         }
00195 
00196         Buffer& operator=(const Buffer& other)
00197         {
00198             buf = other.buf;
00199             return *this;
00200         }
00201 
00202         std::size_t size() const;
00203         void resize(std::size_t newSize);
00204 
00205         void read(std::size_t offset, std::size_t length,
00206             void* destBuffer) const;
00207 
00208         void write(std::size_t offset, std::size_t length,
00209             const void* sourceBuffer);
00210 
00211         const void* data() const
00212         {
00213             return &buf[0];
00214         }
00215 
00216         void* data()
00217         {
00218             return &buf[0];
00219         }
00220     };
00221 
00222     enum FileMode
00223     {
00226         fmRead,
00229         fmReplace,
00232         fmAlter
00233     };
00234 
00236     class File : public Resource
00237     {
00238         struct Impl;
00239         const std::auto_ptr<Impl> pimpl;
00240 
00241     public:
00242         explicit File(const std::wstring& filename, FileMode mode = fmRead);
00243         ~File();
00244 
00245         std::size_t size() const;
00246         void resize(std::size_t newSize);
00247         void read(std::size_t offset, std::size_t length,
00248             void* destBuffer) const;
00249         void write(std::size_t offset, std::size_t length,
00250             const void* sourceBuffer);
00251     };
00252 
00254     void loadFile(Buffer& buffer, const std::wstring& filename);
00256     void saveFile(const Buffer& buffer, const std::wstring& filename);
00257 }
00258 
00259 #endif