Rewrite BufferedFile as a standalone class
authorMikko Rasa <tdb@tdb.fi>
Mon, 7 Oct 2013 16:36:04 +0000 (19:36 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 7 Oct 2013 16:36:04 +0000 (19:36 +0300)
The generic Filtered template is unable to account for the complexities of
buffering a seekable object.  In particular, relative seeks were broken.

I may revisit the template form at a later date if I come up with a
workable design.  For now its use is discouraged.

source/io/file.cpp
source/io/file.h
source/io/filtered.h

index 90694324aa1d6e52f8c59b9f649135725926e031..666b1edc784b9fc9d0bc76cf29d77b82ff80b826 100644 (file)
@@ -81,5 +81,66 @@ const Handle &File::get_handle(Mode m)
        return handle;
 }
 
+
+BufferedFile::BufferedFile(const string &fn, Mode m, File::CreateMode cm):
+       file(fn, m, cm),
+       buffer(file),
+       position(0)
+{
+       mode = m;
+       file.signal_end_of_file.connect(sigc::mem_fun(this, &BufferedFile::set_eof));
+}
+
+unsigned BufferedFile::do_write(const char *buf, unsigned size)
+{
+       unsigned ret = buffer.write(buf, size);
+       position += ret;
+       return ret;
+}
+
+unsigned BufferedFile::do_read(char *buf, unsigned size)
+{
+       unsigned ret = buffer.read(buf, size);
+       position += ret;
+       return ret;
+}
+
+unsigned BufferedFile::put(char c)
+{
+       unsigned ret = buffer.put(c);
+       position += ret;
+       return ret;
+}
+
+bool BufferedFile::getline(string &line)
+{
+       bool ret = buffer.getline(line);
+       if(ret)
+               position += line.size();
+       return ret;
+}
+
+int BufferedFile::get()
+{
+       int ret = buffer.get();
+       if(ret>=0)
+               ++position;
+       return ret;
+}
+
+SeekOffset BufferedFile::seek(SeekOffset offset, SeekType type)
+{
+       if(type==S_CUR)
+       {
+               offset += position;
+               type = S_BEG;
+       }
+
+       signal_flush_required.emit();
+       position = file.seek(offset, type);
+       eof_flag = false;
+       return position;
+}
+
 } // namespace IO
 } // namespace Msp
index d106561e5f599cc31367be5f3de9140a4d349cbf..d34273477736c21efdd01335e75306b52f7ba990 100644 (file)
@@ -81,7 +81,29 @@ inline File::CreateMode operator&(File::CreateMode m, File::CreateMode n)
 inline File::CreateMode operator~(File::CreateMode m)
 { return File::CreateMode(~static_cast<int>(m)); }
 
-typedef Filtered<File, Buffered> BufferedFile;
+
+class BufferedFile: public Seekable
+{
+private:
+       File file;
+       Buffered buffer;
+       SeekOffset position;
+
+public:
+       BufferedFile(const std::string &, Mode = M_READ, File::CreateMode = File::C_OVERWRITE);
+
+protected:
+       virtual unsigned do_write(const char *, unsigned);
+       virtual unsigned do_read(char *, unsigned);
+public:
+       virtual unsigned put(char);
+
+       virtual bool getline(std::string &);
+       virtual int get();
+
+       virtual SeekOffset seek(SeekOffset, SeekType);
+       virtual SeekOffset tell() const { return position; }
+};
 
 } // namespace IO
 } // namespace Msp
index a4a43192b4b2c166dbf4952e3dfff4ee9aad270e..209274361e4432ca6608d4eb1112786c5b84e100 100644 (file)
@@ -4,7 +4,11 @@
 namespace Msp {
 namespace IO {
 
-// XXX This needs a redesign
+/**
+This class is broken by design.  Do not use.  It exposes base class methods in
+an unsafe and misleading way.  In particular, a Filtered<File, Buffered> causes
+seeks to behave incorrectly.
+*/
 template<typename B, typename F>
 class Filtered: public B
 {