title: Implement circular buffer to write/read arbitrary amount of data in a single call
body: <p>Most of circular buffer assumes to only read/write ONE object each time, the only link I found to  operates on binary data in form of (const char *bytes, size_t byte_count) is <a href="http://www.asawicki.info/news_1468_circular_buffer_of_raw_binary_data_in_c.html" rel="noreferrer">http://www.asawicki.info/news_1468_circular_buffer_of_raw_binary_data_in_c.html</a>, which I feel is not incorrect and a little long. What is the right implementation for that? </p>
  
  <p>I created one myself. but it is still long. Can anybody share a more elegant version? or can you point out is there any thing I can improve in my code to make it short?</p>
  
  <pre><code>class Pipe{
      Pipe(size_t capacity): _capacity(capacity){ init();  }
      ~Pipe(){delete [] _buf; }
      size_t read(char* data, size_t bytes);
      size_t write(const char* data, size_t bytes);
     private: 
      //only _capacity-1 is used, one is to identify full or empty.
      void init(){_buf = new char[_capacity]; 
       _wptr = 0; _rptr = 0; _used_size = 0; 
      }
      char* _buf;
      size_t _capacity, _wptr, _rptr, _used_size;
      bool isFull(){return (_wptr + 1 ) % (_capacity) == _rptr;} 
      bool isEmpty(){return _wptr == _rptr;} 
  }; 
  size_t Pipe::read(char* data, size_t bytes){
      if (isEmpty() || bytes == 0) return 0;
      size_t bytes_read1 = 0, bytes_read2 = 0;
      if (_rptr&gt;=_wptr+1) { //two piece can be read
          bytes_read1 = min(bytes, _capacity - _rptr);
          memcpy(data, _buf + _rptr, bytes_read1);
          _rptr += bytes_read1;
          bytes -= bytes_read1;
          if (_rptr == _capacity) _rptr = 0;
          if (bytes &gt; 0){
          bytes_read2 = min(bytes, _wptr);
              memcpy(_buf + _rptr, data, bytes_read2);
              _rptr += bytes_read2;
              bytes -= bytes_read2;
          }
      }
      else{//one piece can be read
      bytes_read1 = min(bytes, _wptr - _rptr); 
      memcpy(_buf + _wptr, data, bytes_read1);
      _rptr += bytes_read1;
      bytes -= bytes_read1;
      }
      return bytes_read1 + bytes_read2; 
  }
  
  size_t Pipe::write(const char* data, size_t bytes){
      if (isFull() || bytes == 0) return 0;
      size_t bytes_write1 = 0, bytes_write2 = 0;
      if (_wptr&gt;=_rptr) { //two piece can be written
          bytes_write1 = min(bytes, _capacity - _wptr); 
          memcpy(_buf + _wptr, data, bytes_write1);
          _wptr += bytes_write1;
          bytes -= bytes_write1;
          if (_wptr == _capacity) _wptr = 0;
          if (bytes &gt; 0){ //_wptr must be 0 here.
              bytes_write2 = min(bytes, _rptr-1);//-1 bcz there is one     
      slot to check empty/full
              memcpy(_buf + _wptr, data+ bytes_write1, bytes_write2);
              _wptr += bytes_write2;
              bytes -= bytes_write2;
          }
      }
      else{ //one piece can be written
          bytes_write1 = min(bytes, _rptr - _wptr -1); 
          memcpy(_buf + _wptr, data, bytes_write1);
          _wptr += bytes_write1;
          bytes -= bytes_write1;
      }
      return bytes_write1 + bytes_write2; 
  }
  </code></pre>