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 {
|
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 UUEncode(std::vector<char> const& data) {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.reserve((data.size() * 4 + 2) / 3 + data.size() / 80 * 2);
|
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
|
/// Encode a blob of data, using ASS's nonstandard variant
|
||||||
std::string UUEncode(std::vector<char> const& data);
|
std::string UUEncode(std::vector<char> const& data);
|
||||||
|
|
||||||
/// Decode an ASS uuencoded string which has had its newlines stripped
|
/// Decode an ASS uuencoded string
|
||||||
std::vector<char> UUDecode(std::string const& str);
|
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 <libaegisub/io.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/range/iterator_range.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
AssAttachment::AssAttachment(std::string const& name, AssEntryGroup group)
|
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 {
|
void AssAttachment::Extract(agi::fs::path const& filename) const {
|
||||||
auto header_end = entry_data.get().find('\n');
|
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 {
|
std::string AssAttachment::GetFileName(bool raw) const {
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
class lagi_option : public libagi {
|
class lagi_option : public libagi {
|
||||||
protected:
|
protected:
|
||||||
std::string default_opt;
|
std::string default_opt;
|
||||||
|
|
|
@ -48,7 +48,7 @@ TEST(lagi_uuencode, random_blobs_roundtrip) {
|
||||||
std::vector<char> data;
|
std::vector<char> data;
|
||||||
|
|
||||||
for (size_t len = 0; len < 200; ++len) {
|
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());
|
data.push_back(rand());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue