file_cached.h

Go to the documentation of this file.
00001 class file_cached : public file {
00002 public:
00003         static void g_create(service_ptr_t<file> & p_out,service_ptr_t<file> p_base,abort_callback & p_abort, t_size blockSize) {
00004                 service_ptr_t<file_cached> temp = new service_impl_t<file_cached>(blockSize);
00005                 temp->initialize(p_base,p_abort);
00006                 p_out = temp.get_ptr();
00007         }
00008 protected:
00009         file_cached(t_size blocksize) {
00010                 m_buffer.set_size(blocksize);
00011         }
00012         void initialize(service_ptr_t<file> p_base,abort_callback & p_abort) {
00013                 m_base = p_base;
00014                 m_position = 0;
00015                 m_can_seek = m_base->can_seek();
00016                 if (m_can_seek) {
00017                         m_position_base = m_base->get_position(p_abort);
00018                 } else {
00019                         m_position_base = 0;
00020                 }
00021 
00022                 m_size = m_base->get_size(p_abort);
00023 
00024                 flush_buffer();
00025         }
00026 public:
00027 
00028         t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
00029                 t_uint8 * outptr = (t_uint8*)p_buffer;
00030                 t_size done = 0;
00031                 while(done < p_bytes && m_position < m_size) {
00032                         p_abort.check();
00033 
00034                         if (m_position >= m_buffer_position && m_position < m_buffer_position + m_buffer_status) {                              
00035                                 t_size delta = pfc::min_t<t_size>((t_size)(m_buffer_position + m_buffer_status - m_position),p_bytes - done);
00036                                 t_size bufptr = (t_size)(m_position - m_buffer_position);
00037                                 memcpy(outptr+done,m_buffer.get_ptr()+bufptr,delta);
00038                                 done += delta;
00039                                 m_position += delta;
00040                                 if (m_buffer_status != m_buffer.get_size() && done < p_bytes) break;//EOF before m_size is hit
00041                         } else {
00042                                 m_buffer_position = m_position - m_position % m_buffer.get_size();
00043                                 adjust_position(m_buffer_position,p_abort);
00044 
00045                                 m_buffer_status = m_base->read(m_buffer.get_ptr(),m_buffer.get_size(),p_abort);
00046                                 m_position_base += m_buffer_status;
00047 
00048                                 if (m_buffer_status <= (t_size)(m_position - m_buffer_position)) break;
00049                         }
00050                 }
00051 
00052                 return done;
00053         }
00054 
00055         void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
00056                 p_abort.check();
00057                 adjust_position(m_position,p_abort);
00058                 m_base->write(p_buffer,p_bytes,p_abort);
00059                 m_position_base = m_position = m_position + p_bytes;
00060                 if (m_size < m_position) m_size = m_position;
00061                 flush_buffer();
00062         }
00063 
00064         t_filesize get_size(abort_callback & p_abort) {
00065                 p_abort.check();
00066                 return m_size;
00067         }
00068         t_filesize get_position(abort_callback & p_abort) {
00069                 p_abort.check();
00070                 return m_position;
00071         }
00072         void set_eof(abort_callback & p_abort) {
00073                 p_abort.check();
00074                 adjust_position(m_position,p_abort);
00075                 m_base->set_eof(p_abort);
00076                 flush_buffer();
00077         }
00078         void seek(t_filesize p_position,abort_callback & p_abort) {
00079                 p_abort.check();
00080                 if (!m_can_seek) throw exception_io_object_not_seekable();
00081                 if (p_position > m_size) throw exception_io_seek_out_of_range();
00082                 m_position = p_position;
00083         }
00084         void reopen(abort_callback & p_abort) {seek(0,p_abort);}
00085         bool can_seek() {return m_can_seek;}
00086         bool get_content_type(pfc::string_base & out) {return m_base->get_content_type(out);}
00087         void on_idle(abort_callback & p_abort) {p_abort.check();m_base->on_idle(p_abort);}
00088         t_filetimestamp get_timestamp(abort_callback & p_abort) {p_abort.check(); return m_base->get_timestamp(p_abort);}
00089         bool is_remote() {return m_base->is_remote();}
00090         void resize(t_filesize p_size,abort_callback & p_abort) {
00091                 flush_buffer();
00092                 m_base->resize(p_size,p_abort);
00093                 m_size = p_size;
00094                 if (m_position > m_size) m_position = m_size;
00095                 if (m_position_base > m_size) m_position_base = m_size;
00096         }
00097 private:
00098         void adjust_position(t_filesize p_target,abort_callback & p_abort) {
00099                 if (p_target != m_position_base) {
00100                         m_base->seek(p_target,p_abort);
00101                         m_position_base = p_target;
00102                 }
00103         }
00104 
00105         void flush_buffer() {
00106                 m_buffer_status = 0;
00107                 m_buffer_position = 0;
00108         }
00109 
00110         service_ptr_t<file> m_base;
00111         t_filesize m_position,m_position_base,m_size;
00112         bool m_can_seek;
00113         t_filesize m_buffer_position;
00114         t_size m_buffer_status;
00115         pfc::array_t<t_uint8> m_buffer;
00116 };

Generated on Fri Apr 25 18:49:33 2008 for foobar2000 SDK by  doxygen 1.5.5