source: libebml/src/EbmlElement.cpp @ 1447

Revision 1447, 19.8 KB checked in by astrange, 3 years ago (diff)

Apply local libebml patch to fix an infinite loop in MKV import

Patch by gbooker
Fixes #338
Fixes #594

Line 
1/****************************************************************************
2** libebml : parse EBML files, see http://embl.sourceforge.net/
3**
4** <file/class description>
5**
6** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.
7**
8** This library is free software; you can redistribute it and/or
9** modify it under the terms of the GNU Lesser General Public
10** License as published by the Free Software Foundation; either
11** version 2.1 of the License, or (at your option) any later version.
12**
13** This library is distributed in the hope that it will be useful,
14** but WITHOUT ANY WARRANTY; without even the implied warranty of
15** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16** Lesser General Public License for more details.
17**
18** You should have received a copy of the GNU Lesser General Public
19** License along with this library; if not, write to the Free Software
20** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21**
22** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.
23**
24** Contact license@matroska.org if any conditions of this licensing are
25** not clear to you.
26**
27**********************************************************************/
28
29/*!
30        \file
31        \version \$Id$
32        \author Steve Lhomme     <robux4 @ users.sf.net>
33*/
34
35#include <cassert>
36#include <cstring>
37
38#include "ebml/EbmlElement.h"
39#include "ebml/EbmlMaster.h"
40#include "ebml/EbmlStream.h"
41#include "ebml/EbmlVoid.h"
42#include "ebml/EbmlDummy.h"
43#include "ebml/EbmlContexts.h"
44
45START_LIBEBML_NAMESPACE
46
47/*!
48        \todo handle more than CodedSize of 5
49*/
50int CodedSizeLength(uint64 Length, unsigned int SizeLength, bool bSizeFinite)
51{
52        unsigned int CodedSize;
53        if (bSizeFinite) {
54                // prepare the head of the size (000...01xxxxxx)
55                // optimal size
56                if (Length < 127) // 2^7 - 1
57                        CodedSize = 1;
58                else if (Length < 16383) // 2^14 - 1
59                        CodedSize = 2;
60                else if (Length < 2097151L) // 2^21 - 1
61                        CodedSize = 3;
62                else if (Length < 268435455L) // 2^28 - 1
63                        CodedSize = 4;
64                else CodedSize = 5;
65        } else {
66                if (Length <= 127) // 2^7 - 1
67                        CodedSize = 1;
68                else if (Length <= 16383) // 2^14 - 1
69                        CodedSize = 2;
70                else if (Length <= 2097151L) // 2^21 - 1
71                        CodedSize = 3;
72                else if (Length <= 268435455L) // 2^28 - 1
73                        CodedSize = 4;
74                else CodedSize = 5;
75        }
76
77        if (SizeLength > 0 && CodedSize < SizeLength) {
78                // defined size
79                CodedSize = SizeLength;
80        }
81
82        return CodedSize;
83}
84
85/*!
86        \todo handle more than CodedSize of 5
87*/
88int CodedSizeLengthSigned(int64 Length, unsigned int SizeLength)
89{
90        unsigned int CodedSize;
91        // prepare the head of the size (000...01xxxxxx)
92        // optimal size
93        if (Length > -64 && Length < 64) // 2^6
94                CodedSize = 1;
95        else if (Length > -8192 && Length < 8192) // 2^13
96                CodedSize = 2;
97        else if (Length > -1048576L && Length < 1048576L) // 2^20
98                CodedSize = 3;
99        else if (Length > -134217728L && Length < 134217728L) // 2^27
100                CodedSize = 4;
101        else CodedSize = 5;
102
103        if (SizeLength > 0 && CodedSize < SizeLength) {
104                // defined size
105                CodedSize = SizeLength;
106        }
107
108        return CodedSize;
109}
110
111int CodedValueLength(uint64 Length, int CodedSize, binary * OutBuffer)
112{
113        int _SizeMask = 0xFF;
114        OutBuffer[0] = 1 << (8 - CodedSize);
115        for (int i=1; i<CodedSize; i++) {
116                OutBuffer[CodedSize-i] = Length & 0xFF;
117                Length >>= 8;
118                _SizeMask >>= 1;
119        }
120        // first one use a OR with the "EBML size head"
121        OutBuffer[0] |= Length & 0xFF & _SizeMask;
122        return CodedSize;
123}
124
125int CodedValueLengthSigned(int64 Length, int CodedSize, binary * OutBuffer)
126{
127        if (Length > -64 && Length < 64) // 2^6
128                Length += 63;
129        else if (Length > -8192 && Length < 8192) // 2^13
130                Length += 8191;
131        else if (Length > -1048576L && Length < 1048576L) // 2^20
132                Length += 1048575L;
133        else if (Length > -134217728L && Length < 134217728L) // 2^27
134                Length += 134217727L;
135
136        return CodedValueLength(Length, CodedSize, OutBuffer);
137}
138
139uint64 ReadCodedSizeValue(const binary * InBuffer, uint32 & BufferSize, uint64 & SizeUnknown)
140{
141        binary SizeBitMask = 1 << 7;
142        uint64 Result = 0x7F;
143        unsigned int SizeIdx, PossibleSizeLength = 0;
144        binary PossibleSize[8];
145
146        SizeUnknown = 0x7F; // the last bit is discarded when computing the size
147        for (SizeIdx = 0; SizeIdx < BufferSize && SizeIdx < 8; SizeIdx++) {
148                if (InBuffer[0] & (SizeBitMask >> SizeIdx)) {
149                        // ID found
150                        PossibleSizeLength = SizeIdx + 1;
151                        SizeBitMask >>= SizeIdx;
152                        for (SizeIdx = 0; SizeIdx < PossibleSizeLength; SizeIdx++) {
153                                PossibleSize[SizeIdx] = InBuffer[SizeIdx];
154                        }
155                        for (SizeIdx = 0; SizeIdx < PossibleSizeLength - 1; SizeIdx++) {
156                                Result <<= 7;
157                                Result |= 0xFF;
158                        }
159
160                        Result = 0;
161                        Result |= PossibleSize[0] & ~SizeBitMask;
162                        for (unsigned int i = 1; i<PossibleSizeLength; i++) {
163                                Result <<= 8;
164                                Result |= PossibleSize[i];
165                        }
166
167                        BufferSize = PossibleSizeLength;
168
169                        return Result;
170                }
171                SizeUnknown <<= 7;
172                SizeUnknown |= 0xFF;
173        }
174
175        BufferSize = 0;
176        return 0;
177}
178
179int64 ReadCodedSizeSignedValue(const binary * InBuffer, uint32 & BufferSize, uint64 & SizeUnknown)
180{
181        int64 Result = ReadCodedSizeValue(InBuffer, BufferSize, SizeUnknown);
182
183        if (BufferSize != 0)
184        {
185                switch (BufferSize)
186                {
187                case 1:
188                        Result -= 63;
189                        break;
190                case 2:
191                        Result -= 8191;
192                        break;
193                case 3:
194                        Result -= 1048575L;
195                        break;
196                case 4:
197                        Result -= 134217727L;
198                        break;
199                }
200        }
201
202        return Result;
203}
204
205
206EbmlCallbacks::EbmlCallbacks(EbmlElement & (*Creator)(), const EbmlId & aGlobalId, const char * aDebugName, const EbmlSemanticContext & aContext)
207        :Create(Creator)
208        ,GlobalId(aGlobalId)
209        ,DebugName(aDebugName)
210        ,Context(aContext)
211{
212  assert((Create!=NULL) || !strcmp(aDebugName, "DummyElement"));
213}
214
215const EbmlSemantic & EbmlSemanticContext::GetSemantic(size_t i) const
216{
217    assert(i<Size);
218    if (i<Size)
219        return MyTable[i];
220    else
221        return *(EbmlSemantic*)NULL;
222}
223
224
225EbmlElement::EbmlElement(uint64 aDefaultSize, bool bValueSet)
226 :DefaultSize(aDefaultSize)
227 ,SizeLength(0) ///< write optimal size by default
228 ,bSizeIsFinite(true)
229 ,ElementPosition(0)
230 ,SizePosition(0)
231 ,bValueIsSet(bValueSet)
232 ,DefaultIsSet(false)
233 ,bLocked(false)
234{
235        Size = DefaultSize;
236}
237
238EbmlElement::EbmlElement(const EbmlElement & ElementToClone)
239 :Size(ElementToClone.Size)
240 ,DefaultSize(ElementToClone.DefaultSize)
241 ,SizeLength(ElementToClone.SizeLength)
242 ,bSizeIsFinite(ElementToClone.bSizeIsFinite)
243 ,ElementPosition(ElementToClone.ElementPosition)
244 ,SizePosition(ElementToClone.SizePosition)
245 ,bValueIsSet(ElementToClone.bValueIsSet)
246 ,DefaultIsSet(ElementToClone.DefaultIsSet)
247 ,bLocked(ElementToClone.bLocked)
248{
249}
250
251EbmlElement::~EbmlElement()
252{
253    assert(!bLocked);
254}
255
256/*!
257        \todo this method is deprecated and should be called FindThisID
258        \todo replace the new RawElement with the appropriate class (when known)
259*/
260EbmlElement * EbmlElement::FindNextID(IOCallback & DataStream, const EbmlCallbacks & ClassInfos, uint64 MaxDataSize)
261{
262        binary PossibleId[4];
263        int PossibleID_Length = 0;
264        binary PossibleSize[8]; // we don't support size stored in more than 64 bits
265        uint32 PossibleSizeLength = 0;
266        uint64 SizeUnknown;
267        uint64 SizeFound;
268        bool bElementFound = false;
269
270        binary BitMask;
271        uint64 aElementPosition, aSizePosition;
272        while (!bElementFound) {
273                // read ID
274                aElementPosition = DataStream.getFilePointer();
275                uint32 ReadSize = 0;
276                BitMask = 1 << 7;
277                while (1) {
278                        ReadSize += DataStream.read(&PossibleId[PossibleID_Length], 1);
279                        if (ReadSize == uint32(PossibleID_Length)) {
280                                return NULL; // no more data ?
281                        }
282                        if (++PossibleID_Length > 4) {
283                                return NULL; // we don't support element IDs over class D
284                        }
285                        if (PossibleId[0] & BitMask) {
286                                // this is the last octet of the ID
287                                // check wether that's the one we're looking for
288/*                      if (PossibleID == EBML_INFO_ID(ClassInfos)) {
289                                        break;
290                                } else {
291                                        /// \todo This element should be skipped (use a context ?)
292                                }*/
293                                bElementFound = true; /// \todo not exactly the one we're looking for
294                                break;
295                        }
296                        BitMask >>= 1;
297                }
298
299                // read the data size
300                aSizePosition = DataStream.getFilePointer();
301                uint32 _SizeLength;
302                do {
303                        if (PossibleSizeLength >= 8)
304                                // Size is larger than 8 bytes
305                                return NULL;
306
307                        ReadSize += DataStream.read(&PossibleSize[PossibleSizeLength++], 1);
308                        _SizeLength = PossibleSizeLength;
309                        SizeFound = ReadCodedSizeValue(&PossibleSize[0], _SizeLength, SizeUnknown);
310                } while (_SizeLength == 0);
311        }
312
313        EbmlElement *Result = NULL;
314        EbmlId PossibleID(PossibleId, PossibleID_Length);
315        if (PossibleID == EBML_INFO_ID(ClassInfos)) {
316                // the element is the one expected
317                Result = &EBML_INFO_CREATE(ClassInfos);
318        } else {
319                /// \todo find the element in the context
320                Result = new EbmlDummy(PossibleID);
321        }
322
323        Result->SetSizeLength(PossibleSizeLength);
324
325        Result->Size = SizeFound;
326
327        if (!Result->ValidateSize() || (SizeFound != SizeUnknown && MaxDataSize < Result->Size)) {
328                        delete Result;
329                        return NULL;
330        }
331
332        // check if the size is not all 1s
333        if (SizeFound == SizeUnknown) {
334                // Size of this element is unknown
335                // only possible for Master elements
336                if (!Result->SetSizeInfinite()) {
337                        /// \todo the element is not allowed to be infinite
338                        delete Result;
339                        return NULL;
340                }
341        } else Result->SetSizeInfinite(false);
342        Result->ElementPosition = aElementPosition;
343        Result->SizePosition = aSizePosition;
344
345        return Result;
346}
347
348
349/*!
350        \todo replace the new RawElement with the appropriate class (when known)
351        \todo skip data for Dummy elements when they are not allowed
352        \todo better check of the size checking for upper elements (using a list of size for each level)
353        \param LowLevel Will be returned with the level of the element found compared to the context given
354*/
355EbmlElement * EbmlElement::FindNextElement(IOCallback & DataStream, const EbmlSemanticContext & Context, int & UpperLevel,
356                        uint64 MaxDataSize, bool AllowDummyElt, unsigned int MaxLowerLevel)
357{
358        int PossibleID_Length = 0;
359        binary PossibleIdNSize[16];
360        int PossibleSizeLength;
361        uint64 SizeUnknown;
362        int ReadIndex = 0; // trick for the algo, start index at 0
363        uint32 ReadSize = 0;
364        uint64 SizeFound;
365        int SizeIdx;
366        bool bFound;
367        int UpperLevel_original = UpperLevel;
368
369        do {
370                // read a potential ID
371                do {
372                        assert(ReadIndex < 16);
373                        // build the ID with the current Read Buffer
374                        bFound = false;
375                        binary IdBitMask = 1 << 7;
376                        for (SizeIdx = 0; SizeIdx < ReadIndex && SizeIdx < 4; SizeIdx++) {
377                                if (PossibleIdNSize[0] & (IdBitMask >> SizeIdx)) {
378                                        // ID found
379                                        PossibleID_Length = SizeIdx + 1;
380                                        IdBitMask >>= SizeIdx;
381                                        bFound = true;
382                                        break;
383                                }
384                        }
385                        if (bFound) {
386                                break;
387                        }
388
389                        if (ReadIndex >= 4) {
390                                // ID not found
391                                // shift left the read octets
392                                memmove(&PossibleIdNSize[0],&PossibleIdNSize[1], --ReadIndex);
393                        }
394
395                        if (DataStream.read(&PossibleIdNSize[ReadIndex++], 1) == 0) {
396                                return NULL; // no more data ?
397                        }
398                        ReadSize++;
399
400                } while (!bFound && MaxDataSize > ReadSize);
401
402                SizeIdx = ReadIndex;
403                ReadIndex -= PossibleID_Length;
404
405                // read the data size
406                uint32 _SizeLength;
407                PossibleSizeLength = ReadIndex;
408                while (1)
409                {
410                        _SizeLength = PossibleSizeLength;
411                        SizeFound = ReadCodedSizeValue(&PossibleIdNSize[PossibleID_Length], _SizeLength, SizeUnknown);
412                        if (_SizeLength != 0) {
413                                bFound = true;
414                                break;
415                        }
416                        if (PossibleSizeLength >= 8) {
417                                bFound = false;
418                                break;
419                        }
420                        ReadSize += DataStream.read(&PossibleIdNSize[SizeIdx++], 1);
421                        PossibleSizeLength++;
422                }
423
424                if (bFound) {
425                        // find the element in the context and use the correct creator
426                        EbmlId PossibleID(PossibleIdNSize, PossibleID_Length);
427                        EbmlElement * Result = CreateElementUsingContext(PossibleID, Context, UpperLevel, false, AllowDummyElt, MaxLowerLevel);
428                        ///< \todo continue is misplaced
429                        if (Result != NULL) {
430                                if (AllowDummyElt || !Result->IsDummy()) {
431                                        Result->SetSizeLength(_SizeLength);
432
433                                        Result->Size = SizeFound;
434                                        // UpperLevel values
435                                        // -1 : global element
436                                        //  0 : child
437                                        //  1 : same level
438                                        //  + : further parent
439                                        if (Result->ValidateSize() && (SizeFound == SizeUnknown || UpperLevel > 0 || MaxDataSize == 0 || MaxDataSize >= (PossibleID_Length + PossibleSizeLength + SizeFound))) {
440                                                if (SizeFound == SizeUnknown) {
441                                                        Result->SetSizeInfinite();
442                                                }
443
444                                                Result->SizePosition = DataStream.getFilePointer() - SizeIdx + EBML_ID_LENGTH(PossibleID);
445                                                Result->ElementPosition = Result->SizePosition - EBML_ID_LENGTH(PossibleID);
446                                                // place the file at the beggining of the data
447                                                DataStream.setFilePointer(Result->SizePosition + _SizeLength);
448                                                return Result;
449                                        }
450                                }
451                                delete Result;
452                        }
453                }
454
455                // recover all the data in the buffer minus one byte
456                ReadIndex = SizeIdx - 1;
457                memmove(&PossibleIdNSize[0], &PossibleIdNSize[1], ReadIndex);
458                UpperLevel = UpperLevel_original;
459        } while ( MaxDataSize > DataStream.getFilePointer() - SizeIdx + PossibleID_Length );
460
461        return NULL;
462}
463
464/*!
465        \todo what happens if we are in a upper element with a known size ?
466*/
467EbmlElement * EbmlElement::SkipData(EbmlStream & DataStream, const EbmlSemanticContext & Context, EbmlElement * TestReadElt, bool AllowDummyElt)
468{
469        EbmlElement * Result = NULL;
470        if (bSizeIsFinite) {
471                assert(TestReadElt == NULL);
472                assert(ElementPosition < SizePosition);
473                DataStream.I_O().setFilePointer(SizePosition + CodedSizeLength(Size, SizeLength, bSizeIsFinite) + Size, seek_beginning);
474//              DataStream.I_O().setFilePointer(Size, seek_current);
475        } else {
476                /////////////////////////////////////////////////
477                // read elements until an upper element is found
478                /////////////////////////////////////////////////
479                bool bEndFound = false;
480                while (!bEndFound && Result == NULL) {
481                        // read an element
482                        /// \todo 0xFF... and true should be configurable
483//                      EbmlElement * NewElt;
484                        if (TestReadElt == NULL) {
485                                int bUpperElement = 0; // trick to call FindNextID correctly
486                                Result = DataStream.FindNextElement(Context, bUpperElement, 0xFFFFFFFFL, AllowDummyElt);
487                        } else {
488                                Result = TestReadElt;
489                                TestReadElt = NULL;
490                        }
491
492                        if (Result != NULL) {
493                                unsigned int EltIndex;
494                                // data known in this Master's context
495                                for (EltIndex = 0; EltIndex < EBML_CTX_SIZE(Context); EltIndex++) {
496                                        if (EbmlId(*Result) == EBML_CTX_IDX_ID(Context,EltIndex)) {
497                                                // skip the data with its own context
498                                                Result = Result->SkipData(DataStream, EBML_SEM_CONTEXT(EBML_CTX_IDX(Context,EltIndex)), NULL);
499                                                break; // let's go to the next ID
500                                        }
501                                }
502
503                                if (EltIndex >= EBML_CTX_SIZE(Context)) {
504                                        if (EBML_CTX_PARENT(Context) != NULL) {
505                                                Result = SkipData(DataStream, *EBML_CTX_PARENT(Context), Result);
506                                        } else {
507                                                assert(Context.GetGlobalContext != NULL);
508                                                if (Context != Context.GetGlobalContext()) {
509                                                        Result = SkipData(DataStream, Context.GetGlobalContext(), Result);
510                                                } else {
511                                                        bEndFound = true;
512                                                }
513                                        }
514                                }
515                        } else {
516                                bEndFound = true;
517                        }
518                }
519        }
520        return Result;
521}
522
523EbmlElement *EbmlElement::CreateElementUsingContext(const EbmlId & aID, const EbmlSemanticContext & Context,
524                                                                                                        int & LowLevel, bool IsGlobalContext, bool bAllowDummy, unsigned int MaxLowerLevel)
525{
526        unsigned int ContextIndex;
527        EbmlElement *Result = NULL;
528
529        // elements at the current level
530        for (ContextIndex = 0; ContextIndex < EBML_CTX_SIZE(Context); ContextIndex++) {
531                if (aID == EBML_CTX_IDX_ID(Context,ContextIndex)) {
532            return &EBML_SEM_CREATE(EBML_CTX_IDX(Context,ContextIndex));
533                }
534        }
535
536        // global elements
537        assert(Context.GetGlobalContext != NULL); // global should always exist, at least the EBML ones
538        const EbmlSemanticContext & tstContext = Context.GetGlobalContext();
539        if (tstContext != Context) {
540                LowLevel--;
541                MaxLowerLevel--;
542                // recursive is good, but be carefull...
543                Result = CreateElementUsingContext(aID, tstContext, LowLevel, true, bAllowDummy, MaxLowerLevel);
544                if (Result != NULL) {
545                        return Result;
546                }
547                LowLevel++;
548                MaxLowerLevel++;
549        } else {
550                return NULL;
551        }
552
553        // parent elements
554        if (EBML_CTX_MASTER(Context) != NULL && aID == EBML_INFO_ID(*EBML_CTX_MASTER(Context))) {
555                LowLevel++; // already one level up (same as context)
556                return &EBML_INFO_CREATE(*EBML_CTX_MASTER(Context));
557        }
558
559        // check wether it's not part of an upper context
560        if (EBML_CTX_PARENT(Context) != NULL) {
561                LowLevel++;
562                MaxLowerLevel++;
563                return CreateElementUsingContext(aID, *EBML_CTX_PARENT(Context), LowLevel, IsGlobalContext, bAllowDummy, MaxLowerLevel);
564        }
565
566        if (!IsGlobalContext && bAllowDummy) {
567                LowLevel = 0;
568                Result = new EbmlDummy(aID);
569        }
570
571        return Result;
572}
573
574/*!
575        \todo verify that the size written is the same as the data written
576*/
577filepos_t EbmlElement::Render(IOCallback & output, bool bWithDefault, bool bKeepPosition, bool bForceRender)
578{
579        assert(bValueIsSet || (bWithDefault && DefaultISset())); // an element is been rendered without a value set !!!
580                                 // it may be a mandatory element without a default value
581        try {
582                if (!bWithDefault && IsDefaultValue()) {
583                        return 0;
584                }
585#if defined(_DEBUG) || defined(DEBUG)
586                uint64 SupposedSize = UpdateSize(bWithDefault, bForceRender);
587#endif // _DEBUG
588                filepos_t result = RenderHead(output, bForceRender, bWithDefault, bKeepPosition);
589                uint64 WrittenSize = RenderData(output, bForceRender, bWithDefault);
590#if defined(_DEBUG) || defined(DEBUG)
591        if (static_cast<int64>(SupposedSize) != (0-1)) assert(WrittenSize == SupposedSize);
592#endif // DEBUG
593                result += WrittenSize;
594                return result;
595        } catch (std::exception & ex) {
596//              const char * What = ex.what();
597                assert(false); // we should never be here !
598                return 0;
599        }
600}
601
602/*!
603        \todo store the position of the Size writing for elements with unknown size
604        \todo handle exceptions on errors
605        \todo handle CodeSize bigger than 5 bytes
606*/
607filepos_t EbmlElement::RenderHead(IOCallback & output, bool bForceRender, bool bWithDefault, bool bKeepPosition)
608{
609        if (EBML_ID_LENGTH((const EbmlId&)*this) <= 0 || EBML_ID_LENGTH((const EbmlId&)*this) > 4)
610                return 0;
611
612        UpdateSize(bWithDefault, bForceRender);
613
614        return MakeRenderHead(output, bKeepPosition);
615}
616
617filepos_t EbmlElement::MakeRenderHead(IOCallback & output, bool bKeepPosition)
618{
619        binary FinalHead[4+8]; // Class D + 64 bits coded size
620        unsigned int FinalHeadSize;
621
622        FinalHeadSize = EBML_ID_LENGTH((const EbmlId&)*this);
623        EbmlId(*this).Fill(FinalHead);
624
625        int CodedSize = CodedSizeLength(Size, SizeLength, bSizeIsFinite);
626        CodedValueLength(Size, CodedSize, &FinalHead[FinalHeadSize]);
627        FinalHeadSize += CodedSize;
628
629        output.writeFully(FinalHead, FinalHeadSize);
630        if (!bKeepPosition) {
631                ElementPosition = output.getFilePointer() - FinalHeadSize;
632                SizePosition = ElementPosition + EBML_ID_LENGTH((const EbmlId&)*this);
633        }
634
635        return FinalHeadSize;
636}
637
638uint64 EbmlElement::ElementSize(bool bWithDefault) const
639{
640        if (!bWithDefault && IsDefaultValue())
641                return 0; // won't be saved
642        return Size + EBML_ID_LENGTH((const EbmlId&)*this) + CodedSizeLength(Size, SizeLength, bSizeIsFinite);
643}
644
645bool EbmlElement::IsSmallerThan(const EbmlElement *Cmp) const
646{
647        return EbmlId(*this) == EbmlId(*Cmp);
648}
649
650bool EbmlElement::CompareElements(const EbmlElement *A, const EbmlElement *B)
651{
652        if (EbmlId(*A) == EbmlId(*B))
653                return A->IsSmallerThan(B);
654        else
655                return false;
656}
657
658void EbmlElement::Read(EbmlStream & inDataStream, const EbmlSemanticContext & Context, int & UpperEltFound, EbmlElement * & FoundElt, bool AllowDummyElt, ScopeMode ReadFully)
659{
660        ReadData(inDataStream.I_O(), ReadFully);
661}
662
663bool EbmlElement::ForceSize(uint64 NewSize)
664{
665        if (bSizeIsFinite) {
666                return false;
667        }
668
669        int OldSizeLen = CodedSizeLength(Size, SizeLength, bSizeIsFinite);
670        uint64 OldSize = Size;
671
672        Size = NewSize;
673
674        if (CodedSizeLength(Size, SizeLength, bSizeIsFinite) == OldSizeLen) {
675                bSizeIsFinite = true;
676                return true;
677        }
678        Size = OldSize;
679
680        return false;
681}
682
683filepos_t EbmlElement::OverwriteHead(IOCallback & output, bool bKeepPosition)
684{
685        if (ElementPosition == 0) {
686                return 0; // the element has not been written
687        }
688
689        uint64 CurrentPosition = output.getFilePointer();
690        output.setFilePointer(GetElementPosition());
691        filepos_t Result = MakeRenderHead(output, bKeepPosition);
692        output.setFilePointer(CurrentPosition);
693        return Result;
694}
695
696uint64 EbmlElement::VoidMe(IOCallback & output, bool bWithDefault)
697{
698        if (ElementPosition == 0) {
699                return 0; // the element has not been written
700        }
701
702        EbmlVoid Dummy;
703        return Dummy.Overwrite(*this, output, bWithDefault);
704}
705
706END_LIBEBML_NAMESPACE
Note: See TracBrowser for help on using the repository browser.