| // Copyright 2013 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_ | 
 | #define NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_ | 
 |  | 
 | #include <deque> | 
 | #include <utility> | 
 | #include <vector> | 
 |  | 
 | #include "base/basictypes.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/scoped_ptr.h" | 
 | #include "net/base/net_export.h" | 
 |  | 
 | extern "C" struct z_stream_s; | 
 |  | 
 | namespace net { | 
 |  | 
 | class IOBufferWithSize; | 
 |  | 
 | // WebSocketInflater uncompresses data compressed by DEFLATE algorithm. | 
 | class NET_EXPORT_PRIVATE WebSocketInflater { | 
 |  public: | 
 |   WebSocketInflater(); | 
 |   // |input_queue_capacity| is a capacity for each contiguous block in the | 
 |   // input queue. The input queue can grow without limit. | 
 |   WebSocketInflater(size_t input_queue_capacity, size_t output_buffer_capacity); | 
 |   ~WebSocketInflater(); | 
 |  | 
 |   // Returns true if there is no error. | 
 |   // |window_bits| must be between 8 and 15 (both inclusive). | 
 |   // This function must be called exactly once before calling any of the | 
 |   // following functions. | 
 |   bool Initialize(int window_bits); | 
 |  | 
 |   // Adds bytes to |stream_|. | 
 |   // Returns true if there is no error. | 
 |   // If the size of the output data reaches the capacity of the output buffer, | 
 |   // the following input data will be "choked", i.e. stored in the input queue, | 
 |   // staying compressed. | 
 |   bool AddBytes(const char* data, size_t size); | 
 |  | 
 |   // Flushes the input. | 
 |   // Returns true if there is no error. | 
 |   bool Finish(); | 
 |  | 
 |   // Returns up to |size| bytes of the decompressed output. | 
 |   // Returns null if there is an inflation error. | 
 |   // The returned bytes will be dropped from the current output and never be | 
 |   // returned again. | 
 |   // If some input data is choked, calling this function may restart the | 
 |   // inflation process. | 
 |   // This means that even if you call |Finish()| and call |GetOutput()| with | 
 |   // size = |CurrentOutputSize()|, the inflater may have some remaining data. | 
 |   // To confirm the inflater emptiness, you should check whether | 
 |   // |CurrentOutputSize()| is zero. | 
 |   scoped_refptr<IOBufferWithSize> GetOutput(size_t size); | 
 |  | 
 |   // Returns the size of the current inflated output. | 
 |   size_t CurrentOutputSize() const { return output_buffer_.Size(); } | 
 |  | 
 |   static const size_t kDefaultBufferCapacity = 512; | 
 |   static const size_t kDefaultInputIOBufferCapacity = 512; | 
 |  | 
 |  private: | 
 |   // Ring buffer with fixed capacity. | 
 |   class NET_EXPORT_PRIVATE OutputBuffer { | 
 |    public: | 
 |     explicit OutputBuffer(size_t capacity); | 
 |     ~OutputBuffer(); | 
 |  | 
 |     size_t Size() const; | 
 |     // Returns (tail pointer, availabe size). | 
 |     // A user can push data to the queue by writing the data to | 
 |     // the area returned by this function and calling AdvanceTail. | 
 |     std::pair<char*, size_t> GetTail(); | 
 |     void Read(char* dest, size_t size); | 
 |     void AdvanceTail(size_t advance); | 
 |  | 
 |    private: | 
 |     void AdvanceHead(size_t advance); | 
 |  | 
 |     const size_t capacity_; | 
 |     std::vector<char> buffer_; | 
 |     size_t head_; | 
 |     size_t tail_; | 
 |   }; | 
 |  | 
 |   class InputQueue { | 
 |    public: | 
 |     // |capacity| is used for the capacity of each IOBuffer in this queue. | 
 |     // this queue itself can grow without limit. | 
 |     explicit InputQueue(size_t capacity); | 
 |     ~InputQueue(); | 
 |  | 
 |     // Returns (data pointer, size), the first component of unconsumed data. | 
 |     // The type of data pointer is non-const because |inflate| function | 
 |     // requires so. | 
 |     std::pair<char*, size_t> Top(); | 
 |     bool IsEmpty() const { return buffers_.empty(); } | 
 |     void Push(const char* data, size_t size); | 
 |     // Consumes the topmost |size| bytes. | 
 |     // |size| must be less than or equal to the first buffer size. | 
 |     void Consume(size_t size); | 
 |  | 
 |    private: | 
 |     size_t PushToLastBuffer(const char* data, size_t size); | 
 |  | 
 |     const size_t capacity_; | 
 |     size_t head_of_first_buffer_; | 
 |     size_t tail_of_last_buffer_; | 
 |     std::deque<scoped_refptr<IOBufferWithSize> > buffers_; | 
 |   }; | 
 |  | 
 |   int InflateWithFlush(const char* next_in, size_t avail_in); | 
 |   int Inflate(const char* next_in, size_t avail_in, int flush); | 
 |   int InflateChokedInput(); | 
 |  | 
 |   scoped_ptr<z_stream_s> stream_; | 
 |   InputQueue input_queue_; | 
 |   OutputBuffer output_buffer_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(WebSocketInflater); | 
 | }; | 
 |  | 
 | }  // namespace net | 
 |  | 
 | #endif  // NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_ |