Dynamically use either inline_string escaping or uuencoding for extradata

Since luabins generates binary data which grows up to 3x by escaping,
it's more efficient to uuencode that instead.
A marker is placed as the first character of the value field, either
'e' for inline_string escaped text, or 'u' for uuencoded binary data.
The key is always inline_string escaped, as it will typically be
human readable.
This commit is contained in:
Niels Martin Hansen 2014-04-25 16:04:08 +02:00
parent bcd41bd986
commit f278c35f3f
3 changed files with 31 additions and 5 deletions

View File

@ -28,7 +28,7 @@ namespace agi { namespace ass {
/// Encode a blob of data, using ASS's nonstandard variant
template<typename RandomAccessRange>
std::string UUEncode(RandomAccessRange const& data) {
std::string UUEncode(RandomAccessRange const& data, bool insert_linebreaks=true) {
using std::begin;
using std::end;
@ -51,7 +51,7 @@ std::string UUEncode(RandomAccessRange const& data) {
for (size_t i = 0; i < std::min<size_t>(size - pos + 1, 4u); ++i) {
ret += dst[i] + 33;
if (++written == 80 && pos + 3 < size) {
if (insert_linebreaks && ++written == 80 && pos + 3 < size) {
written = 0;
ret += "\r\n";
}

View File

@ -22,6 +22,8 @@
#include "string_codec.h"
#include "subtitle_format.h"
#include <libaegisub/ass/uuencode.h>
#include <algorithm>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
@ -115,13 +117,25 @@ void AssParser::ParseGraphicsLine(std::string const& data) {
}
void AssParser::ParseExtradataLine(std::string const &data) {
static const boost::regex matcher("Data:[[:space:]]*(\\d+),([^,]+),(.*)");
static const boost::regex matcher("Data:[[:space:]]*(\\d+),([^,]+),(.)(.*)");
boost::match_results<std::string::const_iterator> mr;
if (boost::regex_match(data, mr, matcher)) {
auto id = boost::lexical_cast<uint32_t>(mr.str(1));
auto key = inline_string_decode(mr.str(2));
auto value = inline_string_decode(mr.str(3));
auto valuetype = mr.str(3);
auto value = mr.str(4);
if (valuetype == "e") {
// escaped/inline_string encoded
value = inline_string_decode(value);
} else if (valuetype == "u") {
// ass uuencoded
auto valuedata = agi::ass::UUDecode(value);
value = std::string(valuedata.begin(), valuedata.end());
} else {
// unknown, error?
value = "";
}
// ensure next_extradata_id is always at least 1 more than the largest existing id
target->next_extradata_id = std::max(id+1, target->next_extradata_id);

View File

@ -27,6 +27,7 @@
#include "text_file_writer.h"
#include "version.h"
#include <libaegisub/ass/uuencode.h>
#include <libaegisub/fs.h>
DEFINE_SIMPLE_EXCEPTION(AssParseError, SubtitleFormatParseError, "subtitle_io/parse/ass")
@ -129,7 +130,18 @@ struct Writer {
line += ",";
line += inline_string_encode(edi.second.first);
line += ",";
line += inline_string_encode(edi.second.second);
std::string encoded_data = inline_string_encode(edi.second.second);
if (4*edi.second.second.size() < 3*encoded_data.size()) {
// the inline_string encoding grew the data by more than uuencoding would
// so base64 encode it instead
line += "u"; // marker for uuencoding
encoded_data = agi::ass::UUEncode(edi.second.second, false);
printf("did uuencoding, original size=%lu, encoded size=%lu\n", edi.second.second.size(), encoded_data.size());
line += encoded_data;
} else {
line += "e"; // marker for inline_string encoding (escaping)
line += encoded_data;
}
file.WriteLineToFile(line);
}
}