Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
286 lines (235 sloc) 6.36 KB
/*
* DataHandlerCallback.cpp
*
* DataHandlerCallback.cpp - file I/O for libebml.
*
*
* Copyright (c) 2006 David Conrad
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "DataHandlerCallback.h"
#include <QuickTime/QuickTime.h>
#include "ebml/Debug.h"
#include "ebml/EbmlConfig.h"
#include "ebml/StdIOCallback.h"
using namespace std;
DataHBuffer::DataHBuffer(size_t bufferSize)
{
buffer = new uint8_t[bufferSize];
allocatedSize = bufferSize;
fileOffset = -1;
dataSize = 0;
}
DataHBuffer::~DataHBuffer()
{
if (buffer)
delete[] buffer;
}
void DataHBuffer::Realloc(size_t bufferSize)
{
if (buffer)
delete[] buffer;
buffer = new uint8_t[bufferSize];
allocatedSize = bufferSize;
fileOffset = -1;
dataSize = 0;
}
bool DataHBuffer::ContainsOffset(uint64_t offset)
{
return offset >= fileOffset && offset < fileOffset + dataSize;
}
uint8_t * DataHBuffer::GetBuffer(uint64_t offset, size_t size)
{
if (size > allocatedSize)
Realloc(size);
fileOffset = offset;
dataSize = size;
return buffer;
}
size_t DataHBuffer::Read(uint64_t offset, size_t size, uint8_t *store)
{
if (!ContainsOffset(offset))
return 0;
uint8_t *dataStart = buffer + (offset - fileOffset);
size_t amountToRead = MIN(fileOffset + dataSize - offset, size);
memcpy(store, dataStart, amountToRead);
return amountToRead;
}
DataHandlerCallback::DataHandlerCallback(ComponentInstance dataHandler, const open_mode aMode)
{
Initialize(aMode);
switch (aMode)
{
case MODE_READ:
case MODE_WRITE:
this->dataHandler = dataHandler;
break;
default:
throw 0;
break;
}
// figure out if we support wide offesets
getFileSize();
}
DataHandlerCallback::DataHandlerCallback(Handle dataRef, OSType dataRefType, const open_mode aMode)
{
ComponentResult err = noErr;
Component dataHComponent = NULL;
Initialize(aMode);
if (aMode == MODE_READ)
dataHComponent = GetDataHandler(dataRef, dataRefType, kDataHCanRead);
else if (aMode == MODE_WRITE)
dataHComponent = GetDataHandler(dataRef, dataRefType, kDataHCanWrite);
else
throw 0;
err = OpenAComponent(dataHComponent, &dataHandler);
if (err) {
throw CRTError("Error opening data handler component", err);
}
err = DataHSetDataRef(dataHandler, dataRef);
if (err) {
throw CRTError("Error setting data handler ref", err);
}
if (aMode == MODE_READ) {
err = DataHOpenForRead(dataHandler);
if (err) {
throw CRTError("Error opening data handler for read", err);
}
} else if (aMode == MODE_WRITE) {
err = DataHOpenForWrite(dataHandler);
if (err) {
throw CRTError("Error opening data handler for write", err);
}
} else {
throw 0;
}
closeHandler = true;
// figure out if we support wide offesets
getFileSize();
}
void DataHandlerCallback::Initialize(const open_mode aMode)
{
closeHandler = false;
supportsWideOffsets = true;
this->dataHandler = NULL;
mCurrentPosition = 0;
filesize = 0;
this->aMode = aMode;
}
DataHandlerCallback::~DataHandlerCallback() throw()
{
close();
}
uint32 DataHandlerCallback::read(void *buffer, size_t size)
{
ComponentResult err = noErr;
size_t amountRead = 0;
uint64_t oldPos = mCurrentPosition;
uint8_t *internalBuffer, *myBuffer = (uint8_t *)buffer;
if (mCurrentPosition + size > filesize)
getFileSize();
if (size < 1 || mCurrentPosition > filesize)
return 0;
if (mCurrentPosition + size > filesize)
size = filesize - mCurrentPosition;
while (size > 0) {
if (dataBuffer.ContainsOffset(mCurrentPosition)) {
amountRead = dataBuffer.Read(mCurrentPosition, size, myBuffer);
myBuffer += amountRead;
mCurrentPosition += amountRead;
size -= amountRead;
}
if (size <= 0)
break;
size_t readSize = MIN(READ_SIZE, filesize - mCurrentPosition);
internalBuffer = dataBuffer.GetBuffer(mCurrentPosition, readSize);
if (supportsWideOffsets) {
wide wideOffset = SInt64ToWide(mCurrentPosition);
err = DataHScheduleData64(dataHandler, (Ptr)internalBuffer, &wideOffset,
readSize, 0, NULL, NULL);
} else {
err = DataHScheduleData(dataHandler, (Ptr)internalBuffer, mCurrentPosition,
readSize, 0, NULL, NULL);
}
if (err) {
throw CRTError("Error reading data", err);
}
}
return mCurrentPosition - oldPos;
}
void DataHandlerCallback::setFilePointer(int64 Offset, seek_mode Mode)
{
switch ( Mode )
{
case SEEK_CUR:
mCurrentPosition += Offset;
break;
case SEEK_END:
// I think this is what seeking this way does (was ftell(File))
mCurrentPosition = getFileSize() + Offset;
break;
case SEEK_SET:
mCurrentPosition = Offset;
break;
}
}
size_t DataHandlerCallback::write(const void *Buffer, size_t Size)
{
ComponentResult err = noErr;
if (supportsWideOffsets) {
wide wideOffset = SInt64ToWide(mCurrentPosition);
err = DataHWrite64(dataHandler, (Ptr)Buffer, &wideOffset, Size, NULL, 0);
} else {
err = DataHWrite(dataHandler, (Ptr)Buffer, mCurrentPosition, Size, NULL, 0);
}
if (err) {
throw CRTError("Error writing data", err);
}
mCurrentPosition += Size;
// does QT tell us how much it writes?
return Size;
}
uint64 DataHandlerCallback::getFilePointer()
{
return mCurrentPosition;
}
void DataHandlerCallback::close()
{
if (closeHandler) {
if (aMode == MODE_READ)
DataHCloseForRead(dataHandler);
else if (aMode == MODE_WRITE)
DataHCloseForWrite(dataHandler);
dataHandler = NULL;
}
}
SInt64 DataHandlerCallback::getFileSize()
{
ComponentResult err = noErr;
wide wideFilesize;
err = DataHGetFileSize64(dataHandler, &wideFilesize);
if (err == noErr) {
supportsWideOffsets = true;
filesize = WideToSInt64(wideFilesize);
} else {
long size32;
supportsWideOffsets = false;
DataHGetFileSize(dataHandler, &size32);
filesize = size32;
}
return filesize;
}