tagparser/abstractattachment.cpp

155 lines
4.2 KiB
C++
Raw Normal View History

2015-09-06 19:57:33 +02:00
#include "./abstractattachment.h"
2015-04-22 19:22:01 +02:00
2015-09-06 19:57:33 +02:00
#include "./mediafileinfo.h"
#include "./exceptions.h"
2015-04-22 19:22:01 +02:00
2015-10-06 22:30:05 +02:00
#include <c++utilities/misc/memory.h>
2016-06-14 22:53:43 +02:00
#include <c++utilities/io/catchiofailure.h>
2015-10-06 22:30:05 +02:00
2015-04-22 19:22:01 +02:00
#include <sstream>
using namespace std;
namespace Media {
/*!
* \class Media::StreamDataBlock
* \brief The StreamDataBlock class is a reference to a certain data block of a stream.
*/
/*!
* \brief Constructs a new StreamDataBlock.
*
* The derived is responsible for the prober initialization of the object.
*/
StreamDataBlock::StreamDataBlock() :
m_stream(nullptr),
m_startOffset(0),
m_endOffset(0)
{}
/*!
* \brief Constructs a new StreamDataBlock with the specified \a stream and offsets.
*
* The \a stream must be provided as function returning a reference the associated stream. This way of passing the stream
* allows the caller to change the stream without the need to update all StreamDataBlock objects
* referring to the stream. This is required when rewriting a file because during rewriting the original file
* gets renamed and then reopend with another stream object.
*
* The object does NOT take ownership over the stream returned by the specified function.
*/
2016-06-10 23:08:01 +02:00
StreamDataBlock::StreamDataBlock(const std::function<std::istream & ()> &stream, std::istream::off_type startOffset, std::ios_base::seekdir startDir, std::istream::off_type endOffset, std::ios_base::seekdir endDir) :
2015-04-22 19:22:01 +02:00
m_stream(stream)
{
auto &s = stream();
auto currentPos = s.tellg();
s.seekg(startOffset, startDir);
m_startOffset = s.tellg();
s.seekg(endOffset, endDir);
m_endOffset = s.tellg();
s.seekg(currentPos);
if(m_endOffset < m_startOffset) {
2016-06-14 22:53:43 +02:00
IoUtilities::throwIoFailure("End offset is less then start offset.");
2015-04-22 19:22:01 +02:00
}
}
2015-11-26 14:22:44 +01:00
/*!
* \brief Buffers the data block. Buffered data can be accessed via buffer().
*/
void StreamDataBlock::makeBuffer() const
{
m_buffer = make_unique<char[]>(size());
stream().seekg(startOffset());
stream().read(m_buffer.get(), size());
}
2015-04-22 19:22:01 +02:00
/*!
* \class Media::FileDataBlock
* \brief The FileDataBlock class is a reference to a certain data block of a file stream.
*/
/*!
* \brief Constructs a new FileDataBlock with the specified \a path.
*
* Opens a file stream with the specified \a path.
*
* \throws Throws ios_base::failure when an IO error occurs.
*/
FileDataBlock::FileDataBlock(const string &path) :
m_fileInfo(new MediaFileInfo)
{
m_fileInfo->setPath(path);
m_fileInfo->open(true);
m_fileInfo->parseContainerFormat();
m_startOffset = 0;
m_endOffset = m_fileInfo->size();
m_stream = [this] () -> std::istream & {
return this->m_fileInfo->stream();
};
}
/*!
* \class Media::AbstractAttachment
* \brief The AbstractAttachment class parses and stores attachment information.
*/
/*!
* \brief Returns a label for the track.
*/
string AbstractAttachment::label() const
{
stringstream ss;
ss << "ID: " << id();
if(!name().empty()) {
ss << ", name: \"" << name() << "\"";
}
if(!mimeType().empty()) {
ss << ", mime-type: \"" << mimeType() << "\"";
}
return ss.str();
}
/*!
* \brief Resets the object to its initial state.
*/
void AbstractAttachment::clear()
{
m_description.clear();
m_name.clear();
m_mimeType.clear();
m_id = 0;
m_data.reset();
}
/*!
* \brief Sets the data, name and MIME-type for the specified \a path.
*
* A stream for the file with the specified \a path is opened (read-only).
* This stream will be freed by the attachment if the other data is assigned
* or the attachment gets destroyed.
*
* \throws Throws std::ios_base::failure when an IO error occurs.
* \throws Throws Media::Failure or a derived class when a parsing
* error occurs.
*
* When such an exception is thrown, the attachment remains unchanged.
*/
void AbstractAttachment::setFile(const std::string &path)
{
2015-10-06 22:30:05 +02:00
m_data.reset();
auto file = make_unique<FileDataBlock>(path);
const auto fileName = file->fileInfo()->fileName();
2015-04-22 19:22:01 +02:00
if(!fileName.empty()) {
m_name = fileName;
}
2015-10-06 22:30:05 +02:00
const char *mimeType = file->fileInfo()->mimeType();
2015-04-22 19:22:01 +02:00
if(*mimeType) {
m_mimeType = mimeType;
}
2015-10-06 22:30:05 +02:00
m_data = move(file);
2015-11-26 14:22:44 +01:00
m_isDataFromFile = true;
2015-04-22 19:22:01 +02:00
}
} // namespace Media