<commit_before>#pragma once

#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <vector>

#include "hash.hpp"
#include "ranger.hpp"
#include "serial.hpp"

template <typename R>
struct TransactionBase {
	struct Input {
		R hash;
		uint32_t vout;
		R script;
		uint32_t sequence;

		Input (R hash, uint32_t vout, R script, uint32_t sequence) :
			hash(hash), vout(vout), script(script), sequence(sequence) {}
	};

	struct Output {
		R script;
		uint64_t value;

		Output (R script, uint64_t value) : script(script), value(value) {}
	};

	struct Witness {
		std::vector<R> stack;

		Witness (std::vector<R> stack) : stack(stack) {}
	};

	R data;

	int32_t version;
	std::vector<Input> inputs;
	std::vector<Output> outputs;
	std::vector<Witness> witnesses;
	uint32_t locktime;

	TransactionBase (
		R data,
		int32_t version,
		std::vector<Input> inputs,
		std::vector<Output> outputs,
		std::vector<Witness> witnesses,
		uint32_t locktime
	) :
		data(data),
		version(version),
		inputs(inputs),
		outputs(outputs),
		witnesses(witnesses),
		locktime(locktime) {}

	auto hash () const {
		return hash256(this->data);
	}
};

namespace {
	template <typename R>
	auto readRange (R& r, size_t n) {
		auto v = r.take(n);
		r.popFrontN(n);
		return v;
	}

	template <typename R>
	auto readVI (R& r) {
		const auto i = serial::read<uint8_t>(r);
		if (i < 253) return static_cast<uint64_t>(i);
		if (i < 254) return static_cast<uint64_t>(serial::read<uint16_t>(r));
		if (i < 255) return static_cast<uint64_t>(serial::read<uint32_t>(r));
		return serial::read<uint64_t>(r);
	}

	template <typename R>
	auto readVI (R&& r) { return readVI<R>(r); }

	template <typename R>
	auto readStack (R& r) {
		const auto count = readVI(r);

		std::vector<R> stack;
		for (uint64_t i = 0; i < count; ++i) {
			stack.emplace_back(readRange(r, readVI(r)));
		}

		return std::move(stack);
	}

	template <typename R>
	auto readTransaction (R& data) {
		using Transaction = TransactionBase<R>;

		auto save = data;
		const auto version = serial::read<int32_t>(data);

		// segregated witness
		const auto marker = serial::peek<uint8_t>(data);
		const auto flag = serial::peek<uint8_t>(data.drop(1));
		const auto hasWitnesses = (marker == 0x00) && (flag == 0x01);
		if (hasWitnesses) data.popFrontN(2);

		const auto nInputs = readVI(data);
		std::vector<typename Transaction::Input> inputs;

		for (size_t i = 0; i < nInputs; ++i) {
			const auto hash = readRange(data, 32);
			const auto vout = serial::read<uint32_t>(data);

			const auto scriptLen = readVI(data);
			const auto script = readRange(data, scriptLen);
			const auto sequence = serial::read<uint32_t>(data);

			inputs.emplace_back(typename Transaction::Input(hash, vout, script, sequence));
		}

		const auto nOutputs = readVI(data);
		std::vector<typename Transaction::Output> outputs;

		for (size_t i = 0; i < nOutputs; ++i) {
			const auto value = serial::read<uint64_t>(data);
			const auto scriptLen = readVI(data);
			const auto script = readRange(data, scriptLen);

			outputs.emplace_back(typename Transaction::Output(script, value));
		}

		std::vector<typename Transaction::Witness> witnesses;
		if (hasWitnesses) {
			for (size_t i = 0; i < nInputs; ++i) {
				const auto stack = readStack(data);

				witnesses.emplace_back(typename Transaction::Witness(std::move(stack)));
			}
		}

		const auto locktime = serial::read<uint32_t>(data);
		save.popBackN(data.size());

		return Transaction(save, version, std::move(inputs), std::move(outputs), std::move(witnesses), locktime);
	}

	template <typename R>
	auto readTransaction (R&& data) { return readTransaction<R>(data); }
}

template <typename R>
struct TransactionRange {
private:
	size_t _count;
	R _data;
	R _save;

public:
	TransactionRange(R data, size_t count) : _count(count), _data(data), _save(data.take(0)) {}

	auto empty () const { return this->_count > 0; }
	auto size () const { return this->_count; }
	auto front () {
		this->_save = this->_data;
		return readTransaction(this->_save);
	}

	void popFront () {
		assert(!this->empty());
		--this->_count;
<commit_msg>fix empty returning inverted result<commit_after>#pragma once

#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <vector>

#include "hash.hpp"
#include "ranger.hpp"
#include "serial.hpp"

template <typename R>
struct TransactionBase {
	struct Input {
		R hash;
		uint32_t vout;
		R script;
		uint32_t sequence;

		Input (R hash, uint32_t vout, R script, uint32_t sequence) :
			hash(hash), vout(vout), script(script), sequence(sequence) {}
	};

	struct Output {
		R script;
		uint64_t value;

		Output (R script, uint64_t value) : script(script), value(value) {}
	};

	struct Witness {
		std::vector<R> stack;

		Witness (std::vector<R> stack) : stack(stack) {}
	};

	R data;

	int32_t version;
	std::vector<Input> inputs;
	std::vector<Output> outputs;
	std::vector<Witness> witnesses;
	uint32_t locktime;

	TransactionBase (
		R data,
		int32_t version,
		std::vector<Input> inputs,
		std::vector<Output> outputs,
		std::vector<Witness> witnesses,
		uint32_t locktime
	) :
		data(data),
		version(version),
		inputs(inputs),
		outputs(outputs),
		witnesses(witnesses),
		locktime(locktime) {}

	auto hash () const {
		return hash256(this->data);
	}
};

namespace {
	template <typename R>
	auto readRange (R& r, size_t n) {
		auto v = r.take(n);
		r.popFrontN(n);
		return v;
	}

	template <typename R>
	auto readVI (R& r) {
		const auto i = serial::read<uint8_t>(r);
		if (i < 253) return static_cast<uint64_t>(i);
		if (i < 254) return static_cast<uint64_t>(serial::read<uint16_t>(r));
		if (i < 255) return static_cast<uint64_t>(serial::read<uint32_t>(r));
		return serial::read<uint64_t>(r);
	}

	template <typename R>
	auto readVI (R&& r) { return readVI<R>(r); }

	template <typename R>
	auto readStack (R& r) {
		const auto count = readVI(r);

		std::vector<R> stack;
		for (uint64_t i = 0; i < count; ++i) {
			stack.emplace_back(readRange(r, readVI(r)));
		}

		return std::move(stack);
	}

	template <typename R>
	auto readTransaction (R& data) {
		using Transaction = TransactionBase<R>;

		auto save = data;
		const auto version = serial::read<int32_t>(data);

		// segregated witness
		const auto marker = serial::peek<uint8_t>(data);
		const auto flag = serial::peek<uint8_t>(data.drop(1));
		const auto hasWitnesses = (marker == 0x00) && (flag == 0x01);
		if (hasWitnesses) data.popFrontN(2);

		const auto nInputs = readVI(data);
		std::vector<typename Transaction::Input> inputs;

		for (size_t i = 0; i < nInputs; ++i) {
			const auto hash = readRange(data, 32);
			const auto vout = serial::read<uint32_t>(data);

			const auto scriptLen = readVI(data);
			const auto script = readRange(data, scriptLen);
			const auto sequence = serial::read<uint32_t>(data);

			inputs.emplace_back(typename Transaction::Input(hash, vout, script, sequence));
		}

		const auto nOutputs = readVI(data);
		std::vector<typename Transaction::Output> outputs;

		for (size_t i = 0; i < nOutputs; ++i) {
			const auto value = serial::read<uint64_t>(data);
			const auto scriptLen = readVI(data);
			const auto script = readRange(data, scriptLen);

			outputs.emplace_back(typename Transaction::Output(script, value));
		}

		std::vector<typename Transaction::Witness> witnesses;
		if (hasWitnesses) {
			for (size_t i = 0; i < nInputs; ++i) {
				const auto stack = readStack(data);

				witnesses.emplace_back(typename Transaction::Witness(std::move(stack)));
			}
		}

		const auto locktime = serial::read<uint32_t>(data);
		save.popBackN(data.size());

		return Transaction(save, version, std::move(inputs), std::move(outputs), std::move(witnesses), locktime);
	}

	template <typename R>
	auto readTransaction (R&& data) { return readTransaction<R>(data); }
}

template <typename R>
struct TransactionRange {
private:
	size_t _count;
	R _data;
	R _save;

public:
	TransactionRange(R data, size_t count) : _count(count), _data(data), _save(data.take(0)) {}

	auto empty () const { return this->_count == 0; }
	auto size () const { return this->_count; }
	auto front () {
		this->_save = this->_data;
		return readTransaction(this->_save);
	}

	void popFront () {
		assert(!this->empty());
		--this->_count;

{'fraction_non_alphanumeric': 0.14998184239196224, 'fraction_numerical': 0.018157608037767826, 'mean_word_length': 4.541247484909457, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 104, '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': '1597248', 'n_tokens_mistral': 3262, 'n_tokens_neox': 2910, 'n_words': 740}