Scopira 20080306

cacheflow.h

00001 
00002 /*
00003  *  Copyright (c) 2003    National Research Council
00004  *
00005  *  All rights reserved.
00006  *
00007  *  This material is confidential and proprietary information of
00008  *  National Research Council Canada ("Confidential Information").
00009  *  This Confidential Information may only be used and reproduced
00010  *  in accordance with the terms of the license agreement.
00011  *
00012  */
00013  
00014 #ifndef __INCLUDED_SCOPIRA_TOOL_CACHEFLOW_H__
00015 #define __INCLUDED_SCOPIRA_TOOL_CACHEFLOW_H__
00016 
00017 #include <scopira/tool/array.h>
00018 #include <scopira/tool/flow.h>
00019 #include <scopira/tool/export.h>
00020 
00021 #include <assert.h>
00022 
00023 namespace scopira
00024 {
00025   namespace tool
00026   {
00027     template <class T> class circular_vector;
00028 
00029     class cacheiflow;
00030     class cacheoflow;
00031   }
00032 }
00033 
00038 template <class T> class scopira::tool::circular_vector
00039 {
00040   public:
00041     typedef T data_type;
00042     typedef typename basic_array<T>::iterator iterator;
00043     typedef typename basic_array<T>::const_iterator const_iterator;
00044   private:
00045     typedef circular_vector<T> this_type;
00046     typedef basic_array<T> arr_type;
00047   protected:
00048     arr_type dm_ary;    // its actually 1 longer than we need
00049     iterator dm_read, dm_write;
00050   public:
00052     explicit circular_vector(size_t reserve_size = 0);
00055     void reserve(size_t reserve_size);
00056 
00057     iterator begin1(void) { return dm_read; }
00058     iterator end1(void)
00059       { return (dm_write<dm_read) ? dm_ary.end() : dm_write; }
00060     const_iterator begin1(void) const { return dm_read; }
00061     const_iterator end1(void) const
00062       { return (dm_write<dm_read) ? dm_ary.end() : dm_write; }
00063     iterator begin2(void) { return dm_ary.begin(); }
00064     iterator end2(void)
00065       { return (dm_write<dm_read) ? dm_write : dm_ary.begin(); }
00066     const_iterator begin2(void) const { return dm_ary.begin(); }
00067     const_iterator end2(void) const
00068       { return (dm_write<dm_read) ? dm_write : dm_ary.begin(); }
00069 
00071     bool empty(void) const { return dm_read == dm_write; }
00073     bool full(void) const
00074       { return (dm_write+1 == dm_read) ||
00075         (dm_read == dm_ary.begin() && dm_write == dm_ary.end()-1); }
00077     size_t size(void) const;
00079     size_t capacity(void) const { return dm_ary.size() - 1; }
00081     size_t free(void) const { return capacity() - size(); }
00083     void clear(void) { dm_read = dm_write = dm_ary.begin(); }
00084 
00086     const T & front(void) const { return *dm_read; }
00088     void push_back(const T &item);
00090     void pop_front(void);
00092     void pop_all(void) { dm_read = dm_write = dm_ary.begin(); }
00094     template <class ITER>
00095       void push_back(ITER head, ITER tail);
00098     template <class ITER>
00099       ITER pop_front(ITER head, ITER tail);
00100 
00102     void push_seek(size_t sz) { dm_write += sz; assert(dm_write<dm_ary.end()); }
00104     void short_rewind(void) { dm_read = dm_ary.begin(); }
00105 };
00106 
00107 //
00108 //
00109 // circular_vector
00110 //
00111 //
00112 
00113 template <class T>
00114 scopira::tool::circular_vector<T>::circular_vector(size_t reserve_size)
00115   : dm_ary(reserve_size+1)
00116 {
00117   if (reserve_size>0)
00118     dm_write = dm_read = dm_ary.begin();
00119 }
00120 
00121 template <class T>
00122 void scopira::tool::circular_vector<T>::reserve(size_t reserve_size)
00123 {
00124   dm_ary.resize(reserve_size+1);
00125   if (reserve_size>0)
00126     dm_write = dm_read = dm_ary.begin();
00127 }
00128 
00129 template <class T>
00130 size_t scopira::tool::circular_vector<T>::size(void) const
00131 {
00132   if (dm_write >= dm_read)
00133     return dm_write - dm_read;
00134   else
00135     return dm_ary.size() + (dm_write - dm_read);
00136 }
00137 
00138 template <class T>
00139 void scopira::tool::circular_vector<T>::push_back(const T &item)
00140 {
00141   *dm_write = item;
00142   ++dm_write;
00143   assert(dm_read != dm_write);    // easier to do this check here
00144 }
00145 
00146 template <class T>
00147 void scopira::tool::circular_vector<T>::pop_front(void)
00148 {
00149   assert(!empty());
00150 
00151   ++dm_read;
00152   if (dm_read == dm_ary.end())
00153     dm_read = dm_ary.begin();
00154 }
00155 
00156 template <class T> template <class ITER>
00157 void scopira::tool::circular_vector<T>::push_back(ITER head, ITER tail)
00158 {
00159   assert(free() >= (tail - head));
00160 
00161   // 2-part write
00162   while (head != tail && dm_write != dm_ary.end()) {
00163     *dm_write = *head;
00164     ++head;
00165     ++dm_write;
00166   }
00167 
00168   if (dm_write == dm_ary.end())
00169     dm_write = dm_ary.begin();
00170   else
00171     return; // 1 part was enough, i guess
00172 
00173   while (head != tail) {
00174     *dm_write = *head;
00175     ++head;
00176     ++dm_write;
00177   }
00178 }
00179 
00180 template <class T> template <class ITER>
00181 ITER scopira::tool::circular_vector<T>::pop_front(ITER head, ITER tail)
00182 {
00183   iterator endend;
00184 
00185   endend = dm_write < dm_read ? dm_ary.end() : dm_write;
00186   // 2-part write
00187   while (head != tail && dm_read != endend) {
00188     *head = *dm_read;
00189     ++head;
00190     ++dm_read;
00191   }
00192 
00193   if (head != tail && !empty())
00194     dm_read = dm_ary.begin();
00195   else
00196     return head; // 1 part was enough, i guess
00197 
00198   while (head != tail && dm_read != dm_write) {
00199     *head = *dm_read;
00200     ++head;
00201     ++dm_read;
00202   }
00203 
00204   return head;
00205 }
00210 class scopira::tool::cacheiflow : public scopira::tool::iflow_i
00211 {
00212   protected:
00213     count2_ptr< iflow_i > dm_in;
00214     circular_vector<byte_t> dm_cache;
00215     bool dm_failed;
00216 
00217   public:
00226     SCOPIRA_EXPORT cacheiflow(bool doref, iflow_i* innie, size_t buffersize = 32768);
00227 
00229     SCOPIRA_EXPORT virtual bool failed(void) const { return dm_failed; }
00230 
00232     SCOPIRA_EXPORT virtual size_t read(byte_t* _buf, size_t _maxsize);
00234     SCOPIRA_EXPORT virtual size_t read_byte(byte_t &out);
00235 
00237     SCOPIRA_EXPORT void open(iflow_i* in);
00239     SCOPIRA_EXPORT void close(void);
00240 
00244     SCOPIRA_EXPORT void short_rewind(void);
00245 
00247     SCOPIRA_EXPORT void load_cache(void);
00248 };
00249 
00254 class scopira::tool::cacheoflow : public scopira::tool::oflow_i
00255 {
00256   protected:
00257     count2_ptr< oflow_i > dm_out;
00258     circular_vector<byte_t> dm_cache;
00259     bool dm_failed;
00260 
00261   public:
00270     SCOPIRA_EXPORT cacheoflow(bool doref, oflow_i* out, size_t buffersize = 32768);
00272     SCOPIRA_EXPORT ~cacheoflow();
00273 
00275     SCOPIRA_EXPORT virtual bool failed(void) const { return dm_failed; }
00276 
00278     SCOPIRA_EXPORT virtual size_t write(const byte_t* _buf, size_t _size);
00280     SCOPIRA_EXPORT virtual size_t write_byte(byte_t b);
00281 
00283     SCOPIRA_EXPORT void open(oflow_i* in);
00285     SCOPIRA_EXPORT void close(void);
00286 
00290     SCOPIRA_EXPORT void flush_cache(void);
00291 };
00292 
00293 #endif