1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_buckets.h" 18 19APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_copy(apr_bucket *a, 20 apr_bucket **b) 21{ 22 *b = apr_bucket_alloc(sizeof(**b), a->list); /* XXX: check for failure? */ 23 **b = *a; 24 25 return APR_SUCCESS; 26} 27 28APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_split(apr_bucket *a, 29 apr_size_t point) 30{ 31 apr_bucket *b; 32 33 if (point > a->length) { 34 return APR_EINVAL; 35 } 36 37 apr_bucket_simple_copy(a, &b); 38 39 a->length = point; 40 b->length -= point; 41 b->start += point; 42 43 APR_BUCKET_INSERT_AFTER(a, b); 44 45 return APR_SUCCESS; 46} 47 48static apr_status_t simple_bucket_read(apr_bucket *b, const char **str, 49 apr_size_t *len, apr_read_type_e block) 50{ 51 *str = (char *)b->data + b->start; 52 *len = b->length; 53 return APR_SUCCESS; 54} 55 56APU_DECLARE(apr_bucket *) apr_bucket_immortal_make(apr_bucket *b, 57 const char *buf, 58 apr_size_t length) 59{ 60 b->data = (char *)buf; 61 b->length = length; 62 b->start = 0; 63 b->type = &apr_bucket_type_immortal; 64 65 return b; 66} 67 68APU_DECLARE(apr_bucket *) apr_bucket_immortal_create(const char *buf, 69 apr_size_t length, 70 apr_bucket_alloc_t *list) 71{ 72 apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); 73 74 APR_BUCKET_INIT(b); 75 b->free = apr_bucket_free; 76 b->list = list; 77 return apr_bucket_immortal_make(b, buf, length); 78} 79 80/* 81 * XXX: This function could do with some tweaking to reduce memory 82 * usage in various cases, e.g. share buffers in the heap between all 83 * the buckets that are set aside, or even spool set-aside data to 84 * disk if it gets too voluminous (but if it does then that's probably 85 * a bug elsewhere). There should probably be a apr_brigade_setaside() 86 * function that co-ordinates the action of all the bucket setaside 87 * functions to improve memory efficiency. 88 */ 89static apr_status_t transient_bucket_setaside(apr_bucket *b, apr_pool_t *pool) 90{ 91 b = apr_bucket_heap_make(b, (char *)b->data + b->start, b->length, NULL); 92 if (b == NULL) { 93 return APR_ENOMEM; 94 } 95 return APR_SUCCESS; 96} 97 98APU_DECLARE(apr_bucket *) apr_bucket_transient_make(apr_bucket *b, 99 const char *buf, 100 apr_size_t length) 101{ 102 b->data = (char *)buf; 103 b->length = length; 104 b->start = 0; 105 b->type = &apr_bucket_type_transient; 106 return b; 107} 108 109APU_DECLARE(apr_bucket *) apr_bucket_transient_create(const char *buf, 110 apr_size_t length, 111 apr_bucket_alloc_t *list) 112{ 113 apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); 114 115 APR_BUCKET_INIT(b); 116 b->free = apr_bucket_free; 117 b->list = list; 118 return apr_bucket_transient_make(b, buf, length); 119} 120 121const apr_bucket_type_t apr_bucket_type_immortal = { 122 "IMMORTAL", 5, APR_BUCKET_DATA, 123 apr_bucket_destroy_noop, 124 simple_bucket_read, 125 apr_bucket_setaside_noop, 126 apr_bucket_simple_split, 127 apr_bucket_simple_copy 128}; 129 130APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_transient = { 131 "TRANSIENT", 5, APR_BUCKET_DATA, 132 apr_bucket_destroy_noop, 133 simple_bucket_read, 134 transient_bucket_setaside, 135 apr_bucket_simple_split, 136 apr_bucket_simple_copy 137}; 138