<commit_before>//
//  TapeUEF.cpp
//  Clock Signal
//
//  Created by <NAME> on 18/01/2016.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#include "TapeUEF.hpp"
#include <string.h>

Storage::UEF::UEF(const char *file_name) :
	_chunk_id(0), _chunk_length(0), _chunk_position(0),
	_time_base(1200)
{
	_file = gzopen(file_name, "rb");

	char identifier[10];
	int bytes_read = gzread(_file, identifier, 10);
	if(bytes_read < 10 || strcmp(identifier, "UEF File!"))
	{
		// exception?
	}

	int minor, major;
	minor = gzgetc(_file);
	major = gzgetc(_file);

	if(major > 0 || minor > 10 || major < 0 || minor < 0)
	{
		// exception?
	}

	find_next_tape_chunk();
}

Storage::UEF::~UEF()
{
	gzclose(_file);
}

void Storage::UEF::reset()
{
	gzseek(_file, 12, SEEK_SET);
}

Storage::Tape::Pulse Storage::UEF::get_next_pulse()
{
	Pulse next_pulse;

	if(!_bit_position && chunk_is_finished())
	{
		find_next_tape_chunk();
	}

	next_pulse.length.clock_rate = _time_base * 2;

	switch(_chunk_id)
	{
		case 0x0100: case 0x0102:
		{
			// In the ordinary ("1200 baud") data encoding format,
			// a zero bit is encoded as one complete cycle at the base frequency.
			// A one bit is two complete cycles at twice the base frequency.

			if(!_bit_position)
			{
				_current_bit = get_next_bit();
			}

			next_pulse.type = (_bit_position&1) ? Pulse::High : Pulse::Low;
			next_pulse.length.length = _current_bit ? 1 : 2;
			_bit_position = (_bit_position+1)&(_current_bit ? 3 : 1);
		} break;

		case 0x0110:
			next_pulse.type = (_bit_position&1) ? Pulse::High : Pulse::Low;
			next_pulse.length.length = 2;
			_bit_position ^= 1;

			if(!_bit_position) _chunk_position++;
		break;

		case 0x0112:
		case 0x0116:
			next_pulse.type = Pulse::Zero;
			next_pulse.length.length = _tone_length;
			_chunk_position++;
		break;
	}

	return next_pulse;
}

void Storage::UEF::find_next_tape_chunk()
{
	int reset_count = 0;
	_chunk_position = 0;
	_bit_position = 0;

	while(1)
	{
		// read chunk ID
		_chunk_id = (uint16_t)gzgetc(_file);
		_chunk_id |= (uint16_t)(gzgetc(_file) << 8);

		_chunk_length = (uint32_t)(gzgetc(_file) << 0);
		_chunk_length |= (uint32_t)(gzgetc(_file) << 8);
		_chunk_length |= (uint32_t)(gzgetc(_file) << 16);
		_chunk_length |= (uint32_t)(gzgetc(_file) << 24);

		if(gzeof(_file))
		{
			reset_count++;
			if(reset_count == 2) break;
			reset();
			continue;
		}

		switch(_chunk_id)
		{
			case 0x0100: case 0x0102: // implicit and explicit bit patterns
			case 0x0112: case 0x0116: // gaps
			return;

			case 0x0110: // carrier tone
				_tone_length = (uint16_t)gzgetc(_file);
				_tone_length |= (uint16_t)(gzgetc(_file) << 8);
				gzseek(_file, _chunk_length - 2, SEEK_CUR);
			return;
			case 0x0111: // carrier tone with dummy byte
				// TODO: read length
			return;
			case 0x0114: // security cycles
				// TODO: read number, Ps and Ws
			break;

			case 0x113: // change of base rate
			break;

			default:
				gzseek(_file, _chunk_length, SEEK_CUR);
			break;
		}
	}
}

bool Storage::UEF::chunk_is_finished()
{
	switch(_chunk_id)
	{
		case 0x0100: return (_chunk_position / 10) == _chunk_length;
		case 0x0102: return (_chunk_position / 8) == _chunk_length;
		case 0x0111: return _chunk_position == _tone_length;

		case 0x0112:
		case 0x0116: return _chunk_position ? true : false;

		default: return true;
	}
}

bool Storage::UEF::get_next_bit()
{
	switch(_chunk_id)
	{
		case 0x0100:
		{
			uint32_t bit_position = _chunk_position%10;
			_chunk_position++;
			if(!bit_position)
			{
				_current_byte = (uint8_t)gzgetc(_file);
			}
			if(bit_position == 0) return false;
			if(bit_position == 9) return true;
			bool result = (_current_byte&1) ? true : false;
			_current_byte >>= 1;
			return result;
		}
		break;<commit_msg>Update TapeUEF.cpp<commit_after>//
//  TapeUEF.cpp
//  Clock Signal
//
//  Created by <NAME> on 18/01/2016.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#include "TapeUEF.hpp"
#include <string.h>

Storage::UEF::UEF(const char *file_name) :
	_chunk_id(0), _chunk_length(0), _chunk_position(0),
	_time_base(1200)
{
	_file = gzopen(file_name, "rb");

	char identifier[10];
	int bytes_read = gzread(_file, identifier, 10);
	if(bytes_read < 10 || strcmp(identifier, "UEF File!"))
	{
		// exception?
	}

	int minor, major;
	minor = gzgetc(_file);
	major = gzgetc(_file);

	if(major > 0 || minor > 10 || major < 0 || minor < 0)
	{
		// exception?
	}

	find_next_tape_chunk();
}

Storage::UEF::~UEF()
{
	gzclose(_file);
}

void Storage::UEF::reset()
{
	gzseek(_file, 12, SEEK_SET);
}

Storage::Tape::Pulse Storage::UEF::get_next_pulse()
{
	Pulse next_pulse;

	if(!_bit_position && chunk_is_finished())
	{
		find_next_tape_chunk();
	}

	next_pulse.length.clock_rate = _time_base * 2;

	switch(_chunk_id)
	{
		case 0x0100: case 0x0102:
		{
			// In the ordinary ("1200 baud") data encoding format,
			// a zero bit is encoded as one complete cycle at the base frequency.
			// A one bit is two complete cycles at twice the base frequency.

			if(!_bit_position)
			{
				_current_bit = get_next_bit();
			}

			next_pulse.type = (_bit_position&1) ? Pulse::High : Pulse::Low;
			next_pulse.length.length = _current_bit ? 1 : 2;
			_bit_position = (_bit_position+1)&(_current_bit ? 3 : 1);
		} break;

		case 0x0110:
			next_pulse.type = (_bit_position&1) ? Pulse::High : Pulse::Low;
			next_pulse.length.length = 1;
			_bit_position ^= 1;

			if(!_bit_position) _chunk_position++;
		break;

		case 0x0112:
		case 0x0116:
			next_pulse.type = Pulse::Zero;
			next_pulse.length.length = _tone_length;
			_chunk_position++;
		break;
	}

	return next_pulse;
}

void Storage::UEF::find_next_tape_chunk()
{
	int reset_count = 0;
	_chunk_position = 0;
	_bit_position = 0;

	while(1)
	{
		// read chunk ID
		_chunk_id = (uint16_t)gzgetc(_file);
		_chunk_id |= (uint16_t)(gzgetc(_file) << 8);

		_chunk_length = (uint32_t)(gzgetc(_file) << 0);
		_chunk_length |= (uint32_t)(gzgetc(_file) << 8);
		_chunk_length |= (uint32_t)(gzgetc(_file) << 16);
		_chunk_length |= (uint32_t)(gzgetc(_file) << 24);

		if(gzeof(_file))
		{
			reset_count++;
			if(reset_count == 2) break;
			reset();
			continue;
		}

		switch(_chunk_id)
		{
			case 0x0100: case 0x0102: // implicit and explicit bit patterns
			case 0x0112: case 0x0116: // gaps
			return;

			case 0x0110: // carrier tone
				_tone_length = (uint16_t)gzgetc(_file);
				_tone_length |= (uint16_t)(gzgetc(_file) << 8);
				gzseek(_file, _chunk_length - 2, SEEK_CUR);
			return;
			case 0x0111: // carrier tone with dummy byte
				// TODO: read length
			return;
			case 0x0114: // security cycles
				// TODO: read number, Ps and Ws
			break;

			case 0x113: // change of base rate
			break;

			default:
				gzseek(_file, _chunk_length, SEEK_CUR);
			break;
		}
	}
}

bool Storage::UEF::chunk_is_finished()
{
	switch(_chunk_id)
	{
		case 0x0100: return (_chunk_position / 10) == _chunk_length;
		case 0x0102: return (_chunk_position / 8) == _chunk_length;
		case 0x0110: return _chunk_position == _tone_length;

		case 0x0112:
		case 0x0116: return _chunk_position ? true : false;

		default: return true;
	}
}

bool Storage::UEF::get_next_bit()
{
	switch(_chunk_id)
	{
		case 0x0100:
		{
			uint32_t bit_position = _chunk_position%10;
			_chunk_position++;
			if(!bit_position)
			{
				_current_byte = (uint8_t)gzgetc(_file);
			}
			if(bit_position == 0) return false;
			if(bit_position == 9) return true;
			bool result = (_current_byte&1) ? true : false;
			_current_byte >>= 1;
			return result;
		}
		break;
{'fraction_non_alphanumeric': 0.1413347542293859, 'fraction_numerical': 0.04848807779405888, 'mean_word_length': 3.631708821714991, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 17, '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': '2340693', 'n_tokens_mistral': 3557, 'n_tokens_neox': 2933, 'n_words': 636}