source: libebml/src/EbmlElement.cpp @ 1443

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

Merge libebml and libmatroska changes.

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                        }
490
491                        if (Result != NULL) {
492                                unsigned int EltIndex;
493                                // data known in this Master's context
494                                for (EltIndex = 0; EltIndex < EBML_CTX_SIZE(Context); EltIndex++) {
495                                        if (EbmlId(*Result) == EBML_CTX_IDX_ID(Context,EltIndex)) {
496                                                // skip the data with its own context
497                                                Result = Result->SkipData(DataStream, EBML_SEM_CONTEXT(EBML_CTX_IDX(Context,EltIndex)), NULL);
498                                                break; // let's go to the next ID
499                                        }
500                                }
501
502                                if (EltIndex >= EBML_CTX_SIZE(Context)) {
503                                        if (EBML_CTX_PARENT(Context) != NULL) {
504                                                Result = SkipData(DataStream, *EBML_CTX_PARENT(Context), Result);
505                                        } else {
506                                                assert(Context.GetGlobalContext != NULL);
507                                                if (Context != Context.GetGlobalContext()) {
508                                                        Result = SkipData(DataStream, Context.GetGlobalContext(), Result);
509                                                } else {
510                                                        bEndFound = true;
511                                                }
512                                        }
513                                }
514                        } else {
515                                bEndFound = true;
516                        }
517                }
518        }
519        return Result;
520}
521
522EbmlElement *EbmlElement::CreateElementUsingContext(const EbmlId & aID, const EbmlSemanticContext & Context,
523                                                                                                        int & LowLevel, bool IsGlobalContext, bool bAllowDummy, unsigned int MaxLowerLevel)
524{
525        unsigned int ContextIndex;
526        EbmlElement *Result = NULL;
527
528        // elements at the current level
529        for (ContextIndex = 0; ContextIndex < EBML_CTX_SIZE(Context); ContextIndex++) {
530                if (aID == EBML_CTX_IDX_ID(Context,ContextIndex)) {
531            return &EBML_SEM_CREATE(EBML_CTX_IDX(Context,ContextIndex));
532                }
533        }
534
535        // global elements
536        assert(Context.GetGlobalContext != NULL); // global should always exist, at least the EBML ones
537        const EbmlSemanticContext & tstContext = Context.GetGlobalContext();
538        if (tstContext != Context) {
539                LowLevel--;
540                MaxLowerLevel--;
541                // recursive is good, but be carefull...
542                Result = CreateElementUsingContext(aID, tstContext, LowLevel, true, bAllowDummy, MaxLowerLevel);
543                if (Result != NULL) {
544                        return Result;
545                }
546                LowLevel++;
547                MaxLowerLevel++;
548        } else {
549                return NULL;
550        }
551
552        // parent elements
553        if (EBML_CTX_MASTER(Context) != NULL && aID == EBML_INFO_ID(*EBML_CTX_MASTER(Context))) {
554                LowLevel++; // already one level up (same as context)
555                return &EBML_INFO_CREATE(*EBML_CTX_MASTER(Context));
556        }
557
558        // check wether it's not part of an upper context
559        if (EBML_CTX_PARENT(Context) != NULL) {
560                LowLevel++;
561                MaxLowerLevel++;
562                return CreateElementUsingContext(aID, *EBML_CTX_PARENT(Context), LowLevel, IsGlobalContext, bAllowDummy, MaxLowerLevel);
563        }
564
565        if (!IsGlobalContext && bAllowDummy) {
566                LowLevel = 0;
567                Result = new EbmlDummy(aID);
568        }
569
570        return Result;
571}
572
573/*!
574        \todo verify that the size written is the same as the data written
575*/
576filepos_t EbmlElement::Render(IOCallback & output, bool bWithDefault, bool bKeepPosition, bool bForceRender)
577{
578        assert(bValueIsSet || (bWithDefault && DefaultISset())); // an element is been rendered without a value set !!!
579                                 // it may be a mandatory element without a default value
580        try {
581                if (!bWithDefault && IsDefaultValue()) {
582                        return 0;
583                }
584#if defined(_DEBUG) || defined(DEBUG)
585                uint64 SupposedSize = UpdateSize(bWithDefault, bForceRender);
586#endif // _DEBUG
587                filepos_t result = RenderHead(output, bForceRender, bWithDefault, bKeepPosition);
588                uint64 WrittenSize = RenderData(output, bForceRender, bWithDefault);
589#if defined(_DEBUG) || defined(DEBUG)
590        if (static_cast<int64>(SupposedSize) != (0-1)) assert(WrittenSize == SupposedSize);
591#endif // DEBUG
592                result += WrittenSize;
593                return result;
594        } catch (std::exception & ex) {
595//              const char * What = ex.what();
596                assert(false); // we should never be here !
597                return 0;
598        }
599}
600
601/*!
602        \todo store the position of the Size writing for elements with unknown size
603        \todo handle exceptions on errors
604        \todo handle CodeSize bigger than 5 bytes
605*/
606filepos_t EbmlElement::RenderHead(IOCallback & output, bool bForceRender, bool bWithDefault, bool bKeepPosition)
607{
608        if (EBML_ID_LENGTH((const EbmlId&)*this) <= 0 || EBML_ID_LENGTH((const EbmlId&)*this) > 4)
609                return 0;
610
611        UpdateSize(bWithDefault, bForceRender);
612
613        return MakeRenderHead(output, bKeepPosition);
614}
615
616filepos_t EbmlElement::MakeRenderHead(IOCallback & output, bool bKeepPosition)
617{
618        binary FinalHead[4+8]; // Class D + 64 bits coded size
619        unsigned int FinalHeadSize;
620
621        FinalHeadSize = EBML_ID_LENGTH((const EbmlId&)*this);
622        EbmlId(*this).Fill(FinalHead);
623
624        int CodedSize = CodedSizeLength(Size, SizeLength, bSizeIsFinite);
625        CodedValueLength(Size, CodedSize, &FinalHead[FinalHeadSize]);
626        FinalHeadSize += CodedSize;
627
628        output.writeFully(FinalHead, FinalHeadSize);
629        if (!bKeepPosition) {
630                ElementPosition = output.getFilePointer() - FinalHeadSize;
631                SizePosition = ElementPosition + EBML_ID_LENGTH((const EbmlId&)*this);
632        }
633
634        return FinalHeadSize;
635}
636
637uint64 EbmlElement::ElementSize(bool bWithDefault) const
638{
639        if (!bWithDefault && IsDefaultValue())
640                return 0; // won't be saved
641        return Size + EBML_ID_LENGTH((const EbmlId&)*this) + CodedSizeLength(Size, SizeLength, bSizeIsFinite);
642}
643
644bool EbmlElement::IsSmallerThan(const EbmlElement *Cmp) const
645{
646        return EbmlId(*this) == EbmlId(*Cmp);
647}
648
649bool EbmlElement::CompareElements(const EbmlElement *A, const EbmlElement *B)
650{
651        if (EbmlId(*A) == EbmlId(*B))
652                return A->IsSmallerThan(B);
653        else
654                return false;
655}
656
657void EbmlElement::Read(EbmlStream & inDataStream, const EbmlSemanticContext & Context, int & UpperEltFound, EbmlElement * & FoundElt, bool AllowDummyElt, ScopeMode ReadFully)
658{
659        ReadData(inDataStream.I_O(), ReadFully);
660}
661
662bool EbmlElement::ForceSize(uint64 NewSize)
663{
664        if (bSizeIsFinite) {
665                return false;
666        }
667
668        int OldSizeLen = CodedSizeLength(Size, SizeLength, bSizeIsFinite);
669        uint64 OldSize = Size;
670
671        Size = NewSize;
672
673        if (CodedSizeLength(Size, SizeLength, bSizeIsFinite) == OldSizeLen) {
674                bSizeIsFinite = true;
675                return true;
676        }
677        Size = OldSize;
678
679        return false;
680}
681
682filepos_t EbmlElement::OverwriteHead(IOCallback & output, bool bKeepPosition)
683{
684        if (ElementPosition == 0) {
685                return 0; // the element has not been written
686        }
687
688        uint64 CurrentPosition = output.getFilePointer();
689        output.setFilePointer(GetElementPosition());
690        filepos_t Result = MakeRenderHead(output, bKeepPosition);
691        output.setFilePointer(CurrentPosition);
692        return Result;
693}
694
695uint64 EbmlElement::VoidMe(IOCallback & output, bool bWithDefault)
696{
697        if (ElementPosition == 0) {
698                return 0; // the element has not been written
699        }
700
701        EbmlVoid Dummy;
702        return Dummy.Overwrite(*this, output, bWithDefault);
703}
704
705END_LIBEBML_NAMESPACE
Note: See TracBrowser for help on using the repository browser.