Goto sanos source index
//
// hbuf.c
//
// HTTP buffer management
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <os.h>
#include <string.h>
#include <httpd.h>
int buffer_size(struct httpd_buffer *buf) {
return buf->end - buf->start;
}
int buffer_capacity(struct httpd_buffer *buf) {
return buf->ceil - buf->floor;
}
int buffer_left(struct httpd_buffer *buf) {
return buf->ceil - buf->end;
}
int buffer_empty(struct httpd_buffer *buf) {
return buf->start == buf->end;
}
int buffer_full(struct httpd_buffer *buf) {
return buf->end == buf->ceil;
}
int allocate_buffer(struct httpd_buffer *buf, int size) {
if (size == 0) {
buf->floor = buf->ceil = NULL;
buf->start = buf->end = NULL;
} else {
buf->floor = (char *) malloc(size);
if (!buf->floor) return -1;
buf->ceil = buf->floor + size;
buf->start = buf->end = buf->floor;
}
return 0;
}
void free_buffer(struct httpd_buffer *buf) {
if (buf->floor) free(buf->floor);
buf->floor = buf->ceil = buf->start = buf->end = NULL;
}
void clear_buffer(struct httpd_buffer *buf) {
buf->start = buf->end = buf->floor;
}
int expand_buffer(struct httpd_buffer *buf, int minfree) {
char *p;
int size;
int minsize;
if (buf->ceil - buf->end >= minfree) return 0;
size = buf->ceil - buf->floor;
minsize = buf->end + minfree - buf->floor;
while (size < minsize) {
if (size == 0) {
size = 1024;
} else {
size *= 2;
}
}
p = (char *) realloc(buf->floor, size);
if (!p) return -1;
buf->start += p - buf->floor;
buf->end += p - buf->floor;
buf->floor = p;
buf->ceil = p + size;
return 0;
}
char *bufgets(struct httpd_buffer *buf) {
char *start;
char *s;
s = start = buf->start;
while (s < buf->end) {
switch (*s) {
case '\n':
if (s[1] != ' ' && s[1] != '\t') {
if (s > start && s[-1] == ' ') {
s[-1] = 0;
} else {
s[0] = 0;
}
buf->start = s + 1;
return start;
} else {
*s++ = ' ';
}
break;
case '\r':
case '\t':
*s++ = ' ';
break;
default:
s++;
}
}
return NULL;
}
int bufncat(struct httpd_buffer *buf, char *data, int len) {
int rc;
rc = expand_buffer(buf, len);
if (rc < 0) return rc;
memcpy(buf->end, data, len);
buf->end += len;
return 0;
}
int bufcat(struct httpd_buffer *buf, char *data) {
if (!data) return 0;
return bufncat(buf, data, strlen(data));
}