Move binarystream functions to dedicated namespace
This commit is contained in:
parent
99b526335c
commit
6256506884
3 changed files with 290 additions and 100 deletions
|
@ -9,63 +9,250 @@
|
|||
#include <functional>
|
||||
#include <stdexcept>
|
||||
|
||||
struct binary_output_stream
|
||||
namespace binarystream
|
||||
{
|
||||
/**
|
||||
* Output binary stream.
|
||||
*/
|
||||
struct output
|
||||
{
|
||||
public:
|
||||
binary_output_stream();
|
||||
binary_output_stream(std::ostream& s);
|
||||
/**
|
||||
* Create a new output binary stream outputting to internal buffer.
|
||||
*/
|
||||
output();
|
||||
/**
|
||||
* Create a new output binary stream outputting to given output stream.
|
||||
*
|
||||
* Parameter s: The stream to output to.
|
||||
*/
|
||||
output(std::ostream& s);
|
||||
/**
|
||||
* Output a byte to stream (1 byte).
|
||||
*
|
||||
* Parameter byte: The byte to output.
|
||||
*/
|
||||
void byte(uint8_t byte);
|
||||
/**
|
||||
* Output a number to stream.
|
||||
*
|
||||
* Parameter number: The number to output.
|
||||
*/
|
||||
void number(uint64_t number);
|
||||
/**
|
||||
* Count number of bytes needed to store given number.
|
||||
*
|
||||
* Parameter number: The number to query.
|
||||
* Return: The number of bytes needed.
|
||||
*/
|
||||
size_t numberbytes(uint64_t number);
|
||||
/**
|
||||
* Output a 32-bit number to stream (4 byte).
|
||||
*
|
||||
* Parameter number: The number to output.
|
||||
*/
|
||||
void number32(uint32_t number);
|
||||
/**
|
||||
* Output a string with explicit length indication to the stream.
|
||||
*
|
||||
* This takes space for one number + number of bytes in the string.
|
||||
*
|
||||
* Parameter string: The number to output.
|
||||
*/
|
||||
void string(const std::string& string);
|
||||
/**
|
||||
* Output a string without length indication to the stream.
|
||||
*
|
||||
* This takes space for number of bytes in the string.
|
||||
*
|
||||
* Parameter string: The number to output.
|
||||
*/
|
||||
void string_implicit(const std::string& string);
|
||||
/**
|
||||
* Output a octet string without length indication to the stream.
|
||||
*
|
||||
* This takes space for number of bytes in the sequence.
|
||||
*
|
||||
* Parameter blob: The octet string to output.
|
||||
*/
|
||||
void blob_implicit(const std::vector<char>& blob);
|
||||
/**
|
||||
* Output a octet string without length indication to the stream.
|
||||
*
|
||||
* This takes space for number of bytes in the sequence.
|
||||
*
|
||||
* Parameter buf: The input buffer to read the octet string from.
|
||||
* Parameter bufsize: The size of buffer in bytes.
|
||||
*/
|
||||
void raw(const void* buf, size_t bufsize);
|
||||
void extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty = false);
|
||||
void extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty,
|
||||
/**
|
||||
* Output a extension substream into stream.
|
||||
*
|
||||
* Parameter tag: Tag identifying the extension member type.
|
||||
* Parameter fn: Function writing the contents of the extension substream.
|
||||
* Parameter even_empty: If true, the member is written even if empty (otherwise it is elided).
|
||||
*/
|
||||
void extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty = false);
|
||||
/**
|
||||
* Output a extension substream with known size into stream.
|
||||
*
|
||||
* In exchange for having to know the size of the payload, this is faster to write as it avoids buffering.
|
||||
*
|
||||
* Parameter tag: Tag identifying the extension member type.
|
||||
* Parameter fn: Function writing the contents of the extension substream.
|
||||
* Parameter even_empty: If true, the member is written even if empty (otherwise it is elided).
|
||||
* Parameter size_precognition: The known size of the payload.
|
||||
*/
|
||||
void extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty,
|
||||
size_t size_precognition);
|
||||
/**
|
||||
* Output explicit extension tag.
|
||||
*
|
||||
* This has to be followed by writing size bytes, forming the payload.
|
||||
*
|
||||
* Parameter tag: The Tag identifying the extension member type.
|
||||
* Parameter size: Size of the payload.
|
||||
*/
|
||||
void write_extension_tag(uint32_t tag, uint64_t size);
|
||||
/**
|
||||
* Get the output stream contents.
|
||||
*
|
||||
* The output stream has to use internal buffer for this to work.
|
||||
*
|
||||
* Returns: The internal buffer contents.
|
||||
*/
|
||||
std::string get();
|
||||
private:
|
||||
std::ostream& strm;
|
||||
std::ostringstream buf;
|
||||
};
|
||||
|
||||
struct binary_input_stream
|
||||
/**
|
||||
* Input binary stream.
|
||||
*/
|
||||
struct input
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Extension tag handler.
|
||||
*/
|
||||
struct binary_tag_handler
|
||||
{
|
||||
/**
|
||||
* The extension tag to activate on.
|
||||
*/
|
||||
uint32_t tag;
|
||||
std::function<void(binary_input_stream& s)> fn;
|
||||
/**
|
||||
* Handler function for the tag.
|
||||
*
|
||||
* Parameter s: The substream of extension.
|
||||
*/
|
||||
std::function<void(input& s)> fn;
|
||||
};
|
||||
binary_input_stream(std::istream& s);
|
||||
binary_input_stream(binary_input_stream& s, uint64_t len);
|
||||
/**
|
||||
* Create a new top-level input stream, reading from specified stream.
|
||||
*/
|
||||
input(std::istream& s);
|
||||
/**
|
||||
* Create a new input substream, under specified top-level stream and with specified length.
|
||||
*
|
||||
* Parameter s: The top-level stream.
|
||||
* Parameter len: Amount of payload in extension stream.
|
||||
*/
|
||||
input(input& s, uint64_t len);
|
||||
/**
|
||||
* Read a byte.
|
||||
*
|
||||
* Returns: The read byte.
|
||||
*/
|
||||
uint8_t byte();
|
||||
/**
|
||||
* Read a number.
|
||||
*
|
||||
* Returns: The read number.
|
||||
*/
|
||||
uint64_t number();
|
||||
/**
|
||||
* Read a 32-bit number.
|
||||
*
|
||||
* Returns: The read number.
|
||||
*/
|
||||
uint32_t number32();
|
||||
/**
|
||||
* Read a string with explicit length indication.
|
||||
*
|
||||
* Returns: The read string.
|
||||
*/
|
||||
std::string string();
|
||||
/**
|
||||
* Read a string without explicit length indication, quitting when reaching end of extension substream.
|
||||
*
|
||||
* Can be only used in extension substreams.
|
||||
*
|
||||
* Returns: The read string.
|
||||
*/
|
||||
std::string string_implicit();
|
||||
/**
|
||||
* Read a octet string without explicit length indication, quitting when reaching end of extension substream.
|
||||
*
|
||||
* Can be only used in extension substreams.
|
||||
*
|
||||
* Parameter blob: Store the read octet string here.
|
||||
*/
|
||||
void blob_implicit(std::vector<char>& blob);
|
||||
/**
|
||||
* Read a octet string of specified length.
|
||||
*
|
||||
* Parameter buf: Buffer to store the octet string to.
|
||||
* Parameter bufsize: The amount of data to read.
|
||||
*/
|
||||
void raw(void* buf, size_t bufsize);
|
||||
void extension(std::function<void(uint32_t tag, binary_input_stream& s)> fn);
|
||||
/**
|
||||
* Read extension substreams.
|
||||
*
|
||||
* This reads substreams until the end of stream.
|
||||
*
|
||||
* Parameter fn: Function handling the read extension substream.
|
||||
* Parameter tag: The type tag of read substream.
|
||||
* Parameter s: The substream with contents of extension substream.
|
||||
*/
|
||||
void extension(std::function<void(uint32_t tag, input& s)> fn);
|
||||
/**
|
||||
* Read extension substreams.
|
||||
*
|
||||
* This reads substreams until the end of stream.
|
||||
*
|
||||
* Parameter funcs: Table of functions to call for each known extension type.
|
||||
* Parameter default_hdlr: Handler for unknown types (parameters as in other ::extension()).
|
||||
*/
|
||||
void extension(std::initializer_list<binary_tag_handler> funcs,
|
||||
std::function<void(uint32_t tag, binary_input_stream& s)> default_hdlr);
|
||||
std::function<void(uint32_t tag, input& s)> default_hdlr);
|
||||
/**
|
||||
* Get number of bytes left in substream.
|
||||
*
|
||||
* Can only be used for substreams.
|
||||
*
|
||||
* Returns: Number of bytes left.
|
||||
*/
|
||||
uint64_t get_left()
|
||||
{
|
||||
if(!parent)
|
||||
throw std::logic_error("binary_input_stream::get_left() can only be used in substreams");
|
||||
throw std::logic_error("binarystream::input::get_left() can only be used in substreams");
|
||||
return left;
|
||||
}
|
||||
private:
|
||||
bool read(char* buf, size_t size, bool allow_none = false);
|
||||
void flush();
|
||||
binary_input_stream* parent;
|
||||
input* parent;
|
||||
std::istream& strm;
|
||||
uint64_t left;
|
||||
};
|
||||
|
||||
void binary_null_default(uint32_t tag, binary_input_stream& s);
|
||||
/**
|
||||
* Do nothing. Handy as second parameter for two-parameter output::extension() if the table enumerates all non-
|
||||
* ignored types.
|
||||
*/
|
||||
void null_default(uint32_t tag, input& s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -83,7 +83,7 @@ void write_linefile(zip_writer& w, const std::string& member, const std::string&
|
|||
|
||||
namespace
|
||||
{
|
||||
void binary_read_movie(binary_input_stream& in, controller_frame_vector& v)
|
||||
void binary_read_movie(binarystream::input& in, controller_frame_vector& v)
|
||||
{
|
||||
uint64_t stride = v.get_stride();
|
||||
uint64_t pageframes = v.get_frames_per_page();
|
||||
|
@ -100,7 +100,7 @@ namespace
|
|||
v.resize(vsize);
|
||||
}
|
||||
|
||||
void binary_write_movie(binary_output_stream& out, controller_frame_vector& v)
|
||||
void binary_write_movie(binarystream::output& out, controller_frame_vector& v)
|
||||
{
|
||||
uint64_t pages = v.get_page_count();
|
||||
uint64_t stride = v.get_stride();
|
||||
|
@ -519,7 +519,7 @@ moviefile::brief_info::brief_info(const std::string& filename)
|
|||
|
||||
void moviefile::brief_info::binary_io(std::istream& _stream)
|
||||
{
|
||||
binary_input_stream in(_stream);
|
||||
binarystream::input in(_stream);
|
||||
sysregion = in.string();
|
||||
//Discard the settings.
|
||||
while(in.byte()) {
|
||||
|
@ -527,17 +527,17 @@ void moviefile::brief_info::binary_io(std::istream& _stream)
|
|||
in.string();
|
||||
}
|
||||
in.extension({
|
||||
{TAG_CORE_VERSION, [this](binary_input_stream& s) {
|
||||
{TAG_CORE_VERSION, [this](binarystream::input& s) {
|
||||
this->corename = s.string_implicit();
|
||||
}},{TAG_PROJECT_ID, [this](binary_input_stream& s) {
|
||||
}},{TAG_PROJECT_ID, [this](binarystream::input& s) {
|
||||
this->projectid = s.string_implicit();
|
||||
}},{TAG_SAVESTATE, [this](binary_input_stream& s) {
|
||||
}},{TAG_SAVESTATE, [this](binarystream::input& s) {
|
||||
this->current_frame = s.number();
|
||||
}},{TAG_RRDATA, [this](binary_input_stream& s) {
|
||||
}},{TAG_RRDATA, [this](binarystream::input& s) {
|
||||
std::vector<char> c_rrdata;
|
||||
s.blob_implicit(c_rrdata);
|
||||
this->rerecords = rrdata.count(c_rrdata);
|
||||
}},{TAG_ROMHASH, [this](binary_input_stream& s) {
|
||||
}},{TAG_ROMHASH, [this](binarystream::input& s) {
|
||||
uint8_t n = s.byte();
|
||||
std::string h = s.string_implicit();
|
||||
if(n > 2 * ROM_SLOT_COUNT)
|
||||
|
@ -546,14 +546,14 @@ void moviefile::brief_info::binary_io(std::istream& _stream)
|
|||
this->hashxml[n >> 1] = h;
|
||||
else
|
||||
this->hash[n >> 1] = h;
|
||||
}},{TAG_ROMHINT, [this](binary_input_stream& s) {
|
||||
}},{TAG_ROMHINT, [this](binarystream::input& s) {
|
||||
uint8_t n = s.byte();
|
||||
std::string h = s.string_implicit();
|
||||
if(n > ROM_SLOT_COUNT)
|
||||
return;
|
||||
this->hint[n] = h;
|
||||
}}
|
||||
}, binary_null_default);
|
||||
}, binarystream::null_default);
|
||||
}
|
||||
|
||||
moviefile::moviefile() throw(std::bad_alloc)
|
||||
|
@ -799,49 +799,49 @@ Following need to be saved:
|
|||
*/
|
||||
void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
binary_output_stream out(_stream);
|
||||
binarystream::output out(_stream);
|
||||
out.string(gametype->get_name());
|
||||
write_settings<binary_output_stream>(out, settings, gametype->get_type().get_settings(),
|
||||
[](binary_output_stream& s, const std::string& name, const std::string& value) -> void {
|
||||
write_settings<binarystream::output>(out, settings, gametype->get_type().get_settings(),
|
||||
[](binarystream::output& s, const std::string& name, const std::string& value) -> void {
|
||||
s.byte(0x01);
|
||||
s.string(name);
|
||||
s.string(value);
|
||||
});
|
||||
out.byte(0x00);
|
||||
|
||||
out.extension(TAG_MOVIE_TIME, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_MOVIE_TIME, [this](binarystream::output& s) {
|
||||
s.number(this->movie_rtc_second);
|
||||
s.number(this->movie_rtc_subsecond);
|
||||
});
|
||||
|
||||
out.extension(TAG_PROJECT_ID, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_PROJECT_ID, [this](binarystream::output& s) {
|
||||
s.string_implicit(this->projectid);
|
||||
});
|
||||
|
||||
out.extension(TAG_CORE_VERSION, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_CORE_VERSION, [this](binarystream::output& s) {
|
||||
this->coreversion = this->gametype->get_type().get_core_identifier();
|
||||
s.string_implicit(this->coreversion);
|
||||
});
|
||||
|
||||
for(unsigned i = 0; i < ROM_SLOT_COUNT; i++) {
|
||||
out.extension(TAG_ROMHASH, [this, i](binary_output_stream& s) {
|
||||
out.extension(TAG_ROMHASH, [this, i](binarystream::output& s) {
|
||||
if(!this->romimg_sha256[i].length()) return;
|
||||
s.byte(2 * i);
|
||||
s.string_implicit(this->romimg_sha256[i]);
|
||||
});
|
||||
out.extension(TAG_ROMHASH, [this, i](binary_output_stream& s) {
|
||||
out.extension(TAG_ROMHASH, [this, i](binarystream::output& s) {
|
||||
if(!this->romxml_sha256[i].length()) return;
|
||||
s.byte(2 * i + 1);
|
||||
s.string_implicit(this->romxml_sha256[i]);
|
||||
});
|
||||
out.extension(TAG_ROMHINT, [this, i](binary_output_stream& s) {
|
||||
out.extension(TAG_ROMHINT, [this, i](binarystream::output& s) {
|
||||
if(!this->namehint[i].length()) return;
|
||||
s.byte(i);
|
||||
s.string_implicit(this->namehint[i]);
|
||||
});
|
||||
}
|
||||
|
||||
out.extension(TAG_RRDATA, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_RRDATA, [this](binarystream::output& s) {
|
||||
uint64_t count;
|
||||
std::vector<char> rrd;
|
||||
count = rrdata.write(rrd);
|
||||
|
@ -849,16 +849,16 @@ void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runt
|
|||
});
|
||||
|
||||
for(auto i : movie_sram)
|
||||
out.extension(TAG_MOVIE_SRAM, [&i](binary_output_stream& s) {
|
||||
out.extension(TAG_MOVIE_SRAM, [&i](binarystream::output& s) {
|
||||
s.string(i.first);
|
||||
s.blob_implicit(i.second);
|
||||
});
|
||||
|
||||
out.extension(TAG_ANCHOR_SAVE, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_ANCHOR_SAVE, [this](binarystream::output& s) {
|
||||
s.blob_implicit(this->anchor_savestate);
|
||||
});
|
||||
if(is_savestate) {
|
||||
out.extension(TAG_SAVESTATE, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_SAVESTATE, [this](binarystream::output& s) {
|
||||
s.number(this->save_frame);
|
||||
s.number(this->lagged_frames);
|
||||
s.number(this->rtc_second);
|
||||
|
@ -872,47 +872,47 @@ void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runt
|
|||
out.numberbytes(rtc_subsecond) + out.numberbytes(pollcounters.size()) +
|
||||
4 * pollcounters.size() + 1 + savestate.size());
|
||||
|
||||
out.extension(TAG_HOSTMEMORY, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_HOSTMEMORY, [this](binarystream::output& s) {
|
||||
s.blob_implicit(this->host_memory);
|
||||
});
|
||||
|
||||
out.extension(TAG_SCREENSHOT, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_SCREENSHOT, [this](binarystream::output& s) {
|
||||
s.blob_implicit(this->screenshot);
|
||||
}, true, screenshot.size());
|
||||
|
||||
for(auto i : sram) {
|
||||
out.extension(TAG_SAVE_SRAM, [&i](binary_output_stream& s) {
|
||||
out.extension(TAG_SAVE_SRAM, [&i](binarystream::output& s) {
|
||||
s.string(i.first);
|
||||
s.blob_implicit(i.second);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
out.extension(TAG_GAMENAME, [this](binary_output_stream& s) {
|
||||
out.extension(TAG_GAMENAME, [this](binarystream::output& s) {
|
||||
s.string_implicit(this->gamename);
|
||||
});
|
||||
|
||||
for(auto i : subtitles)
|
||||
out.extension(TAG_SUBTITLE, [&i](binary_output_stream& s) {
|
||||
out.extension(TAG_SUBTITLE, [&i](binarystream::output& s) {
|
||||
s.number(i.first.get_frame());
|
||||
s.number(i.first.get_length());
|
||||
s.string_implicit(i.second);
|
||||
});
|
||||
|
||||
for(auto i : authors)
|
||||
out.extension(TAG_AUTHOR, [&i](binary_output_stream& s) {
|
||||
out.extension(TAG_AUTHOR, [&i](binarystream::output& s) {
|
||||
s.string(i.first);
|
||||
s.string_implicit(i.second);
|
||||
});
|
||||
|
||||
for(auto i : active_macros)
|
||||
out.extension(TAG_MACRO, [&i](binary_output_stream& s) {
|
||||
out.extension(TAG_MACRO, [&i](binarystream::output& s) {
|
||||
s.number(i.second);
|
||||
s.string_implicit(i.first);
|
||||
});
|
||||
|
||||
for(auto i : ramcontent) {
|
||||
out.extension(TAG_RAMCONTENT, [&i](binary_output_stream& s) {
|
||||
out.extension(TAG_RAMCONTENT, [&i](binarystream::output& s) {
|
||||
s.string(i.first);
|
||||
s.blob_implicit(i.second);
|
||||
});
|
||||
|
@ -923,7 +923,7 @@ void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runt
|
|||
|
||||
void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
binary_input_stream in(_stream);
|
||||
binarystream::input in(_stream);
|
||||
std::string tmp = in.string();
|
||||
try {
|
||||
gametype = &romtype.lookup_sysregion(tmp);
|
||||
|
@ -941,35 +941,35 @@ void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::
|
|||
input.clear(ports);
|
||||
|
||||
in.extension({
|
||||
{TAG_ANCHOR_SAVE, [this](binary_input_stream& s) {
|
||||
{TAG_ANCHOR_SAVE, [this](binarystream::input& s) {
|
||||
s.blob_implicit(this->anchor_savestate);
|
||||
}},{TAG_AUTHOR, [this](binary_input_stream& s) {
|
||||
}},{TAG_AUTHOR, [this](binarystream::input& s) {
|
||||
std::string a = s.string();
|
||||
std::string b = s.string_implicit();
|
||||
this->authors.push_back(std::make_pair(a, b));
|
||||
}},{TAG_CORE_VERSION, [this](binary_input_stream& s) {
|
||||
}},{TAG_CORE_VERSION, [this](binarystream::input& s) {
|
||||
this->coreversion = s.string_implicit();
|
||||
}},{TAG_GAMENAME, [this](binary_input_stream& s) {
|
||||
}},{TAG_GAMENAME, [this](binarystream::input& s) {
|
||||
this->gamename = s.string_implicit();
|
||||
}},{TAG_HOSTMEMORY, [this](binary_input_stream& s) {
|
||||
}},{TAG_HOSTMEMORY, [this](binarystream::input& s) {
|
||||
s.blob_implicit(this->host_memory);
|
||||
}},{TAG_MACRO, [this](binary_input_stream& s) {
|
||||
}},{TAG_MACRO, [this](binarystream::input& s) {
|
||||
uint64_t n = s.number();
|
||||
this->active_macros[s.string_implicit()] = n;
|
||||
}},{TAG_MOVIE, [this](binary_input_stream& s) {
|
||||
}},{TAG_MOVIE, [this](binarystream::input& s) {
|
||||
binary_read_movie(s, input);
|
||||
}},{TAG_MOVIE_SRAM, [this](binary_input_stream& s) {
|
||||
}},{TAG_MOVIE_SRAM, [this](binarystream::input& s) {
|
||||
std::string a = s.string();
|
||||
s.blob_implicit(this->movie_sram[a]);
|
||||
}},{TAG_RAMCONTENT, [this](binary_input_stream& s) {
|
||||
}},{TAG_RAMCONTENT, [this](binarystream::input& s) {
|
||||
std::string a = s.string();
|
||||
s.blob_implicit(this->ramcontent[a]);
|
||||
}},{TAG_MOVIE_TIME, [this](binary_input_stream& s) {
|
||||
}},{TAG_MOVIE_TIME, [this](binarystream::input& s) {
|
||||
this->movie_rtc_second = s.number();
|
||||
this->movie_rtc_subsecond = s.number();
|
||||
}},{TAG_PROJECT_ID, [this](binary_input_stream& s) {
|
||||
}},{TAG_PROJECT_ID, [this](binarystream::input& s) {
|
||||
this->projectid = s.string_implicit();
|
||||
}},{TAG_ROMHASH, [this](binary_input_stream& s) {
|
||||
}},{TAG_ROMHASH, [this](binarystream::input& s) {
|
||||
uint8_t n = s.byte();
|
||||
std::string h = s.string_implicit();
|
||||
if(n > 2 * ROM_SLOT_COUNT)
|
||||
|
@ -978,19 +978,19 @@ void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::
|
|||
romxml_sha256[n >> 1] = h;
|
||||
else
|
||||
romimg_sha256[n >> 1] = h;
|
||||
}},{TAG_ROMHINT, [this](binary_input_stream& s) {
|
||||
}},{TAG_ROMHINT, [this](binarystream::input& s) {
|
||||
uint8_t n = s.byte();
|
||||
std::string h = s.string_implicit();
|
||||
if(n > ROM_SLOT_COUNT)
|
||||
return;
|
||||
namehint[n] = h;
|
||||
}},{TAG_RRDATA, [this](binary_input_stream& s) {
|
||||
}},{TAG_RRDATA, [this](binarystream::input& s) {
|
||||
s.blob_implicit(this->c_rrdata);
|
||||
this->rerecords = (stringfmt() << rrdata.count(c_rrdata)).str();
|
||||
}},{TAG_SAVE_SRAM, [this](binary_input_stream& s) {
|
||||
}},{TAG_SAVE_SRAM, [this](binarystream::input& s) {
|
||||
std::string a = s.string();
|
||||
s.blob_implicit(this->sram[a]);
|
||||
}},{TAG_SAVESTATE, [this](binary_input_stream& s) {
|
||||
}},{TAG_SAVESTATE, [this](binarystream::input& s) {
|
||||
this->is_savestate = true;
|
||||
this->save_frame = s.number();
|
||||
this->lagged_frames = s.number();
|
||||
|
@ -1001,15 +1001,15 @@ void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::
|
|||
i = s.number32();
|
||||
this->poll_flag = (s.byte() != 0);
|
||||
s.blob_implicit(this->savestate);
|
||||
}},{TAG_SCREENSHOT, [this](binary_input_stream& s) {
|
||||
}},{TAG_SCREENSHOT, [this](binarystream::input& s) {
|
||||
s.blob_implicit(this->screenshot);
|
||||
}},{TAG_SUBTITLE, [this](binary_input_stream& s) {
|
||||
}},{TAG_SUBTITLE, [this](binarystream::input& s) {
|
||||
uint64_t f = s.number();
|
||||
uint64_t l = s.number();
|
||||
std::string x = s.string_implicit();
|
||||
this->subtitles[moviefile_subtiming(f, l)] = x;
|
||||
}}
|
||||
}, binary_null_default);
|
||||
}, binarystream::null_default);
|
||||
}
|
||||
|
||||
uint64_t moviefile::get_frame_count() throw()
|
||||
|
|
|
@ -6,24 +6,26 @@
|
|||
#include <iterator>
|
||||
#include <map>
|
||||
|
||||
namespace binarystream
|
||||
{
|
||||
const uint32_t TAG_ = 0xaddb2d86;
|
||||
|
||||
binary_output_stream::binary_output_stream()
|
||||
output::output()
|
||||
: strm(buf)
|
||||
{
|
||||
}
|
||||
|
||||
binary_output_stream::binary_output_stream(std::ostream& s)
|
||||
output::output(std::ostream& s)
|
||||
: strm(s)
|
||||
{
|
||||
}
|
||||
|
||||
void binary_output_stream::byte(uint8_t byte)
|
||||
void output::byte(uint8_t byte)
|
||||
{
|
||||
strm.write(reinterpret_cast<char*>(&byte), 1);
|
||||
}
|
||||
|
||||
void binary_output_stream::number(uint64_t number)
|
||||
void output::number(uint64_t number)
|
||||
{
|
||||
char data[10];
|
||||
size_t len = 0;
|
||||
|
@ -35,7 +37,7 @@ void binary_output_stream::number(uint64_t number)
|
|||
strm.write(data, len);
|
||||
}
|
||||
|
||||
size_t binary_output_stream::numberbytes(uint64_t number)
|
||||
size_t output::numberbytes(uint64_t number)
|
||||
{
|
||||
size_t o = 0;
|
||||
do {
|
||||
|
@ -45,44 +47,44 @@ size_t binary_output_stream::numberbytes(uint64_t number)
|
|||
return o;
|
||||
}
|
||||
|
||||
void binary_output_stream::number32(uint32_t number)
|
||||
void output::number32(uint32_t number)
|
||||
{
|
||||
char data[4];
|
||||
write32ube(data, number);
|
||||
strm.write(data, 4);
|
||||
}
|
||||
|
||||
void binary_output_stream::string(const std::string& string)
|
||||
void output::string(const std::string& string)
|
||||
{
|
||||
number(string.length());
|
||||
std::copy(string.begin(), string.end(), std::ostream_iterator<char>(strm));
|
||||
}
|
||||
|
||||
void binary_output_stream::string_implicit(const std::string& string)
|
||||
void output::string_implicit(const std::string& string)
|
||||
{
|
||||
std::copy(string.begin(), string.end(), std::ostream_iterator<char>(strm));
|
||||
}
|
||||
|
||||
void binary_output_stream::blob_implicit(const std::vector<char>& blob)
|
||||
void output::blob_implicit(const std::vector<char>& blob)
|
||||
{
|
||||
strm.write(&blob[0], blob.size());
|
||||
}
|
||||
|
||||
void binary_output_stream::raw(const void* buf, size_t bufsize)
|
||||
void output::raw(const void* buf, size_t bufsize)
|
||||
{
|
||||
strm.write(reinterpret_cast<const char*>(buf), bufsize);
|
||||
}
|
||||
|
||||
void binary_output_stream::write_extension_tag(uint32_t tag, uint64_t size)
|
||||
void output::write_extension_tag(uint32_t tag, uint64_t size)
|
||||
{
|
||||
number32(TAG_);
|
||||
number32(tag);
|
||||
number(size);
|
||||
}
|
||||
|
||||
void binary_output_stream::extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty)
|
||||
void output::extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty)
|
||||
{
|
||||
binary_output_stream tmp;
|
||||
output tmp;
|
||||
fn(tmp);
|
||||
std::string str = tmp.get();
|
||||
if(!even_empty && !str.length())
|
||||
|
@ -92,7 +94,7 @@ void binary_output_stream::extension(uint32_t tag, std::function<void(binary_out
|
|||
string(str);
|
||||
}
|
||||
|
||||
void binary_output_stream::extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty,
|
||||
void output::extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty,
|
||||
size_t size_precognition)
|
||||
{
|
||||
if(!even_empty && !size_precognition)
|
||||
|
@ -104,21 +106,21 @@ void binary_output_stream::extension(uint32_t tag, std::function<void(binary_out
|
|||
}
|
||||
|
||||
|
||||
std::string binary_output_stream::get()
|
||||
std::string output::get()
|
||||
{
|
||||
if(&strm != &buf)
|
||||
throw std::logic_error("Get can only be used without explicit sink");
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
uint8_t binary_input_stream::byte()
|
||||
uint8_t input::byte()
|
||||
{
|
||||
char byte;
|
||||
read(&byte, 1);
|
||||
return byte;
|
||||
}
|
||||
|
||||
uint64_t binary_input_stream::number()
|
||||
uint64_t input::number()
|
||||
{
|
||||
uint64_t s = 0;
|
||||
int sh = 0;
|
||||
|
@ -131,14 +133,14 @@ uint64_t binary_input_stream::number()
|
|||
return s;
|
||||
}
|
||||
|
||||
uint32_t binary_input_stream::number32()
|
||||
uint32_t input::number32()
|
||||
{
|
||||
char c[4];
|
||||
read(c, 4);
|
||||
return read32ube(c);
|
||||
}
|
||||
|
||||
std::string binary_input_stream::string()
|
||||
std::string input::string()
|
||||
{
|
||||
size_t sz = number();
|
||||
std::vector<char> _r;
|
||||
|
@ -148,10 +150,10 @@ std::string binary_input_stream::string()
|
|||
return r;
|
||||
}
|
||||
|
||||
std::string binary_input_stream::string_implicit()
|
||||
std::string input::string_implicit()
|
||||
{
|
||||
if(!parent)
|
||||
throw std::logic_error("binary_input_stream::string_implicit() can only be used in substreams");
|
||||
throw std::logic_error("binarystream::input::string_implicit() can only be used in substreams");
|
||||
std::vector<char> _r;
|
||||
_r.resize(left);
|
||||
read(&_r[0], left);
|
||||
|
@ -159,40 +161,40 @@ std::string binary_input_stream::string_implicit()
|
|||
return r;
|
||||
}
|
||||
|
||||
void binary_input_stream::blob_implicit(std::vector<char>& blob)
|
||||
void input::blob_implicit(std::vector<char>& blob)
|
||||
{
|
||||
if(!parent)
|
||||
throw std::logic_error("binary_input_stream::string_implicit() can only be used in substreams");
|
||||
throw std::logic_error("binarystream::input::string_implicit() can only be used in substreams");
|
||||
blob.resize(left);
|
||||
read(&blob[0], left);
|
||||
}
|
||||
|
||||
binary_input_stream::binary_input_stream(std::istream& s)
|
||||
input::input(std::istream& s)
|
||||
: strm(s), left(0), parent(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
binary_input_stream::binary_input_stream(binary_input_stream& s, uint64_t len)
|
||||
input::input(input& s, uint64_t len)
|
||||
: strm(s.strm), left(len), parent(&s)
|
||||
{
|
||||
if(parent->parent && left > parent->left)
|
||||
throw std::runtime_error("Substream length greater than its parent");
|
||||
}
|
||||
|
||||
void binary_input_stream::raw(void* buf, size_t bufsize)
|
||||
void input::raw(void* buf, size_t bufsize)
|
||||
{
|
||||
read(reinterpret_cast<char*>(buf), bufsize);
|
||||
}
|
||||
|
||||
void binary_input_stream::extension(std::function<void(uint32_t tag, binary_input_stream& s)> fn)
|
||||
void input::extension(std::function<void(uint32_t tag, input& s)> fn)
|
||||
{
|
||||
extension({}, fn);
|
||||
}
|
||||
|
||||
void binary_input_stream::extension(std::initializer_list<binary_tag_handler> funcs,
|
||||
std::function<void(uint32_t tag, binary_input_stream& s)> default_hdlr)
|
||||
void input::extension(std::initializer_list<binary_tag_handler> funcs,
|
||||
std::function<void(uint32_t tag, input& s)> default_hdlr)
|
||||
{
|
||||
std::map<uint32_t, std::function<void(binary_input_stream& s)>> fn;
|
||||
std::map<uint32_t, std::function<void(input& s)>> fn;
|
||||
for(auto i : funcs)
|
||||
fn[i.tag] = i.fn;
|
||||
while(!parent || left > 0) {
|
||||
|
@ -204,7 +206,7 @@ void binary_input_stream::extension(std::initializer_list<binary_tag_handler> fu
|
|||
throw std::runtime_error("Binary file packet structure desync");
|
||||
uint32_t tag = number32();
|
||||
uint64_t size = number();
|
||||
binary_input_stream ss(*this, size);
|
||||
input ss(*this, size);
|
||||
if(fn.count(tag))
|
||||
fn[tag](ss);
|
||||
else
|
||||
|
@ -213,16 +215,16 @@ void binary_input_stream::extension(std::initializer_list<binary_tag_handler> fu
|
|||
}
|
||||
}
|
||||
|
||||
void binary_input_stream::flush()
|
||||
void input::flush()
|
||||
{
|
||||
if(!parent)
|
||||
throw std::logic_error("binary_input_stream::flush() can only be used in substreams");
|
||||
throw std::logic_error("binarystream::input::flush() can only be used in substreams");
|
||||
char buf[256];
|
||||
while(left)
|
||||
read(buf, min(left, (uint64_t)256));
|
||||
}
|
||||
|
||||
bool binary_input_stream::read(char* buf, size_t size, bool allow_none)
|
||||
bool input::read(char* buf, size_t size, bool allow_none)
|
||||
{
|
||||
if(parent) {
|
||||
if(left == 0 && allow_none)
|
||||
|
@ -242,7 +244,8 @@ bool binary_input_stream::read(char* buf, size_t size, bool allow_none)
|
|||
return true;
|
||||
}
|
||||
|
||||
void binary_null_default(uint32_t tag, binary_input_stream& s)
|
||||
void null_default(uint32_t tag, input& s)
|
||||
{
|
||||
//no-op
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue