From 093eb55fc64d3428c2e714d7a76106a859a651ba Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 6 Nov 2016 15:25:18 -0500 Subject: [PATCH] The parsers no longer own a tape, merely taking one as an argument. So they can be an adjunct. --- StaticAnalyser/Acorn/Tape.cpp | 64 ++++++++--------- StaticAnalyser/Commodore/Tape.cpp | 116 +++++++++++++++--------------- StaticAnalyser/TapeParser.hpp | 46 ++++++------ 3 files changed, 111 insertions(+), 115 deletions(-) diff --git a/StaticAnalyser/Acorn/Tape.cpp b/StaticAnalyser/Acorn/Tape.cpp index 056b05ccb..92a1bd573 100644 --- a/StaticAnalyser/Acorn/Tape.cpp +++ b/StaticAnalyser/Acorn/Tape.cpp @@ -24,30 +24,30 @@ enum class SymbolType { class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser { public: - Acorn1200BaudTapeParser(const std::shared_ptr &tape) : - TapeParser(tape), + Acorn1200BaudTapeParser() : + TapeParser(), _crc(0x1021, 0x0000) {} - int get_next_bit() + int get_next_bit(const std::shared_ptr &tape) { - SymbolType symbol = get_next_symbol(); + SymbolType symbol = get_next_symbol(tape); return (symbol == SymbolType::One) ? 1 : 0; } - int get_next_byte() + int get_next_byte(const std::shared_ptr &tape) { int value = 0; int c = 8; - if(get_next_bit()) + if(get_next_bit(tape)) { set_error_flag(); return -1; } while(c--) { - value = (value >> 1) | (get_next_bit() << 7); + value = (value >> 1) | (get_next_bit(tape) << 7); } - if(!get_next_bit()) + if(!get_next_bit(tape)) { set_error_flag(); return -1; @@ -56,17 +56,17 @@ class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser &tape) { - int result = get_next_byte(); - result |= get_next_byte() << 8; + int result = get_next_byte(tape); + result |= get_next_byte(tape) << 8; return result; } - int get_next_word() + int get_next_word(const std::shared_ptr &tape) { - int result = get_next_short(); - result |= get_next_short() << 8; + int result = get_next_short(tape); + result |= get_next_short(tape) << 8; return result; } @@ -117,22 +117,22 @@ class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser GetNextChunk(Acorn1200BaudTapeParser &parser) +static std::unique_ptr GetNextChunk(const std::shared_ptr &tape, Acorn1200BaudTapeParser &parser) { std::unique_ptr new_chunk(new File::Chunk); int shift_register = 0; // TODO: move this into the parser -#define shift() shift_register = (shift_register >> 1) | (parser.get_next_bit() << 9) +#define shift() shift_register = (shift_register >> 1) | (parser.get_next_bit(tape) << 9) // find next area of high tone - while(!parser.is_at_end() && (shift_register != 0x3ff)) + while(!tape->is_at_end() && (shift_register != 0x3ff)) { shift(); } // find next 0x2a (swallowing stop bit) - while(!parser.is_at_end() && (shift_register != 0x254)) + while(!tape->is_at_end() && (shift_register != 0x254)) { shift(); } @@ -145,9 +145,9 @@ static std::unique_ptr GetNextChunk(Acorn1200BaudTapeParser &parser // read out name char name[11]; int name_ptr = 0; - while(!parser.is_at_end() && name_ptr < sizeof(name)) + while(!tape->is_at_end() && name_ptr < sizeof(name)) { - name[name_ptr] = (char)parser.get_next_byte(); + name[name_ptr] = (char)parser.get_next_byte(tape); if(!name[name_ptr]) break; name_ptr++; } @@ -155,15 +155,15 @@ static std::unique_ptr GetNextChunk(Acorn1200BaudTapeParser &parser new_chunk->name = name; // addresses - new_chunk->load_address = (uint32_t)parser.get_next_word(); - new_chunk->execution_address = (uint32_t)parser.get_next_word(); - new_chunk->block_number = (uint16_t)parser.get_next_short(); - new_chunk->block_length = (uint16_t)parser.get_next_short(); - new_chunk->block_flag = (uint8_t)parser.get_next_byte(); - new_chunk->next_address = (uint32_t)parser.get_next_word(); + new_chunk->load_address = (uint32_t)parser.get_next_word(tape); + new_chunk->execution_address = (uint32_t)parser.get_next_word(tape); + new_chunk->block_number = (uint16_t)parser.get_next_short(tape); + new_chunk->block_length = (uint16_t)parser.get_next_short(tape); + new_chunk->block_flag = (uint8_t)parser.get_next_byte(tape); + new_chunk->next_address = (uint32_t)parser.get_next_word(tape); uint16_t calculated_header_crc = parser.get_crc(); - uint16_t stored_header_crc = (uint16_t)parser.get_next_short(); + uint16_t stored_header_crc = (uint16_t)parser.get_next_short(tape); stored_header_crc = (uint16_t)((stored_header_crc >> 8) | (stored_header_crc << 8)); new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc; @@ -171,13 +171,13 @@ static std::unique_ptr GetNextChunk(Acorn1200BaudTapeParser &parser new_chunk->data.reserve(new_chunk->block_length); for(int c = 0; c < new_chunk->block_length; c++) { - new_chunk->data.push_back((uint8_t)parser.get_next_byte()); + new_chunk->data.push_back((uint8_t)parser.get_next_byte(tape)); } if(new_chunk->block_length && !(new_chunk->block_flag&0x40)) { uint16_t calculated_data_crc = parser.get_crc(); - uint16_t stored_data_crc = (uint16_t)parser.get_next_short(); + uint16_t stored_data_crc = (uint16_t)parser.get_next_short(tape); stored_data_crc = (uint16_t)((stored_data_crc >> 8) | (stored_data_crc << 8)); new_chunk->data_crc_matched = stored_data_crc == calculated_data_crc; } @@ -233,13 +233,13 @@ std::unique_ptr GetNextFile(std::deque &chunks) std::list StaticAnalyser::Acorn::GetFiles(const std::shared_ptr &tape) { - Acorn1200BaudTapeParser parser(tape); + Acorn1200BaudTapeParser parser; // populate chunk list std::deque chunk_list; - while(!parser.is_at_end()) + while(!tape->is_at_end()) { - std::unique_ptr chunk = GetNextChunk(parser); + std::unique_ptr chunk = GetNextChunk(tape, parser); if(chunk) { chunk_list.push_back(*chunk); diff --git a/StaticAnalyser/Commodore/Tape.cpp b/StaticAnalyser/Commodore/Tape.cpp index 1cb9fe8ec..94c65e936 100644 --- a/StaticAnalyser/Commodore/Tape.cpp +++ b/StaticAnalyser/Commodore/Tape.cpp @@ -49,7 +49,7 @@ struct Data { class CommodoreROMTapeParser: public StaticAnalyer::TapeParser { public: CommodoreROMTapeParser(const std::shared_ptr &tape) : - TapeParser(tape), + TapeParser(), _wave_period(0.0f), _previous_was_high(false), _parity_byte(0) {} @@ -58,11 +58,11 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser get_next_header() + std::unique_ptr
get_next_header(const std::shared_ptr &tape) { return duplicate_match
( - get_next_header_body(true), - get_next_header_body(false) + get_next_header_body(tape, true), + get_next_header_body(tape, false) ); } @@ -70,29 +70,29 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser get_next_data() + std::unique_ptr get_next_data(const std::shared_ptr &tape) { return duplicate_match( - get_next_data_body(true), - get_next_data_body(false) + get_next_data_body(tape, true), + get_next_data_body(tape, false) ); } - void spin() - { - while(!is_at_end()) - { - SymbolType symbol = get_next_symbol(); - switch(symbol) - { - case SymbolType::One: printf("1"); break; - case SymbolType::Zero: printf("0"); break; - case SymbolType::Word: printf(" "); break; - case SymbolType::EndOfBlock: printf("\n"); break; - case SymbolType::LeadIn: printf("-"); break; - } - } - } +// void spin() +// { +// while(!is_at_end()) +// { +// SymbolType symbol = get_next_symbol(); +// switch(symbol) +// { +// case SymbolType::One: printf("1"); break; +// case SymbolType::Zero: printf("0"); break; +// case SymbolType::Word: printf(" "); break; +// case SymbolType::EndOfBlock: printf("\n"); break; +// case SymbolType::LeadIn: printf("-"); break; +// } +// } +// } private: /*! @@ -122,20 +122,20 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser get_next_header_body(bool is_original) + std::unique_ptr
get_next_header_body(const std::shared_ptr &tape, bool is_original) { std::unique_ptr
header(new Header); reset_error_flag(); // find and proceed beyond lead-in tone - proceed_to_symbol(SymbolType::LeadIn); + proceed_to_symbol(tape, SymbolType::LeadIn); // look for landing zone - proceed_to_landing_zone(is_original); + proceed_to_landing_zone(tape, is_original); reset_parity_byte(); // get header type - uint8_t header_type = get_next_byte(); + uint8_t header_type = get_next_byte(tape); switch(header_type) { default: header->type = Header::Unknown; break; @@ -150,11 +150,11 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParserdata.reserve(191); for(size_t c = 0; c < 191; c++) { - header->data.push_back(get_next_byte()); + header->data.push_back(get_next_byte(tape)); } uint8_t parity_byte = get_parity_byte(); - header->parity_was_valid = get_next_byte() == parity_byte; + header->parity_was_valid = get_next_byte(tape) == parity_byte; // parse if this is not pure data if(header->type != Header::DataBlock) @@ -174,22 +174,22 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser get_next_data_body(bool is_original) + std::unique_ptr get_next_data_body(const std::shared_ptr &tape, bool is_original) { std::unique_ptr data(new Data); reset_error_flag(); // find and proceed beyond lead-in tone to the next landing zone - proceed_to_symbol(SymbolType::LeadIn); - proceed_to_landing_zone(is_original); + proceed_to_symbol(tape, SymbolType::LeadIn); + proceed_to_landing_zone(tape, is_original); reset_parity_byte(); // accumulate until the next non-word marker is hit - while(!is_at_end()) + while(!tape->is_at_end()) { - SymbolType start_symbol = get_next_symbol(); + SymbolType start_symbol = get_next_symbol(tape); if(start_symbol != SymbolType::Word) break; - data->data.push_back(get_next_byte_contents()); + data->data.push_back(get_next_byte_contents(tape)); } // the above has reead the parity byte to the end of the data; if it matched the calculated parity it'll now be zero @@ -205,13 +205,13 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser &tape, bool is_original) { uint8_t landing_zone[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - while(!is_at_end()) + while(!tape->is_at_end()) { memmove(landing_zone, &landing_zone[1], sizeof(uint8_t) * 8); - landing_zone[8] = get_next_byte(); + landing_zone[8] = get_next_byte(tape); bool is_landing_zone = true; for(int c = 0; c < 9; c++) @@ -230,11 +230,11 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser &tape, SymbolType required_symbol) { - while(!is_at_end()) + while(!tape->is_at_end()) { - SymbolType symbol = get_next_symbol(); + SymbolType symbol = get_next_symbol(tape); if(symbol == required_symbol) return; } } @@ -242,9 +242,9 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser &tape, uint8_t value) { - uint8_t next_byte = get_next_byte(); + uint8_t next_byte = get_next_byte(tape); if(next_byte != value) set_error_flag(); } @@ -256,10 +256,10 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser &tape) { - proceed_to_symbol(SymbolType::Word); - return get_next_byte_contents(); + proceed_to_symbol(tape, SymbolType::Word); + return get_next_byte_contents(tape); } /*! @@ -267,13 +267,13 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser &tape) { int byte_plus_parity = 0; int c = 9; while(c--) { - SymbolType next_symbol = get_next_symbol(); + SymbolType next_symbol = get_next_symbol(tape); if((next_symbol != SymbolType::One) && (next_symbol != SymbolType::Zero)) set_error_flag(); byte_plus_parity = (byte_plus_parity >> 1) | (((next_symbol == SymbolType::One) ? 1 : 0) << 8); } @@ -292,10 +292,10 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser &tape) { - uint16_t value = get_next_byte(); - value |= get_next_byte() << 8; + uint16_t value = get_next_byte(tape); + value |= get_next_byte(tape) << 8; return value; } @@ -376,13 +376,13 @@ std::list StaticAnalyser::Commodore::GetFiles(const std::shared_ptr file_list; - std::unique_ptr
header = parser.get_next_header(); + std::unique_ptr
header = parser.get_next_header(tape); - while(!parser.is_at_end()) + while(!tape->is_at_end()) { if(!header) { - header = parser.get_next_header(); + header = parser.get_next_header(tape); continue; } @@ -398,9 +398,9 @@ std::list StaticAnalyser::Commodore::GetFiles(const std::shared_ptrdata); - while(!parser.is_at_end()) + while(!tape->is_at_end()) { - header = parser.get_next_header(); + header = parser.get_next_header(tape); if(!header) continue; if(header->type != Header::DataBlock) break; std::copy(header->data.begin(), header->data.end(), std::back_inserter(new_file.data)); @@ -413,7 +413,7 @@ std::list StaticAnalyser::Commodore::GetFiles(const std::shared_ptr data = parser.get_next_data(); + std::unique_ptr data = parser.get_next_data(tape); if(data) { File new_file; @@ -427,12 +427,12 @@ std::list StaticAnalyser::Commodore::GetFiles(const std::shared_ptr class TapeParser { public: /// Instantiates a new parser with the supplied @c tape. - TapeParser(const std::shared_ptr &tape) : _tape(tape), _has_next_symbol(false), _error_flag(false) {} + TapeParser() : _has_next_symbol(false), _error_flag(false) {} /// Resets the error flag. void reset_error_flag() { _error_flag = false; } /// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise. bool get_error_flag() { return _error_flag; } - /// @returns @c true if the encapsulated tape has reached its end; @c false otherwise. - bool is_at_end() { return _tape->is_at_end(); } + + /*! + Asks the parser to continue taking pulses from the tape until either the subclass next declares a symbol + or the tape runs out, returning the most-recently declared symbol. + */ + SymbolType get_next_symbol(const std::shared_ptr &tape) + { + while(!_has_next_symbol && !tape->is_at_end()) + { + process_pulse(tape->get_next_pulse()); + } + _has_next_symbol = false; + return _next_symbol; + } + + /*! + Should be implemented by subclasses. Consumes @c pulse. Is likely either to call @c push_wave + or to take no action. + */ + virtual void process_pulse(Storage::Tape::Tape::Pulse pulse) = 0; protected: @@ -67,20 +85,6 @@ template class TapeParser { remove_waves(number_of_waves); } - /*! - Asks the parser to continue taking pulses from the tape until either the subclass next declares a symbol - or the tape runs out, returning the most-recently declared symbol. - */ - SymbolType get_next_symbol() - { - while(!_has_next_symbol && !is_at_end()) - { - process_pulse(_tape->get_next_pulse()); - } - _has_next_symbol = false; - return _next_symbol; - } - void set_error_flag() { _error_flag = true; @@ -89,12 +93,6 @@ template class TapeParser { private: bool _error_flag; - /*! - Should be implemented by subclasses. Consumes @c pulse. Is likely either to call @c push_wave - or to take no action. - */ - virtual void process_pulse(Storage::Tape::Tape::Pulse pulse) = 0; - /*! Should be implemented by subclasses. Inspects @c waves for a potential new symbol. If one is found should call @c push_symbol. May wish alternatively to call @c remove_waves to have entries @@ -106,8 +104,6 @@ template class TapeParser { std::vector _wave_queue; SymbolType _next_symbol; bool _has_next_symbol; - - std::shared_ptr _tape; }; }