OSDN Git Service

* Added serf library.
[modchxj/mod_chxj.git] / src / serf / buckets / limit_buckets.c
1 /* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <apr_pools.h>
17
18 #include "serf.h"
19 #include "serf_bucket_util.h"
20
21
22 typedef struct {
23     serf_bucket_t *stream;
24     apr_size_t remaining;
25 } limit_context_t;
26
27
28 SERF_DECLARE(serf_bucket_t *) serf_bucket_limit_create(
29     serf_bucket_t *stream, apr_size_t len, serf_bucket_alloc_t *allocator)
30 {
31     limit_context_t *ctx;
32
33     ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
34     ctx->stream = stream;
35     ctx->remaining = len;
36
37     return serf_bucket_create(&serf_bucket_type_limit, allocator, ctx);
38 }
39
40 static apr_status_t serf_limit_read(serf_bucket_t *bucket,
41                                     apr_size_t requested,
42                                     const char **data, apr_size_t *len)
43 {
44     limit_context_t *ctx = bucket->data;
45     apr_status_t status;
46
47     if (!ctx->remaining) {
48         *len = 0;
49         return APR_EOF;
50     }
51
52     if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining)
53         requested = ctx->remaining;
54
55     status = serf_bucket_read(ctx->stream, requested, data, len);
56
57     if (!SERF_BUCKET_READ_ERROR(status)) {
58         ctx->remaining -= *len;
59     }
60
61     /* If we have met our limit and don't have a status, return EOF. */
62     if (!ctx->remaining && !status) {
63         status = APR_EOF;
64     }
65
66     return status;
67 }
68
69 static apr_status_t serf_limit_readline(serf_bucket_t *bucket,
70                                          int acceptable, int *found,
71                                          const char **data, apr_size_t *len)
72 {
73     limit_context_t *ctx = bucket->data;
74     apr_status_t status;
75
76     if (!ctx->remaining) {
77         *len = 0;
78         return APR_EOF;
79     }
80
81     status = serf_bucket_readline(ctx->stream, acceptable, found, data, len);
82
83     if (!SERF_BUCKET_READ_ERROR(status)) {
84         ctx->remaining -= *len;
85     }
86
87     /* If we have met our limit and don't have a status, return EOF. */
88     if (!ctx->remaining && !status) {
89         status = APR_EOF;
90     }
91
92     return status;
93 }
94
95 static apr_status_t serf_limit_peek(serf_bucket_t *bucket,
96                                      const char **data,
97                                      apr_size_t *len)
98 {
99     limit_context_t *ctx = bucket->data;
100
101     return serf_bucket_peek(ctx->stream, data, len);
102 }
103
104 static void serf_limit_destroy(serf_bucket_t *bucket)
105 {
106     limit_context_t *ctx = bucket->data;
107
108     serf_bucket_destroy(ctx->stream);
109
110     serf_default_destroy_and_data(bucket);
111 }
112
113 SERF_DECLARE_DATA const serf_bucket_type_t serf_bucket_type_limit = {
114     "LIMIT",
115     serf_limit_read,
116     serf_limit_readline,
117     serf_default_read_iovec,
118     serf_default_read_for_sendfile,
119     serf_default_read_bucket,
120     serf_limit_peek,
121     serf_limit_destroy,
122 };