forked from metin2/server
295 lines
6.5 KiB
C++
295 lines
6.5 KiB
C++
|
/*
|
|||
|
* Filename: buffer.c
|
|||
|
* Description: Buffer ó<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*
|
|||
|
* Author: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (aka. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>, Cronan)
|
|||
|
*/
|
|||
|
#define __LIBTHECORE__
|
|||
|
#include "stdafx.h"
|
|||
|
|
|||
|
static LPBUFFER normalized_buffer_pool[32] = { NULL, };
|
|||
|
|
|||
|
#define DEFAULT_POOL_SIZE 8192
|
|||
|
|
|||
|
// internal function forward
|
|||
|
void buffer_realloc(LPBUFFER& buffer, int length);
|
|||
|
|
|||
|
static int buffer_get_pool_index(int size) {
|
|||
|
int i;
|
|||
|
for (i = 0; i < 32; ++i) {
|
|||
|
if ((1 << i) >= size) {
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
return -1; // too big... not pooled
|
|||
|
}
|
|||
|
static int buffer_get_exac_pool_index(int size) {
|
|||
|
int i;
|
|||
|
for (i = 0; i < 32; ++i) {
|
|||
|
if ((1 << i) == size) {
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
return -1; // too big... not pooled
|
|||
|
}
|
|||
|
// <20><><EFBFBD><EFBFBD> buffer pool <20><><EFBFBD><EFBFBD>.
|
|||
|
static void buffer_pool_free ()
|
|||
|
{
|
|||
|
for (int i = 31; i >= 0; i--)
|
|||
|
{
|
|||
|
if (normalized_buffer_pool[i] != NULL)
|
|||
|
{
|
|||
|
LPBUFFER next;
|
|||
|
for (LPBUFFER p = normalized_buffer_pool[i]; p != NULL; p = next)
|
|||
|
{
|
|||
|
next = p->next;
|
|||
|
free(p->mem_data);
|
|||
|
free(p);
|
|||
|
}
|
|||
|
normalized_buffer_pool[i] = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// n<><6E><EFBFBD><EFBFBD> ū buffer pool <20>ϳ<EFBFBD><CFB3><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
|||
|
static bool buffer_larger_pool_free (int n)
|
|||
|
{
|
|||
|
for (int i = 31; i > n; i--)
|
|||
|
{
|
|||
|
if (normalized_buffer_pool[i] != NULL)
|
|||
|
{
|
|||
|
LPBUFFER buffer = normalized_buffer_pool[i];
|
|||
|
LPBUFFER next = buffer->next;
|
|||
|
free(buffer->mem_data);
|
|||
|
free(buffer);
|
|||
|
normalized_buffer_pool[i] = next;
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
bool safe_create(char** pdata, int number)
|
|||
|
{
|
|||
|
if (!((*pdata) = (char *) calloc (number, sizeof(char))))
|
|||
|
{
|
|||
|
sys_err("calloc failed [%d] %s", errno, strerror(errno));
|
|||
|
return false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LPBUFFER buffer_new(int size)
|
|||
|
{
|
|||
|
if (size < 0) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
LPBUFFER buffer = NULL;
|
|||
|
int pool_index = buffer_get_pool_index(size);
|
|||
|
if (pool_index >= 0) {
|
|||
|
BUFFER** buffer_pool = normalized_buffer_pool + pool_index;
|
|||
|
size = 1 << pool_index;
|
|||
|
|
|||
|
if (*buffer_pool) {
|
|||
|
buffer = *buffer_pool;
|
|||
|
*buffer_pool = buffer->next;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (buffer == NULL)
|
|||
|
{
|
|||
|
CREATE(buffer, BUFFER, 1);
|
|||
|
buffer->mem_size = size;
|
|||
|
// buffer_new<65><77><EFBFBD><EFBFBD> calloc failed<65><64> <20><><EFBFBD><EFBFBD> <20><EFBFBD><DFBB>Ͽ<EFBFBD>(<28><>Ű<EFBFBD><C5B0> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ӽſ<D3BD><C5BF><EFBFBD> <20>ַ<EFBFBD> <20><EFBFBD>),
|
|||
|
// calloc<6F><63> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>, buffer pool<6F><6C> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٽ<EFBFBD> <20>õ<EFBFBD><C3B5>Ѵ<EFBFBD>.
|
|||
|
if (!safe_create(&buffer->mem_data, size))
|
|||
|
{
|
|||
|
// <20>ʿ<EFBFBD><CABF><EFBFBD> buffer<65><72><EFBFBD><EFBFBD> ū buffer pool<6F><6C><EFBFBD><EFBFBD> <20>ϳ<EFBFBD><CFB3><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
|||
|
if (!buffer_larger_pool_free(pool_index))
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> pool<6F><6C> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
|||
|
buffer_pool_free();
|
|||
|
CREATE(buffer->mem_data, char, size);
|
|||
|
sys_err ("buffer pool free success.");
|
|||
|
}
|
|||
|
}
|
|||
|
assert(buffer != NULL);
|
|||
|
assert(buffer->mem_size == size);
|
|||
|
assert(buffer->mem_data != NULL);
|
|||
|
|
|||
|
buffer_reset(buffer);
|
|||
|
|
|||
|
return buffer;
|
|||
|
}
|
|||
|
|
|||
|
void buffer_delete(LPBUFFER buffer)
|
|||
|
{
|
|||
|
if (buffer == NULL) {
|
|||
|
return;
|
|||
|
}
|
|||
|
buffer_reset(buffer);
|
|||
|
|
|||
|
int size = buffer->mem_size;
|
|||
|
|
|||
|
int pool_index = buffer_get_exac_pool_index(size);
|
|||
|
if (pool_index >= 0) {
|
|||
|
BUFFER** buffer_pool = normalized_buffer_pool + pool_index;
|
|||
|
buffer->next = *buffer_pool;
|
|||
|
*buffer_pool = buffer;
|
|||
|
}
|
|||
|
else {
|
|||
|
free(buffer->mem_data);
|
|||
|
free(buffer);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DWORD buffer_size(LPBUFFER buffer)
|
|||
|
{
|
|||
|
return (buffer->length);
|
|||
|
}
|
|||
|
|
|||
|
void buffer_reset(LPBUFFER buffer)
|
|||
|
{
|
|||
|
buffer->read_point = buffer->mem_data;
|
|||
|
buffer->write_point = buffer->mem_data;
|
|||
|
buffer->write_point_pos = 0;
|
|||
|
buffer->length = 0;
|
|||
|
buffer->next = NULL;
|
|||
|
buffer->flag = 0;
|
|||
|
}
|
|||
|
|
|||
|
void buffer_write(LPBUFFER& buffer, const void *src, int length)
|
|||
|
{
|
|||
|
if (buffer->write_point_pos + length >= buffer->mem_size)
|
|||
|
buffer_realloc(buffer, buffer->mem_size + length + MIN(10240, length));
|
|||
|
|
|||
|
thecore_memcpy(buffer->write_point, src, length);
|
|||
|
buffer_write_proceed(buffer, length);
|
|||
|
}
|
|||
|
|
|||
|
void buffer_read(LPBUFFER buffer, void * buf, int bytes)
|
|||
|
{
|
|||
|
thecore_memcpy(buf, buffer->read_point, bytes);
|
|||
|
buffer_read_proceed(buffer, bytes);
|
|||
|
}
|
|||
|
|
|||
|
BYTE buffer_byte(LPBUFFER buffer)
|
|||
|
{
|
|||
|
BYTE val = *(BYTE *) buffer->read_point;
|
|||
|
buffer_read_proceed(buffer, sizeof(BYTE));
|
|||
|
return val;
|
|||
|
}
|
|||
|
|
|||
|
WORD buffer_word(LPBUFFER buffer)
|
|||
|
{
|
|||
|
WORD val = *(WORD *) buffer->read_point;
|
|||
|
buffer_read_proceed(buffer, sizeof(WORD));
|
|||
|
return val;
|
|||
|
}
|
|||
|
|
|||
|
DWORD buffer_dword(LPBUFFER buffer)
|
|||
|
{
|
|||
|
DWORD val = *(DWORD *) buffer->read_point;
|
|||
|
buffer_read_proceed(buffer, sizeof(DWORD));
|
|||
|
return val;
|
|||
|
}
|
|||
|
|
|||
|
const void * buffer_read_peek(LPBUFFER buffer)
|
|||
|
{
|
|||
|
return (const void *) buffer->read_point;
|
|||
|
}
|
|||
|
|
|||
|
void buffer_read_proceed(LPBUFFER buffer, int length)
|
|||
|
{
|
|||
|
if (length == 0)
|
|||
|
return;
|
|||
|
|
|||
|
if (length < 0)
|
|||
|
sys_err("buffer_proceed: length argument lower than zero (length: %d)", length);
|
|||
|
else if (length > buffer->length)
|
|||
|
{
|
|||
|
sys_err("buffer_proceed: length argument bigger than buffer (length: %d, buffer: %d)", length, buffer->length);
|
|||
|
length = buffer->length;
|
|||
|
}
|
|||
|
|
|||
|
// ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD>̰<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̺<EFBFBD><CCBA><EFBFBD> <20>۴ٸ<DBB4>, <20><><EFBFBD>۸<EFBFBD> <20><><EFBFBD>ܵξ<DCB5><CEBE><EFBFBD> <20>Ѵ<EFBFBD>.
|
|||
|
if (length < buffer->length)
|
|||
|
{
|
|||
|
// write_point <20><> pos <20><> <20>״<EFBFBD><D7B4><EFBFBD> <20>ΰ<EFBFBD> read_point <20><> <20><><EFBFBD><EFBFBD> <20><>Ų<EFBFBD><C5B2>.
|
|||
|
if (buffer->read_point + length - buffer->mem_data > buffer->mem_size)
|
|||
|
{
|
|||
|
sys_err("buffer_read_proceed: buffer overflow! length %d read_point %d", length, buffer->read_point - buffer->mem_data);
|
|||
|
abort();
|
|||
|
}
|
|||
|
|
|||
|
buffer->read_point += length;
|
|||
|
buffer->length -= length;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
buffer_reset(buffer);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void * buffer_write_peek(LPBUFFER buffer)
|
|||
|
{
|
|||
|
return (buffer->write_point);
|
|||
|
}
|
|||
|
|
|||
|
void buffer_write_proceed(LPBUFFER buffer, int length)
|
|||
|
{
|
|||
|
buffer->length += length;
|
|||
|
buffer->write_point += length;
|
|||
|
buffer->write_point_pos += length;
|
|||
|
}
|
|||
|
|
|||
|
int buffer_has_space(LPBUFFER buffer)
|
|||
|
{
|
|||
|
return (buffer->mem_size - buffer->write_point_pos);
|
|||
|
}
|
|||
|
|
|||
|
void buffer_adjust_size(LPBUFFER& buffer, int add_size)
|
|||
|
{
|
|||
|
if (buffer->mem_size >= buffer->write_point_pos + add_size)
|
|||
|
return;
|
|||
|
|
|||
|
sys_log(0, "buffer_adjust %d current %d/%d", add_size, buffer->length, buffer->mem_size);
|
|||
|
buffer_realloc(buffer, buffer->mem_size + add_size);
|
|||
|
}
|
|||
|
|
|||
|
void buffer_realloc(LPBUFFER& buffer, int length)
|
|||
|
{
|
|||
|
int i, read_point_pos;
|
|||
|
LPBUFFER temp;
|
|||
|
|
|||
|
assert(length >= 0 && "buffer_realloc: length is lower than zero");
|
|||
|
|
|||
|
if (buffer->mem_size >= length)
|
|||
|
return;
|
|||
|
|
|||
|
// i <20><> <20><><EFBFBD><EFBFBD> <20>Ҵ<EFBFBD><D2B4><EFBFBD> ũ<><C5A9><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ũ<EFBFBD><C5A9><EFBFBD><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|||
|
// <20><EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD> ũ<>⸦ <20><><EFBFBD>Ѵ<EFBFBD>.
|
|||
|
i = length - buffer->mem_size;
|
|||
|
|
|||
|
if (i <= 0)
|
|||
|
return;
|
|||
|
|
|||
|
temp = buffer_new (length);
|
|||
|
sys_log(0, "reallocating buffer to %d, current %d", temp->mem_size, buffer->mem_size);
|
|||
|
thecore_memcpy(temp->mem_data, buffer->mem_data, buffer->mem_size);
|
|||
|
|
|||
|
read_point_pos = buffer->read_point - buffer->mem_data;
|
|||
|
|
|||
|
// write_point <20><> read_point <20><> <20><> <20><><EFBFBD><EFBFBD> <20><>Ų<EFBFBD><C5B2>.
|
|||
|
temp->write_point = temp->mem_data + buffer->write_point_pos;
|
|||
|
temp->write_point_pos = buffer->write_point_pos;
|
|||
|
temp->read_point = temp->mem_data + read_point_pos;
|
|||
|
temp->flag = buffer->flag;
|
|||
|
temp->next = NULL;
|
|||
|
temp->length = buffer->length;
|
|||
|
|
|||
|
buffer_delete(buffer);
|
|||
|
buffer = temp;
|
|||
|
}
|