1/* ==================================================================== 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 * ==================================================================== 19 */ 20 21#include <apr_pools.h> 22 23#include "serf.h" 24#include "serf_bucket_util.h" 25 26 27typedef struct { 28 const char *original; 29 const char *current; 30 apr_size_t remaining; 31 32 serf_simple_freefunc_t freefunc; 33 void *baton; 34 35} simple_context_t; 36 37 38static void free_copied_data(void *baton, const char *data) 39{ 40 serf_bucket_mem_free(baton, (char*)data); 41} 42 43serf_bucket_t *serf_bucket_simple_create( 44 const char *data, 45 apr_size_t len, 46 serf_simple_freefunc_t freefunc, 47 void *freefunc_baton, 48 serf_bucket_alloc_t *allocator) 49{ 50 simple_context_t *ctx; 51 52 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 53 ctx->original = ctx->current = data; 54 ctx->remaining = len; 55 ctx->freefunc = freefunc; 56 ctx->baton = freefunc_baton; 57 58 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx); 59} 60 61serf_bucket_t *serf_bucket_simple_copy_create( 62 const char *data, apr_size_t len, 63 serf_bucket_alloc_t *allocator) 64{ 65 simple_context_t *ctx; 66 67 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 68 69 ctx->original = ctx->current = serf_bucket_mem_alloc(allocator, len); 70 memcpy((char*)ctx->original, data, len); 71 72 ctx->remaining = len; 73 ctx->freefunc = free_copied_data; 74 ctx->baton = allocator; 75 76 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx); 77} 78 79serf_bucket_t *serf_bucket_simple_own_create( 80 const char *data, apr_size_t len, 81 serf_bucket_alloc_t *allocator) 82{ 83 simple_context_t *ctx; 84 85 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 86 87 ctx->original = ctx->current = data; 88 89 ctx->remaining = len; 90 ctx->freefunc = free_copied_data; 91 ctx->baton = allocator; 92 93 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx); 94} 95 96static apr_status_t serf_simple_read(serf_bucket_t *bucket, 97 apr_size_t requested, 98 const char **data, apr_size_t *len) 99{ 100 simple_context_t *ctx = bucket->data; 101 102 if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining) 103 requested = ctx->remaining; 104 105 *data = ctx->current; 106 *len = requested; 107 108 ctx->current += requested; 109 ctx->remaining -= requested; 110 111 return ctx->remaining ? APR_SUCCESS : APR_EOF; 112} 113 114static apr_status_t serf_simple_readline(serf_bucket_t *bucket, 115 int acceptable, int *found, 116 const char **data, apr_size_t *len) 117{ 118 simple_context_t *ctx = bucket->data; 119 120 /* Returned data will be from current position. */ 121 *data = ctx->current; 122 serf_util_readline(&ctx->current, &ctx->remaining, acceptable, found); 123 124 /* See how much ctx->current moved forward. */ 125 *len = ctx->current - *data; 126 127 return ctx->remaining ? APR_SUCCESS : APR_EOF; 128} 129 130static apr_status_t serf_simple_peek(serf_bucket_t *bucket, 131 const char **data, 132 apr_size_t *len) 133{ 134 simple_context_t *ctx = bucket->data; 135 136 /* return whatever we have left */ 137 *data = ctx->current; 138 *len = ctx->remaining; 139 140 /* we returned everything this bucket will ever hold */ 141 return APR_EOF; 142} 143 144static void serf_simple_destroy(serf_bucket_t *bucket) 145{ 146 simple_context_t *ctx = bucket->data; 147 148 if (ctx->freefunc) 149 (*ctx->freefunc)(ctx->baton, ctx->original); 150 151 serf_default_destroy_and_data(bucket); 152} 153 154 155const serf_bucket_type_t serf_bucket_type_simple = { 156 "SIMPLE", 157 serf_simple_read, 158 serf_simple_readline, 159 serf_default_read_iovec, 160 serf_default_read_for_sendfile, 161 serf_default_read_bucket, 162 serf_simple_peek, 163 serf_simple_destroy, 164}; 165