source: trunk/DataHandlerCallback.cpp @ 322

Last change on this file since 322 was 322, checked in by dconrad, 10 years ago

Another check to prevent libmatroska from going wild on an incomplete file

File size: 5.1 KB
Line 
1/*
2 *  DataHandlerCallback.cpp
3 *
4 *    DataHandlerCallback.cpp - file I/O for libebml.
5 *
6 *
7 *  Copyright (c) 2006  David Conrad
8 *
9 *  This program is free software; you can redistribute it and/or
10 *  modify it under the terms of the GNU Lesser General Public
11 *  License as published by the Free Software Foundation;
12 *  version 2.1 of the License.
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 *  Lesser General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public
20 *  License along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 */
24
25#include "DataHandlerCallback.h"
26#include <QuickTime/QuickTime.h>
27
28#include "ebml/Debug.h"
29#include "ebml/EbmlConfig.h"
30
31using namespace std;
32
33CRTError::CRTError(int nError, const std::string & Description)
34        :std::runtime_error(Description+": "+strerror(nError))
35        ,Error(Error)
36{
37}
38
39CRTError::CRTError(const std::string & Description,int nError)
40        :std::runtime_error(Description+": "+strerror(nError))
41        ,Error(Error)
42{
43}
44
45DataHandlerCallback::DataHandlerCallback(ComponentInstance dataHandler, const open_mode aMode)
46{       
47        closeHandler = false;
48        supportsWideOffsets = true;
49        this->dataHandler = NULL;
50        mCurrentPosition = 0;
51        filesize = 0;
52        this->aMode = aMode;
53       
54        switch (aMode)
55        {
56                case MODE_READ:
57                case MODE_WRITE:
58                        this->dataHandler = dataHandler;
59                        break;
60                       
61                default:
62                        throw 0;
63                        break;
64        }
65       
66        // figure out if we support wide offesets
67        getFileSize();
68}
69
70DataHandlerCallback::DataHandlerCallback(Handle dataRef, OSType dataRefType, const open_mode aMode)
71{
72    ComponentResult err = noErr;
73    Component dataHComponent = NULL;
74       
75        closeHandler = true;
76        supportsWideOffsets = true;
77        dataHComponent = NULL;
78        mCurrentPosition = 0;
79        filesize = 0;
80        this->aMode = aMode;
81       
82        if (aMode == MODE_READ)
83                dataHComponent = GetDataHandler(dataRef, dataRefType, kDataHCanRead);
84        else if (aMode == MODE_WRITE)
85                dataHComponent = GetDataHandler(dataRef, dataRefType, kDataHCanWrite);
86        else
87                throw 0;
88       
89        err = OpenAComponent(dataHComponent, &dataHandler);
90        if (err) {
91                throw CRTError("Error opening data handler component", err);
92        }
93       
94        err = DataHSetDataRef(dataHandler, dataRef);
95        if (err) {
96                throw CRTError("Error setting data handler ref", err);
97        }
98       
99        if (aMode == MODE_READ) {
100                err = DataHOpenForRead(dataHandler);
101        if (err) {
102            throw CRTError("Error opening data handler for read", err);
103        }
104        } else if (aMode == MODE_WRITE) {
105                err = DataHOpenForWrite(dataHandler);
106        if (err) {
107            throw CRTError("Error opening data handler for write", err);
108        }
109        } else {
110                throw 0;
111        }
112       
113        // figure out if we support wide offesets
114        getFileSize();
115}
116
117
118DataHandlerCallback::~DataHandlerCallback() throw()
119{
120        close();
121}
122
123
124
125uint32 DataHandlerCallback::read(void *Buffer, size_t Size)
126{
127        ComponentResult err = noErr;
128       
129    if (Size < 1 || mCurrentPosition > filesize)
130        return 0;
131       
132        if (mCurrentPosition + Size > filesize)
133                Size = filesize - mCurrentPosition;
134       
135        if (supportsWideOffsets) {
136                wide wideOffset = SInt64ToWide(mCurrentPosition);
137               
138                err = DataHScheduleData64(dataHandler, (Ptr)Buffer, &wideOffset, Size, 0, NULL, NULL);
139        } else {
140                err = DataHScheduleData(dataHandler, (Ptr)Buffer, mCurrentPosition, Size, 0, NULL, NULL);
141        }
142       
143        if (err) {
144                throw CRTError("Error reading data", err);
145        }
146        mCurrentPosition += Size;
147       
148        // does QuickTime tell us how much it's read?
149        return Size;
150}
151
152void DataHandlerCallback::setFilePointer(int64 Offset, LIBEBML_NAMESPACE::seek_mode Mode)
153{
154        switch ( Mode )
155        {
156                case SEEK_CUR:
157                        mCurrentPosition += Offset;
158                        break;
159                case SEEK_END:
160                        // I think this is what seeking this way does (was ftell(File))
161                        mCurrentPosition = getFileSize() + Offset;
162                        break;
163                case SEEK_SET:
164                        mCurrentPosition = Offset;
165                        break;
166        }
167}
168
169size_t DataHandlerCallback::write(const void *Buffer, size_t Size)
170{
171        ComponentResult err = noErr;
172       
173        if (supportsWideOffsets) {
174                wide wideOffset = SInt64ToWide(mCurrentPosition);
175               
176                err = DataHWrite64(dataHandler, (Ptr)Buffer, &wideOffset, Size, NULL, 0);
177        } else {
178                err = DataHWrite(dataHandler, (Ptr)Buffer, mCurrentPosition, Size, NULL, 0);
179        }
180       
181        if (err) {
182                throw CRTError("Error writing data", err);
183        }
184        mCurrentPosition += Size;
185       
186        // does QT tell us how much it writes?
187        return Size;
188}
189
190uint64 DataHandlerCallback::getFilePointer()
191{
192        return mCurrentPosition;
193}
194
195void DataHandlerCallback::close()
196{
197        if (closeHandler) {
198                if (aMode == MODE_READ)
199                        DataHCloseForRead(dataHandler);
200                else if (aMode == MODE_WRITE)
201                        DataHCloseForWrite(dataHandler);
202                dataHandler = NULL;
203        }
204}
205
206SInt64 DataHandlerCallback::getFileSize()
207{
208        ComponentResult err = noErr;
209        wide wideFilesize;
210       
211        if (filesize > 0) 
212                return filesize;
213       
214        err = DataHGetFileSize64(dataHandler, &wideFilesize);
215        if (err == noErr) {
216                supportsWideOffsets = true;
217                filesize = WideToSInt64(wideFilesize);
218        } else {
219                long size32;
220                supportsWideOffsets = false;
221                DataHGetFileSize(dataHandler, &size32);
222                filesize = size32;
223        }
224       
225        return filesize;
226}
Note: See TracBrowser for help on using the repository browser.