<commit_before>#line 2 "togo/io/object_buffer.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Object buffer interface.
@ingroup io_object_buffer
*/

#pragma once

#include <togo/config.hpp>
#include <togo/types.hpp>
#include <togo/error/assert.hpp>
#include <togo/memory/types.hpp>
#include <togo/collection/array.hpp>
#include <togo/io/io.hpp>
#include <togo/io/memory_stream.hpp>
#include <togo/io/object_buffer_type.hpp>

namespace togo {

/// Construct with allocator and initial capacity (in bytes).
template<class T, class S>
inline ObjectBuffer<T, S>::ObjectBuffer(
	Allocator& allocator,
	u32 const init_capacity
)
	: _stream(allocator, init_capacity)
	, _num_objects(0)
	, _consume_mode(false)
{}

namespace object_buffer {

/**
	@addtogroup io_object_buffer
	@{
*/

/// Number of objects.
template<class T, class S>
inline unsigned size(ObjectBuffer<T, S> const& ob) {
	return ob._num_objects;
}

/// Returns true if the buffer is empty.
template<class T, class S>
inline bool empty(ObjectBuffer<T, S> const& ob) {
	return ob._num_objects == 0;
}

/// Returns true if there is another object in the buffer.
///
/// This is always false if buffer is not in consume mode.
template<class T, class S>
inline bool has_more(ObjectBuffer<T, S> const& ob) {
	return ob._consume_mode && ob._num_objects > 0;
}

/// Reset stream and remove all objects.
template<class T, class S>
inline void clear(ObjectBuffer<T, S>& ob) {
	ob._stream.clear();
	ob._num_objects = 0;
}

/// Begin consume mode.
template<class T, class S>
inline void begin_consume(ObjectBuffer<T, S>& ob) {
	TOGO_ASSERT(!ob._consume_mode, "already in consume mode");
	ob._consume_mode = true;
	io::seek_to(ob._stream, 0);
}

/// End consume mode.
///
/// This will clear the buffer.
template<class T, class S>
inline void end_consume(ObjectBuffer<T, S>& ob) {
	TOGO_ASSERT(ob._consume_mode, "not in consume mode");
	clear(ob);
	ob._consume_mode = false;
}

/// Read object from a buffer.
///
/// This function fails if there are no more objects in the buffer.
/// Each read operation decrements the number of objects in the stream.
///
/// Returns the size of the object.
/// type is assigned to the deserialized type.
/// object either points to the object in the buffer or is null when
/// the object size is 0.
template<class T, class S, class E>
inline unsigned read(ObjectBuffer<T, S>& ob, E& type, void const*& object) {
	TOGO_DEBUG_ASSERT(ob._consume_mode, "not in consume mode");
	TOGO_ASSERT(ob._num_objects > 0, "no more objects remaining");
	T type_serial{0};
	S size_serial{0};
	TOGO_ASSERT(
		io::read_value(ob._stream, type_serial) &&
		io::read_value(ob._stream, size_serial),
		"failed to read from object buffer"
	);
	type = static_cast<E>(type_serial);
	if (size_serial > 0) {
		object = array::begin(ob._stream.buffer()) + ob._stream._position;
		io::seek_relative(ob._stream, size_serial);
	} else {
		object = nullptr;
	}
	--ob._num_objects;
	return static_cast<unsigned>(size_serial);
}

/// Write object to a buffer.
template<class T, class S, class E, class O>
inline void write(ObjectBuffer<T, S>& ob, E const type, O const& object) {
	TOGO_DEBUG_ASSERT(!ob._consume_mode, "cannot write in consume mode");
	TOGO_ASSERT(
		io::write_value(ob._stream, static_cast<T>(type)) &&
		io::write_value(ob._stream, static_cast<S>(sizeof_empty<O>())) &&<commit_msg>io/object_buffer: URC (io/memory_stream).<commit_after>#line 2 "togo/io/object_buffer.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Object buffer interface.
@ingroup io_object_buffer
*/

#pragma once

#include <togo/config.hpp>
#include <togo/types.hpp>
#include <togo/error/assert.hpp>
#include <togo/memory/types.hpp>
#include <togo/collection/array.hpp>
#include <togo/io/io.hpp>
#include <togo/io/memory_stream.hpp>
#include <togo/io/object_buffer_type.hpp>

namespace togo {

/// Construct with allocator and initial capacity (in bytes).
template<class T, class S>
inline ObjectBuffer<T, S>::ObjectBuffer(
	Allocator& allocator,
	u32 const init_capacity
)
	: _stream(allocator, init_capacity)
	, _num_objects(0)
	, _consume_mode(false)
{}

namespace object_buffer {

/**
	@addtogroup io_object_buffer
	@{
*/

/// Number of objects.
template<class T, class S>
inline unsigned size(ObjectBuffer<T, S> const& ob) {
	return ob._num_objects;
}

/// Returns true if the buffer is empty.
template<class T, class S>
inline bool empty(ObjectBuffer<T, S> const& ob) {
	return ob._num_objects == 0;
}

/// Returns true if there is another object in the buffer.
///
/// This is always false if buffer is not in consume mode.
template<class T, class S>
inline bool has_more(ObjectBuffer<T, S> const& ob) {
	return ob._consume_mode && ob._num_objects > 0;
}

/// Reset stream and remove all objects.
template<class T, class S>
inline void clear(ObjectBuffer<T, S>& ob) {
	ob._stream.clear();
	ob._num_objects = 0;
}

/// Begin consume mode.
template<class T, class S>
inline void begin_consume(ObjectBuffer<T, S>& ob) {
	TOGO_ASSERT(!ob._consume_mode, "already in consume mode");
	ob._consume_mode = true;
	io::seek_to(ob._stream, 0);
}

/// End consume mode.
///
/// This will clear the buffer.
template<class T, class S>
inline void end_consume(ObjectBuffer<T, S>& ob) {
	TOGO_ASSERT(ob._consume_mode, "not in consume mode");
	clear(ob);
	ob._consume_mode = false;
}

/// Read object from a buffer.
///
/// This function fails if there are no more objects in the buffer.
/// Each read operation decrements the number of objects in the stream.
///
/// Returns the size of the object.
/// type is assigned to the deserialized type.
/// object either points to the object in the buffer or is null when
/// the object size is 0.
template<class T, class S, class E>
inline unsigned read(ObjectBuffer<T, S>& ob, E& type, void const*& object) {
	TOGO_DEBUG_ASSERT(ob._consume_mode, "not in consume mode");
	TOGO_ASSERT(ob._num_objects > 0, "no more objects remaining");
	T type_serial{0};
	S size_serial{0};
	TOGO_ASSERT(
		io::read_value(ob._stream, type_serial) &&
		io::read_value(ob._stream, size_serial),
		"failed to read from object buffer"
	);
	type = static_cast<E>(type_serial);
	if (size_serial > 0) {
		object = array::begin(ob._stream.data()) + ob._stream._position;
		io::seek_relative(ob._stream, size_serial);
	} else {
		object = nullptr;
	}
	--ob._num_objects;
	return static_cast<unsigned>(size_serial);
}

/// Write object to a buffer.
template<class T, class S, class E, class O>
inline void write(ObjectBuffer<T, S>& ob, E const type, O const& object) {
	TOGO_DEBUG_ASSERT(!ob._consume_mode, "cannot write in consume mode");
	TOGO_ASSERT(
		io::write_value(ob._stream, static_cast<T>(type)) &&
		io::write_value(ob._stream, static_cast<S>(sizeof_empty<O>())) &&
{'fraction_non_alphanumeric': 0.13446858485026425, 'fraction_numerical': 0.003816793893129771, 'mean_word_length': 4.4504, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 71, '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': '6934196', 'n_tokens_mistral': 2353, 'n_tokens_neox': 2314, 'n_words': 714}