forked from mia/Aegisub
Store ass attachments in the encoded form in memory
This marginally increases memory use, but vastly speeds up pretty much everything when a file has attachments (other than extracting the attachments, but that's generally IO-bound anyway).
This commit is contained in:
parent
73217fd0e9
commit
a872fc50b8
3 changed files with 53 additions and 96 deletions
|
@ -1,37 +1,19 @@
|
||||||
// Copyright (c) 2006, Rodrigo Braz Monteiro
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
//
|
||||||
// Aegisub Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
/// @file ass_attachment.cpp
|
|
||||||
/// @brief Manage files embedded in subtitles
|
|
||||||
/// @ingroup subs_storage
|
|
||||||
///
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "ass_attachment.h"
|
#include "ass_attachment.h"
|
||||||
|
@ -49,50 +31,52 @@ AssAttachment::AssAttachment(std::string const& name, AssEntryGroup group)
|
||||||
}
|
}
|
||||||
|
|
||||||
AssAttachment::AssAttachment(agi::fs::path const& name, AssEntryGroup group)
|
AssAttachment::AssAttachment(agi::fs::path const& name, AssEntryGroup group)
|
||||||
: data(new std::vector<char>)
|
: filename(name.filename().string())
|
||||||
, filename(name.filename().string())
|
|
||||||
, group(group)
|
, group(group)
|
||||||
{
|
{
|
||||||
if (boost::iends_with(filename, ".ttf"))
|
// SSA stuffs some information about the font in the embeded filename, but
|
||||||
filename = filename.substr(0, filename.size() - 4) + "_0" + filename.substr(filename.size() - 4);
|
// nothing else uses it so just do the absolute minimum (0 is the encoding)
|
||||||
|
if (boost::iends_with(filename.get(), ".ttf"))
|
||||||
|
filename = filename.get().substr(0, filename.get().size() - 4) + "_0" + filename.get().substr(filename.get().size() - 4);
|
||||||
|
|
||||||
|
std::vector<char> data;
|
||||||
std::unique_ptr<std::istream> file(agi::io::Open(name, true));
|
std::unique_ptr<std::istream> file(agi::io::Open(name, true));
|
||||||
file->seekg(0, std::ios::end);
|
file->seekg(0, std::ios::end);
|
||||||
data->resize(file->tellg());
|
data.resize(file->tellg());
|
||||||
file->seekg(0, std::ios::beg);
|
file->seekg(0, std::ios::beg);
|
||||||
file->read(&(*data)[0], data->size());
|
file->read(&data[0], data.size());
|
||||||
|
|
||||||
|
entry_data = (group == ENTRY_FONT ? "fontname: " : "filename: ") + filename.get() + "\r\n";
|
||||||
|
entry_data = entry_data.get() + agi::ass::UUEncode(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssEntry *AssAttachment::Clone() const {
|
AssEntry *AssAttachment::Clone() const {
|
||||||
AssAttachment *clone = new AssAttachment(filename, group);
|
AssAttachment *clone = new AssAttachment(filename, group);
|
||||||
clone->data = data;
|
clone->entry_data = entry_data;
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string AssAttachment::GetEntryData() const {
|
const std::string AssAttachment::GetEntryData() const {
|
||||||
std::string entryData = (group == ENTRY_FONT ? "fontname: " : "filename: ") + filename + "\r\n";
|
return entry_data;
|
||||||
if (data)
|
}
|
||||||
entryData += agi::ass::UUEncode(*data);
|
|
||||||
return entryData;
|
size_t AssAttachment::GetSize() const {
|
||||||
|
auto header_end = entry_data.get().find('\n');
|
||||||
|
return entry_data.get().size() - header_end - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssAttachment::Extract(agi::fs::path const& filename) const {
|
void AssAttachment::Extract(agi::fs::path const& filename) const {
|
||||||
agi::io::Save(filename, true).Get().write(&(*data)[0], data->size());
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssAttachment::GetFileName(bool raw) const {
|
std::string AssAttachment::GetFileName(bool raw) const {
|
||||||
if (raw || !boost::iends_with(filename, ".ttf")) return filename;
|
if (raw || !boost::iends_with(filename.get(), ".ttf")) return filename;
|
||||||
|
|
||||||
// Remove stuff after last underscore if it's a font
|
// Remove stuff after last underscore if it's a font
|
||||||
std::string::size_type last_under = filename.rfind('_');
|
std::string::size_type last_under = filename.get().rfind('_');
|
||||||
if (last_under == std::string::npos)
|
if (last_under == std::string::npos)
|
||||||
return filename;
|
return filename;
|
||||||
|
|
||||||
return filename.substr(0, last_under) + ".ttf";
|
return filename.get().substr(0, last_under) + ".ttf";
|
||||||
}
|
|
||||||
|
|
||||||
void AssAttachment::Finish() {
|
|
||||||
data = std::make_shared<std::vector<char>>(agi::ass::UUDecode(buffer));
|
|
||||||
buffer.clear();
|
|
||||||
buffer.shrink_to_fit();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,66 +1,42 @@
|
||||||
// Copyright (c) 2006, Rodrigo Braz Monteiro
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
//
|
||||||
// Aegisub Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
/// @file ass_attachment.h
|
|
||||||
/// @see ass_attachment.cpp
|
|
||||||
/// @ingroup subs_storage
|
|
||||||
///
|
|
||||||
|
|
||||||
#include "ass_entry.h"
|
#include "ass_entry.h"
|
||||||
|
|
||||||
#include <libaegisub/fs_fwd.h>
|
#include <libaegisub/fs_fwd.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <boost/flyweight.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/// @class AssAttachment
|
/// @class AssAttachment
|
||||||
class AssAttachment : public AssEntry {
|
class AssAttachment : public AssEntry {
|
||||||
/// Decoded file data
|
/// ASS uuencoded entry data, including header.
|
||||||
std::shared_ptr<std::vector<char>> data;
|
boost::flyweight<std::string> entry_data;
|
||||||
|
|
||||||
/// Encoded data which has been read from the script but not yet decoded
|
|
||||||
std::string buffer;
|
|
||||||
|
|
||||||
/// Name of the attached file, with SSA font mangling if it is a ttf
|
/// Name of the attached file, with SSA font mangling if it is a ttf
|
||||||
std::string filename;
|
boost::flyweight<std::string> filename;
|
||||||
|
|
||||||
AssEntryGroup group;
|
AssEntryGroup group;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Get the size of the attached file in bytes
|
/// Get the size of the attached file in bytes
|
||||||
size_t GetSize() const { return data->size(); }
|
size_t GetSize() const;
|
||||||
|
|
||||||
/// Add a line of data (without newline) read from a subtitle file to the
|
/// Add a line of data (without newline) read from a subtitle file
|
||||||
/// buffer waiting to be decoded
|
void AddData(std::string const& data) { entry_data = entry_data.get() + data + "\r\n"; }
|
||||||
void AddData(std::string const& data) { buffer += data; }
|
|
||||||
/// Decode all data passed with AddData
|
|
||||||
void Finish();
|
|
||||||
|
|
||||||
/// Extract the contents of this attachment to a file
|
/// Extract the contents of this attachment to a file
|
||||||
/// @param filename Path to save the attachment to
|
/// @param filename Path to save the attachment to
|
||||||
|
|
|
@ -53,7 +53,6 @@ void AssParser::ParseAttachmentLine(std::string const& data) {
|
||||||
|
|
||||||
// Data is over, add attachment to the file
|
// Data is over, add attachment to the file
|
||||||
if (!valid_data || is_filename) {
|
if (!valid_data || is_filename) {
|
||||||
attach->Finish();
|
|
||||||
InsertLine(attach.release());
|
InsertLine(attach.release());
|
||||||
AddLine(data);
|
AddLine(data);
|
||||||
}
|
}
|
||||||
|
@ -61,11 +60,9 @@ void AssParser::ParseAttachmentLine(std::string const& data) {
|
||||||
attach->AddData(data);
|
attach->AddData(data);
|
||||||
|
|
||||||
// Done building
|
// Done building
|
||||||
if (data.size() < 80) {
|
if (data.size() < 80)
|
||||||
attach->Finish();
|
|
||||||
InsertLine(attach.release());
|
InsertLine(attach.release());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssParser::ParseScriptInfoLine(std::string const& data) {
|
void AssParser::ParseScriptInfoLine(std::string const& data) {
|
||||||
|
|
Loading…
Reference in a new issue