forked from mia/Aegisub
parent
b1ecefe0f2
commit
50f92ef573
5 changed files with 34 additions and 25 deletions
|
@ -26,27 +26,6 @@
|
|||
|
||||
namespace agi { namespace ass {
|
||||
|
||||
std::vector<char> UUDecode(std::string const& str) {
|
||||
std::vector<char> ret;
|
||||
ret.reserve(str.size() * 3 / 4);
|
||||
|
||||
for(size_t pos = 0; pos + 1 < str.size(); pos += 4) {
|
||||
size_t bytes = std::min<size_t>(str.size() - pos, 4);
|
||||
|
||||
unsigned char src[4] = { '\0', '\0', '\0', '\0' };
|
||||
for (size_t i = 0; i < bytes; ++i)
|
||||
src[i] = str[pos + i] - 33;
|
||||
|
||||
ret.push_back((src[0] << 2) | (src[1] >> 4));
|
||||
if (bytes > 2)
|
||||
ret.push_back(((src[1] & 0xF) << 4) | (src[2] >> 2));
|
||||
if (bytes > 3)
|
||||
ret.push_back(((src[2] & 0x3) << 6) | (src[3]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string UUEncode(std::vector<char> const& data) {
|
||||
std::string ret;
|
||||
ret.reserve((data.size() * 4 + 2) / 3 + data.size() / 80 * 2);
|
||||
|
|
|
@ -22,7 +22,33 @@ namespace agi {
|
|||
/// Encode a blob of data, using ASS's nonstandard variant
|
||||
std::string UUEncode(std::vector<char> const& data);
|
||||
|
||||
/// Decode an ASS uuencoded string which has had its newlines stripped
|
||||
std::vector<char> UUDecode(std::string const& str);
|
||||
/// Decode an ASS uuencoded string
|
||||
template<typename String>
|
||||
std::vector<char> UUDecode(String const& str) {
|
||||
std::vector<char> ret;
|
||||
size_t len = std::end(str) - std::begin(str);
|
||||
ret.reserve(len * 3 / 4);
|
||||
|
||||
for (size_t pos = 0; pos + 1 < len; ) {
|
||||
size_t bytes = 0;
|
||||
unsigned char src[4] = { '\0', '\0', '\0', '\0' };
|
||||
for (size_t i = 0; i < 4 && pos < len; ) {
|
||||
char c = str[pos++];
|
||||
if (c && c != '\n' && c != '\r') {
|
||||
src[i++] = c - 33;
|
||||
++bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes > 1)
|
||||
ret.push_back((src[0] << 2) | (src[1] >> 4));
|
||||
if (bytes > 2)
|
||||
ret.push_back(((src[1] & 0xF) << 4) | (src[2] >> 2));
|
||||
if (bytes > 3)
|
||||
ret.push_back(((src[2] & 0x3) << 6) | (src[3]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <libaegisub/io.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <fstream>
|
||||
|
||||
AssAttachment::AssAttachment(std::string const& name, AssEntryGroup group)
|
||||
|
@ -67,7 +68,8 @@ size_t AssAttachment::GetSize() const {
|
|||
|
||||
void AssAttachment::Extract(agi::fs::path const& filename) const {
|
||||
auto header_end = entry_data.get().find('\n');
|
||||
agi::io::Save(filename, true).Get().write(&entry_data.get()[header_end + 1], entry_data.get().size() - header_end - 1);
|
||||
auto decoded = agi::ass::UUDecode(boost::make_iterator_range(entry_data.get().begin() + header_end + 1, entry_data.get().end()));
|
||||
agi::io::Save(filename, true).Get().write(&decoded[0], decoded.size());
|
||||
}
|
||||
|
||||
std::string AssAttachment::GetFileName(bool raw) const {
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
class lagi_option : public libagi {
|
||||
protected:
|
||||
std::string default_opt;
|
||||
|
|
|
@ -48,7 +48,7 @@ TEST(lagi_uuencode, random_blobs_roundtrip) {
|
|||
std::vector<char> data;
|
||||
|
||||
for (size_t len = 0; len < 200; ++len) {
|
||||
EXPECT_EQ(data, UUDecode(boost::replace_all_copy(UUEncode(data), "\r\n", "")));
|
||||
EXPECT_EQ(data, UUDecode(UUEncode(data)));
|
||||
data.push_back(rand());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue