<commit_before>
#pragma once

#include <togo/utility.hpp>
#include <togo/assert.hpp>
#include <togo/io_types.hpp>
#include <togo/io_proto.hpp>
#include <togo/io.hpp>

using namespace togo;

namespace {

union FloatInt {
	float f;
	u32 i;
};

bool float_exact(float const x, float const y) {
	FloatInt const xu{x};
	FloatInt const yu{y};
	return xu.i == yu.i;
}

struct TestStreamState {
	u8  v8 {8};
	u16 v16{16};
	u32 v32{32};
	u64 v64{64};
	float vfloat{-32.0f};
	u32 array[10]{0};
};

enum : signed {
	SIZE_VALUES
		= sizeof(TestStreamState::v8)
		+ sizeof(TestStreamState::v16)
		+ sizeof(TestStreamState::v32)
		+ sizeof(TestStreamState::v64)
		+ sizeof(TestStreamState::vfloat)
	,
	SIZE_ARRAY = sizeof(TestStreamState::array),
	SIZE_BOTH = SIZE_VALUES + SIZE_ARRAY
};

} // anonymous namespace

void test_reader(IReader& stream, bool const seekable) {
	TestStreamState s{};
	TOGO_ASSERTE(io::read_value(stream, s.v8 ) && s.v8  ==  8);
	TOGO_ASSERTE(io::read_value(stream, s.v16) && s.v16 == 16);
	TOGO_ASSERTE(io::read_value(stream, s.v32) && s.v32 == 32);
	TOGO_ASSERTE(io::read_value(stream, s.v64) && s.v64 == 64);
	TOGO_ASSERTE(io::read_value(stream, s.vfloat) && float_exact(s.vfloat, -32.0f));

	if (seekable) {
		TOGO_ASSERTE(io::position(dynamic_cast<IStreamSeekable&>(stream)) == SIZE_VALUES);
	}

	TOGO_ASSERTE(io::read_array(stream, s.array, array_extent(&TestStreamState::array)));
	u32 bit = 128;
	for (u32& v : s.array) {
		TOGO_ASSERTE(v == bit);
		bit <<= 1;
	}

	if (seekable) {
		IStreamSeekable& stream_seekable = dynamic_cast<IStreamSeekable&>(stream);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_BOTH);
		TOGO_ASSERTE(!io::status(stream_seekable).eof());

		TOGO_ASSERTE(io::seek_relative(stream_seekable, -SIZE_ARRAY) == SIZE_VALUES);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_VALUES);
		TOGO_ASSERTE(io::seek_to(stream_seekable, 0) == 0);
		TOGO_ASSERTE(io::position(stream_seekable) == 0);
	}
}

void test_writer(IWriter& stream, bool const seekable) {
	TestStreamState s{};
	TOGO_ASSERTE(io::write_value(stream, s.v8 ));
	TOGO_ASSERTE(io::write_value(stream, s.v16));
	TOGO_ASSERTE(io::write_value(stream, s.v32));
	TOGO_ASSERTE(io::write_value(stream, s.v64));
	TOGO_ASSERTE(io::write_value(stream, s.vfloat));

	if (seekable) {
		TOGO_ASSERTE(io::position(dynamic_cast<IStreamSeekable&>(stream)) == SIZE_VALUES);
	}

	u32 bit = 128;
	for (u32& v : s.array) {
		v = bit;
		bit <<= 1;
	}
	TOGO_ASSERTE(io::write_array(stream, s.array, array_extent(&TestStreamState::array)));

	if (seekable) {
		IStreamSeekable& stream_seekable = dynamic_cast<IStreamSeekable&>(stream);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_BOTH);
		TOGO_ASSERTE(!io::status(stream_seekable).eof());

		TOGO_ASSERTE(io::seek_relative(stream_seekable, -SIZE_ARRAY) == SIZE_VALUES);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_VALUES);
		TOGO_ASSERTE(io::seek_to(stream_seekable, 0) == 0);
		TOGO_ASSERTE(io::position(stream_seekable) == 0);
	}
}
<commit_msg>test/io/common: 0-fill test state in test_reader().¹<commit_after>
#pragma once

#include <togo/utility.hpp>
#include <togo/assert.hpp>
#include <togo/io_types.hpp>
#include <togo/io_proto.hpp>
#include <togo/io.hpp>

#include <cstring>

using namespace togo;

namespace {

union FloatInt {
	float f;
	u32 i;
};

bool float_exact(float const x, float const y) {
	FloatInt const xu{x};
	FloatInt const yu{y};
	return xu.i == yu.i;
}

struct TestStreamState {
	u8  v8 {8};
	u16 v16{16};
	u32 v32{32};
	u64 v64{64};
	float vfloat{-32.0f};
	u32 array[10]{0};
};

enum : signed {
	SIZE_VALUES
		= sizeof(TestStreamState::v8)
		+ sizeof(TestStreamState::v16)
		+ sizeof(TestStreamState::v32)
		+ sizeof(TestStreamState::v64)
		+ sizeof(TestStreamState::vfloat)
	,
	SIZE_ARRAY = sizeof(TestStreamState::array),
	SIZE_BOTH = SIZE_VALUES + SIZE_ARRAY
};

} // anonymous namespace

void test_reader(IReader& stream, bool const seekable) {
	TestStreamState s{};
	std::memset(&s, 0, sizeof(TestStreamState));
	TOGO_ASSERTE(io::read_value(stream, s.v8 ) && s.v8  ==  8);
	TOGO_ASSERTE(io::read_value(stream, s.v16) && s.v16 == 16);
	TOGO_ASSERTE(io::read_value(stream, s.v32) && s.v32 == 32);
	TOGO_ASSERTE(io::read_value(stream, s.v64) && s.v64 == 64);
	TOGO_ASSERTE(io::read_value(stream, s.vfloat) && float_exact(s.vfloat, -32.0f));

	if (seekable) {
		TOGO_ASSERTE(io::position(dynamic_cast<IStreamSeekable&>(stream)) == SIZE_VALUES);
	}

	TOGO_ASSERTE(io::read_array(stream, s.array, array_extent(&TestStreamState::array)));
	u32 bit = 128;
	for (u32& v : s.array) {
		TOGO_ASSERTE(v == bit);
		bit <<= 1;
	}

	if (seekable) {
		IStreamSeekable& stream_seekable = dynamic_cast<IStreamSeekable&>(stream);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_BOTH);
		TOGO_ASSERTE(!io::status(stream_seekable).eof());

		TOGO_ASSERTE(io::seek_relative(stream_seekable, -SIZE_ARRAY) == SIZE_VALUES);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_VALUES);
		TOGO_ASSERTE(io::seek_to(stream_seekable, 0) == 0);
		TOGO_ASSERTE(io::position(stream_seekable) == 0);
	}
}

void test_writer(IWriter& stream, bool const seekable) {
	TestStreamState s{};
	TOGO_ASSERTE(io::write_value(stream, s.v8 ));
	TOGO_ASSERTE(io::write_value(stream, s.v16));
	TOGO_ASSERTE(io::write_value(stream, s.v32));
	TOGO_ASSERTE(io::write_value(stream, s.v64));
	TOGO_ASSERTE(io::write_value(stream, s.vfloat));

	if (seekable) {
		TOGO_ASSERTE(io::position(dynamic_cast<IStreamSeekable&>(stream)) == SIZE_VALUES);
	}

	u32 bit = 128;
	for (u32& v : s.array) {
		v = bit;
		bit <<= 1;
	}
	TOGO_ASSERTE(io::write_array(stream, s.array, array_extent(&TestStreamState::array)));

	if (seekable) {
		IStreamSeekable& stream_seekable = dynamic_cast<IStreamSeekable&>(stream);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_BOTH);
		TOGO_ASSERTE(!io::status(stream_seekable).eof());

		TOGO_ASSERTE(io::seek_relative(stream_seekable, -SIZE_ARRAY) == SIZE_VALUES);
		TOGO_ASSERTE(io::position(stream_seekable) == SIZE_VALUES);
		TOGO_ASSERTE(io::seek_to(stream_seekable, 0) == 0);
		TOGO_ASSERTE(io::position(stream_seekable) == 0);
	}
}

{'fraction_non_alphanumeric': 0.16543816543816545, 'fraction_numerical': 0.03013923013923014, 'mean_word_length': 6.243179122182681, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 22, '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': '4182800', 'n_tokens_mistral': 2759, 'n_tokens_neox': 2559, 'n_words': 384}