ys2-intro/loader/tools/exomizer-3.1/src/buf.c
2025-11-13 19:07:39 +03:00

408 lines
8.9 KiB
C

/*
* Copyright (c) 2002 2005 Magnus Lind.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software, alter it and re-
* distribute it freely for any non-commercial, non-profit purpose subject to
* the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any distribution.
*
* 4. The names of this software and/or it's copyright holders may not be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "buf.h"
void buf_init(struct buf *b)
{
b->data = NULL;
b->size = 0;
b->capacity = 0;
}
void buf_free(struct buf *b)
{
if (b->capacity == -1)
{
fprintf(stderr, "error, can't free a buf view\n");
exit(1);
}
if (b->data != NULL)
{
free(b->data);
b->data = NULL;
}
b->size = 0;
b->capacity = 0;
}
void buf_new(struct buf **bp)
{
struct buf *b;
b = malloc(sizeof(struct buf));
if (b == NULL)
{
fprintf(stderr, "error, can't allocate memory\n");
exit(1);
}
b->data = NULL;
b->size = 0;
b->capacity = 0;
*bp = b;
}
void buf_delete(struct buf **bp)
{
struct buf *b;
b = *bp;
buf_free(b);
free(b);
b = NULL;
*bp = b;
}
int buf_size(const struct buf *b)
{
return b->size;
}
int buf_capacity(const struct buf *b)
{
return b->capacity;
}
void *buf_data(const struct buf *b)
{
return b->data;
}
void *buf_reserve(struct buf *b, int new_capacity)
{
int capacity = b->capacity;
if (capacity == -1)
{
fprintf(stderr, "error, can't reserve capacity for a buf view\n");
exit(1);
}
if (capacity == 0)
{
capacity = 1;
}
while (capacity < new_capacity)
{
capacity <<= 1;
}
if (capacity > b->capacity)
{
b->data = realloc(b->data, capacity);
if (b->data == NULL)
{
fprintf(stderr, "error, can't reallocate memory\n");
exit(1);
}
b->capacity = capacity;
}
return b->data;
}
void buf_clear(struct buf *b)
{
buf_replace(b, 0, b->size, NULL, 0);
}
void buf_remove(struct buf *b, int b_off, int b_n)
{
buf_replace(b, b_off, b_n, NULL, 0);
}
void *buf_insert(struct buf *b, int b_off, const void *m, int m_n)
{
return buf_replace(b, b_off, 0, m, m_n);
}
void *buf_append(struct buf *b, const void *m, int m_n)
{
return buf_replace(b, b->size, 0, m, m_n);
}
void buf_append_char(struct buf *b, char c)
{
buf_replace(b, b->size, 0, &c, 1);
}
void buf_append_str(struct buf *b, const char *str)
{
buf_replace(b, b->size, 0, str, strlen(str));
}
void *buf_replace(struct buf *b, int b_off, int b_n, const void *m, int m_n)
{
int new_size;
int rest_off;
int rest_n;
if (b->capacity == -1)
{
fprintf(stderr, "error, can't modify a buf view\n");
exit(1);
}
if (b_off < 0)
{
b_off += b->size + 1;
}
if (b_n == -1)
{
b_n = b->size - b_off;
}
if(b_off < 0 || b_off > b->size)
{
fprintf(stderr, "error, b_off %d must be within [0 - %d].\n",
b_off, b->size);
exit(1);
}
if(b_n < 0 || b_n > b->size - b_off)
{
fprintf(stderr,
"error, b_n %d must be within [0 and %d] for b_off %d.\n",
b_n, b->size - b_off, b_off);
exit(1);
}
if (m_n < 0)
{
fprintf(stderr, "error, m_n %d must be >= 0.\n", m_n);
exit(1);
}
new_size = b->size - b_n + m_n;
if (new_size > b->capacity)
{
buf_reserve(b, new_size);
}
rest_off = b_off + b_n;
rest_n = b->size - rest_off;
if (rest_n > 0)
{
memmove((char*)b->data + b_off + m_n,
(char*)b->data + rest_off, rest_n);
}
if (m_n > 0)
{
if (m != NULL)
{
memcpy((char*)b->data + b_off, m, m_n);
}
}
b->size = new_size;
return (char*)b->data + b_off;
}
static void fskip(FILE *f, int off)
{
int skip, remaining;
for (remaining = off; remaining > 0; remaining -= skip)
{
char buf[2048];
if (remaining == 0)
{
/* done */
break;
}
skip = remaining < 2048 ? remaining : 2048;
if (fread(buf, 1, skip, f) != skip)
{
if (feof(f))
{
fprintf(stderr,
"Error: EOF occured while skipping %d bytes.\n",
off);
}
else
{
fprintf(stderr,
"Error: Error occured while skipping %d bytes.\n",
off);
}
exit(-1);
}
}
}
void *buf_freplace(struct buf *b, int b_off, int b_n,
FILE *f, int f_off, int f_n)
{
char buf[2048];
int read;
int len;
int pos;
if (f == NULL)
{
fprintf(stderr, "Error: f must not be NULL.\n");
exit(-1);
}
if (b->capacity == -1)
{
fprintf(stderr, "error, can't modify a buf view\n");
exit(1);
}
if (f_off < 0)
{
int f_size;
if(fseek(f, 0, SEEK_END))
{
fprintf(stderr, "Error: can't seek to EOF in file.\n");
exit(-1);
}
f_size = ftell(f);
if(fseek(f, 0, SEEK_SET))
{
fprintf(stderr, "Error: can't seek to start in file.\n");
exit(-1);
}
if (f_off < 0)
{
f_off += f_size + 1;
}
if (f_n == -1)
{
f_n = f_size - f_off;
}
if(f_off < 0 || f_off > f_size)
{
fprintf(stderr, "Error, f_off %d must be within [0 - %d].\n",
f_off, f_size);
exit(1);
}
if (f_n < 0 || f_n > f_size - f_off)
{
fprintf(stderr,
"Error, f_n %d must be within [0 and %d] for f_off %d.\n",
f_n, f_size - f_off, f_off);
exit(1);
}
}
/* skip to f_off */
fskip(f, f_off);
if (ferror(f))
{
/* An error occured. */
fprintf(stderr, "Error, failed to skip %d bytes in file.\n", f_off);
exit(-1);
}
len = (f_n == -1 || f_n > 2048) ? 2048 : f_n;
pos = b_off;
while ((read = fread(buf, 1, len, f)) == len)
{
buf_replace(b, pos, b_n, buf, read);
b_n = 0;
pos += len;
if (f_n != -1)
{
f_n -= len;
len = f_n > 2048 ? 2048 : f_n;
}
}
if (ferror(f))
{
/* A read error occured. */
fprintf(stderr, "Error, failed to read from file.\n");
}
if (read > 0)
{
buf_replace(b, pos, b_n, buf, read);
}
return (char*)b->data + pos;
}
const struct buf *buf_view(struct buf *v,
const struct buf *b, int b_off, int b_n)
{
if (b_off < 0)
{
b_off += b->size + 1;
}
if (b_n == -1)
{
b_n = b->size - b_off;
}
if(b_off < 0 || b_off > b->size)
{
fprintf(stderr, "error, b_off %d must be within [0 - %d].\n",
b_off, b->size);
exit(1);
}
if(b_n < 0 || b_n > b->size - b_off)
{
fprintf(stderr, "error, b_n %d must be within [0 - %d].\n",
b_n, b->size - b_off);
exit(1);
}
if (b->data != NULL)
{
v->data = (char*)b->data + b_off;
}
else
{
v->data = NULL;
}
v->size = b_n;
v->capacity = -1;
return v;
}
void buf_printf(struct buf *b, const char *format, ...)
{
int pos;
int printed;
va_list args;
if (b->capacity == -1)
{
fprintf(stderr, "error, can't printf to a buf view\n");
exit(1);
}
pos = b->size;
va_start(args, format);
printed = vsnprintf((char*)buf_data(b) + pos, b->capacity - pos,
format, args);
va_end(args);
if (printed >= b->capacity - pos)
{
va_list args2;
buf_reserve(b, pos + printed + 1);
va_start(args2, format);
printed = vsnprintf((char*)buf_data(b) + pos, b->capacity - pos,
format, args2);
va_end(args2);
}
b->size += printed;
}