<commit_before>/*
 * libdivecomputer
 *
 * Copyright (C) 2009 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA
 */

#include <stdlib.h> // malloc, realloc, free
#include <string.h> // memcpy, memmove

#include "buffer.h"

struct dc_buffer_t {
	unsigned char *data;
	size_t capacity, offset, size;
};

dc_buffer_t *
dc_buffer_new (size_t capacity)
{
	dc_buffer_t *buffer = (dc_buffer_t *) malloc (sizeof (dc_buffer_t));
	if (buffer == NULL)
		return NULL;

	if (capacity) {
		buffer->data = (unsigned char *) malloc (capacity);
		if (buffer->data == NULL) {
			free (buffer);
			return NULL;
		}
	} else {
		buffer->data = NULL;
	}

	buffer->capacity = capacity;
	buffer->offset = 0;
	buffer->size = 0;

	return buffer;
}


void
dc_buffer_free (dc_buffer_t *buffer)
{
	if (buffer == NULL)
		return;

	if (buffer->data)
		free (buffer->data);

	free (buffer);
}


int
dc_buffer_clear (dc_buffer_t *buffer)
{
	if (buffer == NULL)
		return 0;

	buffer->offset = 0;
	buffer->size = 0;

	return 1;
}


static int
dc_buffer_expand_append (dc_buffer_t *buffer, size_t n)
{
	if (n > buffer->capacity - buffer->offset) {
		if (n > buffer->capacity) {
			size_t capacity = n;

			unsigned char *data = (unsigned char *) malloc (capacity);
			if (data == NULL)
				return 0;

			if (buffer->size)
				memcpy (data, buffer->data + buffer->offset, buffer->size);

			free (buffer->data);

			buffer->data = data;
			buffer->capacity = capacity;
			buffer->offset = 0;
		} else {
			if (buffer->size)
				memmove (buffer->data, buffer->data + buffer->offset, buffer->size);

			buffer->offset = 0;
		}
	}

	return 1;
}


static int
dc_buffer_expand_prepend (dc_buffer_t *buffer, size_t n)
{
	size_t available = buffer->capacity - buffer->size;

	if (n > buffer->offset + buffer->size) {
		if (n > buffer->capacity) {
			size_t capacity = n;

			unsigned char *data = (unsigned char *) malloc (capacity);
			if (data == NULL)
				return 0;

			if (buffer->size)
				memcpy (data + capacity - buffer->size, buffer->data + buffer->offset, buffer->size);

			free (buffer->data);

			buffer->data = data;
			buffer->capacity = capacity;
			buffer->offset = capacity - buffer->size;<commit_msg>Implement a more efficient buffer growing strategy.<commit_after>/*
 * libdivecomputer
 *
 * Copyright (C) 2009 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA
 */

#include <stdlib.h> // malloc, realloc, free
#include <string.h> // memcpy, memmove

#include "buffer.h"

struct dc_buffer_t {
	unsigned char *data;
	size_t capacity, offset, size;
};

dc_buffer_t *
dc_buffer_new (size_t capacity)
{
	dc_buffer_t *buffer = (dc_buffer_t *) malloc (sizeof (dc_buffer_t));
	if (buffer == NULL)
		return NULL;

	if (capacity) {
		buffer->data = (unsigned char *) malloc (capacity);
		if (buffer->data == NULL) {
			free (buffer);
			return NULL;
		}
	} else {
		buffer->data = NULL;
	}

	buffer->capacity = capacity;
	buffer->offset = 0;
	buffer->size = 0;

	return buffer;
}


void
dc_buffer_free (dc_buffer_t *buffer)
{
	if (buffer == NULL)
		return;

	if (buffer->data)
		free (buffer->data);

	free (buffer);
}


int
dc_buffer_clear (dc_buffer_t *buffer)
{
	if (buffer == NULL)
		return 0;

	buffer->offset = 0;
	buffer->size = 0;

	return 1;
}


static size_t
dc_buffer_expand_calc (dc_buffer_t *buffer, size_t n)
{
	size_t oldsize = buffer->capacity;
	size_t newsize = (oldsize ? oldsize : n);
	while (newsize < n)
		newsize *= 2;

	return newsize;
}


static int
dc_buffer_expand_append (dc_buffer_t *buffer, size_t n)
{
	if (n > buffer->capacity - buffer->offset) {
		if (n > buffer->capacity) {
			size_t capacity = dc_buffer_expand_calc (buffer, n);

			unsigned char *data = (unsigned char *) malloc (capacity);
			if (data == NULL)
				return 0;

			if (buffer->size)
				memcpy (data, buffer->data + buffer->offset, buffer->size);

			free (buffer->data);

			buffer->data = data;
			buffer->capacity = capacity;
			buffer->offset = 0;
		} else {
			if (buffer->size)
				memmove (buffer->data, buffer->data + buffer->offset, buffer->size);

			buffer->offset = 0;
		}
	}

	return 1;
}


static int
dc_buffer_expand_prepend (dc_buffer_t *buffer, size_t n)
{
	size_t available = buffer->capacity - buffer->size;

	if (n > buffer->offset + buffer->size) {
		if (n > buffer->capacity) {
			size_t capacity = dc_buffer_expand_calc (buffer, n);

			unsigned char *data = (unsigned char *) malloc (capacity);
			if (data == NULL)
				return 0;

			if (buffer->size)
				memcpy (data + capacity - buffer->size, buffer->data + buffer->offset, buffer->size);

			free (buffer->data);

			buffer->data = data;
			buffer->capacity = capacity;
			buffer->offset = capacity - buffer->size;
{'fraction_non_alphanumeric': 0.12368073878627968, 'fraction_numerical': 0.009399736147757257, 'mean_word_length': 3.5126488095238093, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 102, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4762064', 'n_tokens_mistral': 2182, 'n_tokens_neox': 1937, 'n_words': 667}