CppCMS
booster/aio/buffer.h
00001 //
00002 //  Copyright (C) 2009-2012 Artyom Beilis (Tonkikh)
00003 //
00004 //  Distributed under the Boost Software License, Version 1.0. (See
00005 //  accompanying file LICENSE_1_0.txt or copy at
00006 //  http://www.boost.org/LICENSE_1_0.txt)
00007 //
00008 #ifndef BOOSTER_AIO_BUFFER_H
00009 #define BOOSTER_AIO_BUFFER_H
00010 
00011 #include <vector>
00012 #include <string>
00013 
00014 namespace booster {
00015         namespace aio {
00023                 template<typename Pointer>
00024                 class buffer_impl {
00025                 public:
00029                         struct entry {
00030                                 Pointer ptr;
00031                                 size_t size;
00032                         };
00033                         
00037                         buffer_impl() : 
00038                                 size_(0)
00039                         {
00040                         }
00041                 
00043                         typedef std::pair<entry const *,size_t> buffer_data_type;
00044 
00048                         std::pair<entry const *,size_t> get() const
00049                         {
00050                                 if(size_ == 0) {
00051                                         buffer_data_type bt;
00052                                         bt.first=0;
00053                                         bt.second=0;
00054                                         return bt;
00055                                 }
00056                                 else if(size_ == 1)
00057                                         return buffer_data_type(&entry_,1);
00058                                 else
00059                                         return buffer_data_type(&vec_.front(),vec_.size());
00060                         }
00064                         void add(Pointer p,size_t s)
00065                         {
00066                                 if(s==0)
00067                                         return;
00068                                 if(size_ == 0) {
00069                                         entry_.ptr = p;
00070                                         entry_.size = s;
00071                                         size_ = 1;
00072                                         return;
00073                                 }
00074                                 else if(size_ == 1) {
00075                                         vec_.push_back(entry_);
00076                                 }
00077                                 entry tmp = { p,s };
00078                                 vec_.push_back(tmp);
00079                                 size_ = vec_.size();
00080                         }
00084                         bool empty() const
00085                         {
00086                                 return size_ == 0;
00087                         }
00088                 private:
00089                         int size_;
00090                         entry entry_;
00091                         std::vector<entry> vec_;
00092                 };
00093 
00097                 class mutable_buffer : public buffer_impl<char *> {
00098                 public:
00099                         mutable_buffer() {}
00100                 };
00101 
00105                 class const_buffer : public buffer_impl<const char *> {
00106                 public:
00107                         const_buffer() {}
00111                         const_buffer(mutable_buffer const &other) 
00112                         {
00113                                 mutable_buffer::buffer_data_type data = other.get();
00114                                 for(unsigned i=0;i<data.second;i++)
00115                                         add(data.first[i].ptr,data.first[i].size);
00116                         }
00117                 };
00118 
00122                 inline const_buffer buffer(void const *p,size_t n)
00123                 {
00124                         const_buffer tmp;
00125                         tmp.add(reinterpret_cast<char const *>(p),n);
00126                         return tmp;
00127                 }
00131                 inline mutable_buffer buffer(void *p,size_t n)
00132                 {
00133                         mutable_buffer tmp;
00134                         tmp.add(reinterpret_cast<char *>(p),n);
00135                         return tmp;
00136                 }
00140                 inline const_buffer buffer(std::vector<char> const &d)
00141                 {
00142                         return buffer(&d.front(),d.size());
00143                 }
00147                 inline mutable_buffer buffer(std::vector<char> &d)
00148                 {
00149                         return buffer(&d.front(),d.size());
00150                 }
00154                 inline const_buffer buffer(std::string const &d)
00155                 {
00156                         return buffer(d.c_str(),d.size());
00157                 }
00158 
00160 
00161                 namespace details {
00162                         template<typename Buffer>
00163                         Buffer advance(Buffer const &buf,size_t n)
00164                         {
00165                                 Buffer res;
00166                                 typename Buffer::buffer_data_type data=buf.get();
00167                                 while(data.second > 0 && n > 0) {
00168                                         if(data.first->size <= n) {
00169                                                 n-= data.first->size;
00170                                                 data.second--;
00171                                                 data.first++;
00172                                         }
00173                                         else {
00174                                                 res.add(data.first->ptr + n,data.first->size - n);
00175                                                 n=0;
00176                                                 data.second--;
00177                                                 data.first++;
00178                                         }
00179                                 }
00180                                 while(data.second > 0) {
00181                                         res.add(data.first->ptr,data.first->size);
00182                                         data.second--;
00183                                         data.first++;
00184                                 }
00185                                 return res;
00186                         }
00187                         template<typename Buffer>
00188                         void add(Buffer &left,Buffer const &right)
00189                         {
00190                                 typename Buffer::buffer_data_type data=right.get();
00191                                 for(unsigned i=0;i<data.second;i++)
00192                                         left.add(data.first[i].ptr,data.first[i].size);
00193                         }
00194                 } // details
00195 
00197 
00203                 inline const_buffer operator+(const_buffer const &buf,size_t n)
00204                 {
00205                         return details::advance(buf,n);
00206                 }
00212                 inline mutable_buffer operator+(mutable_buffer const &buf,size_t n)
00213                 {
00214                         return details::advance(buf,n);
00215                 }
00219                 inline const_buffer &operator+=(const_buffer &buf,size_t n)
00220                 {
00221                         buf = details::advance(buf,n);
00222                         return buf;
00223                 }
00227                 inline mutable_buffer &operator+=(mutable_buffer &buf,size_t n)
00228                 {
00229                         buf = details::advance(buf,n);
00230                         return buf;
00231                 }
00235                 inline const_buffer operator+(const_buffer const &b1,const_buffer const &b2)
00236                 {
00237                         const_buffer tmp=b1;
00238                         details::add(tmp,b2);
00239                         return tmp;
00240                 }
00244                 inline const_buffer &operator+=(const_buffer &b1,const_buffer const &b2)
00245                 {
00246                         details::add(b1,b2);
00247                         return b1;
00248                 }
00252                 inline mutable_buffer operator+(mutable_buffer const &b1,mutable_buffer const &b2)
00253                 {
00254                         mutable_buffer tmp=b1;
00255                         details::add(tmp,b2);
00256                         return tmp;
00257                 }
00261                 inline mutable_buffer &operator+=(mutable_buffer &b1,mutable_buffer const &b2)
00262                 {
00263                         details::add(b1,b2);
00264                         return b1;
00265                 }
00266         
00267         } // aio
00268 } // booster
00269 
00270 
00271 
00272 
00273 
00274 #endif