File: poolbuf.c

package info (click to toggle)
libapache-mod-jk 1%3A1.2.18-3
  • links: PTS
  • area: main
  • in suites: etch-m68k
  • size: 5,004 kB
  • ctags: 2,664
  • sloc: ansic: 20,014; sh: 8,643; xml: 7,304; perl: 617; makefile: 321; awk: 59
file content (146 lines) | stat: -rw-r--r-- 4,466 bytes parent folder | download | duplicates (2)
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
/*
 *  Copyright 1999-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/***************************************************************************
 * Description: ISAPI plugin for Tomcat                                    *
 * Author:      Andy Armstrong <andy@tagish.com>                           *
 * Version:     $Revision: 299830 $                                           *
 ***************************************************************************/

#include "poolbuf.h"

/* Macro to return the address of the first byte in a poolbuf__chunk on
 * the understanding that the buffer follows the structure in memory.
 */
#define poolbuf__buf(chnk) \
	((char *) ((poolbuf__chunk *) chnk + 1))

void poolbuf_init(poolbuf * pb, jk_pool_t *p)
{
    pb->p = p;
    pb->head = pb->current = NULL;
    pb->readPos = pb->writePos = 0;
    pb->avail = 0;
    pb->state = WRITE;
}

/* Write bytes to the buffer returning the number of bytes successfully
 * written. Can't be called again once poolbuf_read() has been called.
 */
size_t poolbuf_write(poolbuf * pb, const void *buf, size_t size)
{
    const char *cbuf = (const char *)buf;
    size_t left = size;

    if (READ == pb->state)
        return 0;

    /* first work out what we can write into the current buffer */
    if (pb->current != NULL && pb->writePos < pb->current->size) {
        char *chbuf = poolbuf__buf(pb->current) + pb->writePos;
        size_t sz = pb->current->size - pb->writePos;
        if (sz > left)
            sz = left;
        memcpy(chbuf, cbuf, sz);
        pb->writePos += sz;
        pb->avail += sz;
        cbuf += sz;
        left -= sz;
    }

    /* something left that we couldn't fit in the last chunk */
    if (left > 0) {
        poolbuf__chunk *chnk;
        size_t sz = size;

        if (sz < poolbuf__MINCHUNK)
            sz = poolbuf__MINCHUNK;
        if (NULL == pb->p
            || NULL == (chnk =
                        jk_pool_alloc(pb->p, sz + sizeof(poolbuf__chunk))))
            return size - left;

        chnk->next = NULL;
        chnk->size = sz;
        if (NULL == pb->head)
            pb->head = chnk;
        if (NULL != pb->current)
            pb->current->next = chnk;
        pb->current = chnk;
        memcpy(poolbuf__buf(chnk), cbuf, left);
        pb->avail += left;
        pb->writePos = left;
    }

    return size;
}

/* Read bytes from the buffer returning the number of bytes read (which
 * will be less than desired when the end of the buffer is reached). Once
 * poolbuf_read() has been called poolbuf_write() may not be called again.
 */
size_t poolbuf_read(poolbuf * pb, void *buf, size_t size)
{
    char *cbuf = (char *)buf;
    size_t nread = 0;

    if (WRITE == pb->state) {
        /* Move to read mode. Once we've done this subsequent
         * writes are not allowed.
         */
        pb->current = pb->head;
        pb->readPos = 0;
        pb->state = READ;
    }

    while (size > 0 && pb->avail > 0) {
        size_t sz = pb->current->size - pb->readPos;
        if (sz > pb->avail)
            sz = pb->avail;
        if (sz > size)
            sz = size;
        memcpy(cbuf, poolbuf__buf(pb->current) + pb->readPos, sz);
        pb->readPos += sz;
        if (pb->readPos == pb->current->size) {
            pb->current = pb->current->next;
            pb->readPos = 0;
        }
        pb->avail -= sz;
        nread += sz;
    }

    return nread;
}

/* Find out how many bytes are available for reading.
 */
size_t poolbuf_available(poolbuf * pb)
{
    return pb->avail;
}

/* Destroy the buffer. This doesn't actually free any memory
 * because the jk_pool functions don't support freeing individual
 * chunks, but it does recycle the buffer for subsequent use.
 */
void poolbuf_destroy(poolbuf * pb)
{
    pb->p = NULL;
    pb->head = pb->current = NULL;
    pb->readPos = pb->writePos = 0;
    pb->avail = 0;
    pb->state = WRITE;
}