blob: 2ee0a81375f35ed5a129084520a1ef8c86408a48 [file] [log] [blame]
/*
* Copyright (C) 2003, 2004, 2005, 2015 Filip Pizlo. 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.
*
* THIS SOFTWARE IS PROVIDED BY FILIP PIZLO ``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 FILIP PIZLO 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 "tsf_internal.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
tsf_bool_t tsf_fd_writer(void *arg, const void *data, uint32_t len) {
uint8_t *cur = (uint8_t*)data;
int fd = *((int*)arg);
while (len) {
int res = write(fd, cur, len);
if (res < 0) {
if (errno == EINTR) {
continue;
}
tsf_set_errno("Calling write() in tsf_fd_writer()");
return tsf_false;
}
cur += res;
len -= res;
}
return tsf_true;
}
tsf_bool_t tsf_fd_reader(void *arg, void *data, uint32_t len) {
uint8_t *cur=data;
int fd=*((int*)arg);
while (len) {
int res=read(fd,cur,len);
if (res<0) {
if (errno==EINTR) {
continue;
}
tsf_set_errno("Calling read() in tsf_fd_reader()");
return tsf_false;
}
if (res==0) {
tsf_set_error((void*)cur==data?
TSF_E_UNEXPECTED_EOF:TSF_E_ERRONEOUS_EOF,
"Calling read() in tsf_fd_reader()");
return tsf_false;
}
cur+=res;
len-=res;
}
return tsf_true;
}
int32_t tsf_fd_partial_reader(void *arg,
void *data,
uint32_t len) {
int fd=*((int*)arg);
for (;;) {
int res=read(fd,data,len);
if (res<0) {
if (errno==EINTR) {
continue;
}
tsf_set_errno("Calling read() in tsf_fd_partial_reader()");
return -1;
}
if (res==0) {
tsf_set_error(TSF_E_UNEXPECTED_EOF,
"Calling read() in tsf_fd_partial_reader()");
return -1;
}
return res;
}
}
tsf_bool_t tsf_comparing_writer(void *arg,
const void *buf,
uint32_t len) {
tsf_comparing_writer_t *self=arg;
void *my_buf=malloc(len);
if (my_buf==NULL) {
tsf_set_errno("Could not allocate temporary buffer");
return tsf_false;
}
if (self->reader(self->arg,my_buf,len)) {
int res=memcmp(buf,my_buf,len);
free(my_buf);
if (res==0) {
return tsf_true;
} else {
tsf_set_error(TSF_E_COMPARE_FAIL,NULL);
return tsf_false;
}
} else {
free(my_buf);
return tsf_false;
}
}
tsf_bool_t tsf_hashing_writer(void *arg,
const void *_buf,
uint32_t len) {
uint8_t *buf = (uint8_t*)_buf;
uint32_t *hash = arg;
uint32_t h = *hash, g;
/* this is the ELF hash, at least according to my hashtable
library. */
while (len --> 0) {
h = (h << 4) + buf[len];
g = h & 0xf0000000;
if (g) {
h ^= g >> 24;
}
h &= ~g;
}
*hash = h;
return tsf_true;
}
tsf_bool_t tsf_size_calc_writer(void *arg,
const void *buf,
uint32_t len) {
uint32_t *total_len=arg;
(*total_len)+=len;
return tsf_true;
}
tsf_bool_t tsf_size_aware_reader(void *arg,
void *buf,
uint32_t len) {
tsf_size_aware_rdr_t *self=arg;
if (self->limit<len) {
tsf_set_error(TSF_E_PARSE_ERROR,
"Overran size limit for %s",self->name);
return tsf_false;
}
if (!self->reader(self->arg,buf,len)) {
return tsf_false;
}
self->limit-=len;
return tsf_true;
}
tsf_bool_t tsf_buffer_only_writer(void *arg,
const void *buf,
uint32_t len) {
uint8_t **cur = arg;
memcpy(*cur, buf, len);
(*cur) += len;
return tsf_true;
}
tsf_bool_t tsf_resizable_buffer_writer(void *arg,
const void *buf,
uint32_t len) {
tsf_resizable_buffer_t *resizable = arg;
if (resizable->end - resizable->cur < len) {
size_t old_size;
size_t new_size;
uint8_t *new_base;
old_size = resizable->end - resizable->base;
new_size = (old_size + len) << 1;
if (resizable->base == NULL) {
new_base = malloc(new_size);
} else {
new_base = realloc(resizable->base, new_size);
}
if (new_base == NULL) {
tsf_set_errno("Could not malloc resizable buffer");
return tsf_false;
}
resizable->end = new_base + new_size;
resizable->cur = new_base + (resizable->cur - resizable->base);
resizable->base = new_base;
}
memcpy(resizable->cur, buf, len);
resizable->cur += len;
return tsf_true;
}
tsf_bool_t tsf_buffer_only_reader(void *arg,
void *buf,
uint32_t len) {
tsf_light_buffer_t *state=arg;
if (state->cur == state->end) {
tsf_set_error(TSF_E_UNEXPECTED_EOF,
"Buffer is empty");
return tsf_false;
}
if (state->cur+len > state->end) {
tsf_set_error(TSF_E_ERRONEOUS_EOF,
"Buffer does not have requested data");
return tsf_false;
}
memcpy(buf,state->cur,len);
state->cur+=len;
return tsf_true;
}