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 const char *original;
24 const char *current;
25 apr_size_t remaining;
26
27 serf_simple_freefunc_t freefunc;
28 void *baton;
29
30 } simple_context_t;
31
32
free_copied_data(void * baton,const char * data)33 static void free_copied_data(void *baton, const char *data)
34 {
35 serf_bucket_mem_free(baton, (char*)data);
36 }
37
serf_bucket_simple_create(const char * data,apr_size_t len,serf_simple_freefunc_t freefunc,void * freefunc_baton,serf_bucket_alloc_t * allocator)38 serf_bucket_t *serf_bucket_simple_create(
39 const char *data,
40 apr_size_t len,
41 serf_simple_freefunc_t freefunc,
42 void *freefunc_baton,
43 serf_bucket_alloc_t *allocator)
44 {
45 simple_context_t *ctx;
46
47 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
48 ctx->original = ctx->current = data;
49 ctx->remaining = len;
50 ctx->freefunc = freefunc;
51 ctx->baton = freefunc_baton;
52
53 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
54 }
55
serf_bucket_simple_copy_create(const char * data,apr_size_t len,serf_bucket_alloc_t * allocator)56 serf_bucket_t *serf_bucket_simple_copy_create(
57 const char *data, apr_size_t len,
58 serf_bucket_alloc_t *allocator)
59 {
60 simple_context_t *ctx;
61
62 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
63
64 ctx->original = ctx->current = serf_bucket_mem_alloc(allocator, len);
65 memcpy((char*)ctx->original, data, len);
66
67 ctx->remaining = len;
68 ctx->freefunc = free_copied_data;
69 ctx->baton = allocator;
70
71 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
72 }
73
serf_bucket_simple_own_create(const char * data,apr_size_t len,serf_bucket_alloc_t * allocator)74 serf_bucket_t *serf_bucket_simple_own_create(
75 const char *data, apr_size_t len,
76 serf_bucket_alloc_t *allocator)
77 {
78 simple_context_t *ctx;
79
80 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
81
82 ctx->original = ctx->current = data;
83
84 ctx->remaining = len;
85 ctx->freefunc = free_copied_data;
86 ctx->baton = allocator;
87
88 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
89 }
90
serf_simple_read(serf_bucket_t * bucket,apr_size_t requested,const char ** data,apr_size_t * len)91 static apr_status_t serf_simple_read(serf_bucket_t *bucket,
92 apr_size_t requested,
93 const char **data, apr_size_t *len)
94 {
95 simple_context_t *ctx = bucket->data;
96
97 if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining)
98 requested = ctx->remaining;
99
100 *data = ctx->current;
101 *len = requested;
102
103 ctx->current += requested;
104 ctx->remaining -= requested;
105
106 return ctx->remaining ? APR_SUCCESS : APR_EOF;
107 }
108
serf_simple_readline(serf_bucket_t * bucket,int acceptable,int * found,const char ** data,apr_size_t * len)109 static apr_status_t serf_simple_readline(serf_bucket_t *bucket,
110 int acceptable, int *found,
111 const char **data, apr_size_t *len)
112 {
113 simple_context_t *ctx = bucket->data;
114
115 /* Returned data will be from current position. */
116 *data = ctx->current;
117 serf_util_readline(&ctx->current, &ctx->remaining, acceptable, found);
118
119 /* See how much ctx->current moved forward. */
120 *len = ctx->current - *data;
121
122 return ctx->remaining ? APR_SUCCESS : APR_EOF;
123 }
124
serf_simple_peek(serf_bucket_t * bucket,const char ** data,apr_size_t * len)125 static apr_status_t serf_simple_peek(serf_bucket_t *bucket,
126 const char **data,
127 apr_size_t *len)
128 {
129 simple_context_t *ctx = bucket->data;
130
131 /* return whatever we have left */
132 *data = ctx->current;
133 *len = ctx->remaining;
134
135 /* we returned everything this bucket will ever hold */
136 return APR_EOF;
137 }
138
serf_simple_destroy(serf_bucket_t * bucket)139 static void serf_simple_destroy(serf_bucket_t *bucket)
140 {
141 simple_context_t *ctx = bucket->data;
142
143 if (ctx->freefunc)
144 (*ctx->freefunc)(ctx->baton, ctx->original);
145
146 serf_default_destroy_and_data(bucket);
147 }
148
149
150 const serf_bucket_type_t serf_bucket_type_simple = {
151 "SIMPLE",
152 serf_simple_read,
153 serf_simple_readline,
154 serf_default_read_iovec,
155 serf_default_read_for_sendfile,
156 serf_default_read_bucket,
157 serf_simple_peek,
158 serf_simple_destroy,
159 };
160