summaryrefslogtreecommitdiffstats
path: root/net/base/filter.h
blob: 3551056467c624e36528149ce374de36784b2248 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright (c) 2006-2008 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.
//
// Filter performs filtering on data streams. Sample usage:
//
//   IStream* pre_filter_source;
//   ...
//   Filter* filter = Filter::Factory(filter_type, size);
//   int pre_filter_data_len = filter->stream_buffer_size();
//   pre_filter_source->read(filter->stream_buffer(), pre_filter_data_len);
//
//   filter->FlushStreamBuffer(pre_filter_data_len);
//
//   char post_filter_buf[kBufferSize];
//   int post_filter_data_len = kBufferSize;
//   filter->ReadFilteredData(post_filter_buf, &post_filter_data_len);
//
// To filter a data stream, the caller first gets filter's stream_buffer_
// through its accessor and fills in stream_buffer_ with pre-filter data, next
// calls FlushStreamBuffer to notify Filter, then calls ReadFilteredData
// repeatedly to get all the filtered data. After all data have been fitlered
// and read out, the caller may fill in stream_buffer_ again. This
// WriteBuffer-Flush-Read cycle is repeated until reaching the end of data
// stream.
//
// The lifetime of a Filter instance is completely controlled by its caller.

#ifndef NET_BASE_FILTER_H__
#define NET_BASE_FILTER_H__

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "googleurl/src/gurl.h"

class Filter {
 public:
  // Creates a Filter object.
  // Parameters: Filter_types specifies the type of filter created; Buffer_size
  // specifies the size (in number of chars) of the buffer the filter should
  // allocate to hold pre-filter data.
  // If success, the function returns the pointer to the Filter object created.
  // If failed or a filter is not needed, the function returns NULL.
  //
  // Note: filter_types is an array of filter names (content encoding types as
  // provided in an HTTP header), which will be chained together serially do
  // successive filtering of data.  The names in the vector are ordered based on
  // encoding order, and the filters are chained to operate in the reverse
  // (decoding) order. For example, types[0] = "sdch", types[1] = "gzip" will
  // cause data to first be gunizip filtered, and the resulting output from that
  // filter will be sdch decoded.
  static Filter* Factory(const std::vector<std::string>& filter_types,
                         const std::string& mime_type,
                         int buffer_size);

  virtual ~Filter();

  // Return values of function ReadFilteredData.
  enum FilterStatus {
    // Read filtered data successfully
    FILTER_OK,
    // Read filtered data successfully, and the data in the buffer has been
    // consumed by the filter, but more data is needed in order to continue
    // filtering.  At this point, the caller is free to reuse the filter
    // buffer to provide more data.
    FILTER_NEED_MORE_DATA,
    // Read filtered data successfully, and filter reaches the end of the data
    // stream.
    FILTER_DONE,
    // There is an error during filtering.
    FILTER_ERROR
  };

  // External call to obtain data from this filter chain.  If ther is no
  // next_filter_, then it obtains data from this specific filter.
  FilterStatus ReadData(char* dest_buffer, int* dest_len);

  // Returns a pointer to the beginning of stream_buffer_.
  char* stream_buffer() const { return stream_buffer_.get(); }

  // Returns the maximum size of stream_buffer_ in number of chars.
  int stream_buffer_size() const { return stream_buffer_size_; }

  // Returns the total number of chars remaining in stream_buffer_ to be
  // filtered.
  //
  // If the function returns 0 then all data have been filtered and the caller
  // is safe to copy new data into stream_buffer_.
  int stream_data_len() const { return stream_data_len_; }

  // Flushes stream_buffer_ for next round of filtering. After copying data to
  // stream_buffer_, the caller should call this function to notify Filter to
  // start filtering. Then after this function is called, the caller can get
  // post-filtered data using ReadFilteredData. The caller must not write to
  // stream_buffer_ and call this function again before stream_buffer_ is empty
  // out by ReadFilteredData.
  //
  // The input stream_data_len is the length (in number of chars) of valid
  // data in stream_buffer_. It can not be greater than stream_buffer_size_.
  // The function returns true if success, and false otherwise.
  bool FlushStreamBuffer(int stream_data_len);

  void SetURL(const GURL& url);
  const GURL& url() const { return url_; }

 protected:
  // Filters the data stored in stream_buffer_ and writes the output into the
  // dest_buffer passed in.
  //
  // Upon entry, *dest_len is the total size (in number of chars) of the
  // destination buffer. Upon exit, *dest_len is the actual number of chars
  // written into the destination buffer.
  //
  // This function will fail if there is no pre-filter data in the
  // stream_buffer_. On the other hand, *dest_len can be 0 upon successful
  // return. For example, a decoding filter may process some pre-filter data
  // but not produce output yet.
  virtual FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len);

  Filter();

  // Copy pre-filter data directly to destination buffer without decoding.
  FilterStatus CopyOut(char* dest_buffer, int* dest_len);

  // Specifies type of filters that can be created.
  enum FilterType {
    FILTER_TYPE_DEFLATE,
    FILTER_TYPE_GZIP,
    FILTER_TYPE_BZIP2,
    FILTER_TYPE_SDCH,  // open-vcdiff compression relative to a dictionary.
    FILTER_TYPE_UNSUPPORTED
  };

  // Allocates and initializes stream_buffer_.
  // Buffer_size is the maximum size of stream_buffer_ in number of chars.
  bool InitBuffer(int buffer_size);

  // A factory helper for creating filters for within a chain of potentially
  // multiple encodings.  If a chain of filters is created, then this may be
  // called multiple times during the filter creation process.  In most simple
  // cases, this is only called once. 
  static Filter* SingleFilter(const std::string& filter_type,
                              const std::string& mime_type,
                              int buffer_size);
  FilterStatus last_status() const { return last_status_; }

  // Buffer to hold the data to be filtered.
  scoped_array<char> stream_buffer_;

  // Maximum size of stream_buffer_ in number of chars.
  int stream_buffer_size_;

  // Pointer to the next data in stream_buffer_ to be filtered.
  char* next_stream_data_;

  // Total number of remaining chars in stream_buffer_ to be filtered.
  int stream_data_len_;

  // The URL that is currently being filtered.
  // This is used by SDCH filters which need to restrict use of a dictionary to
  // a specific URL or path.
  GURL url_;

  // An optional filter to process output from this filter.
  scoped_ptr<Filter> next_filter_;
  // Remember what status or local filter last returned so we can better handle
  // chained filters.
  FilterStatus last_status_;

  DISALLOW_COPY_AND_ASSIGN(Filter);
};

#endif  // NET_BASE_FILTER_H__