source: trunk/DataHandlerCallback.cpp @ 322

Revision 322, 5.1 KB checked in by dconrad, 8 years ago (diff)

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

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.