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 file is part of libebml.
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Lesser General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2.1 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** Lesser General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Lesser General Public
21 ** License along with this library; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 **
24 ** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.
25 **
26 ** Contact license@matroska.org if any conditions of this licensing are
27 ** not clear to you.
28 **
29 **********************************************************************/
30
31 /*!
32 \file
33 \version \$Id: EbmlVoid.cpp 1232 2005-10-15 15:56:52Z robux4 $
34 \author Steve Lhomme <robux4 @ users.sf.net>
35 */
36 #include "ebml/EbmlVoid.h"
37 #include "ebml/EbmlContexts.h"
38
39 START_LIBEBML_NAMESPACE
40
41 DEFINE_EBML_CLASS_GLOBAL(EbmlVoid, 0xEC, 1, "EBMLVoid")
42
EbmlVoid()43 EbmlVoid::EbmlVoid()
44 {
45 SetValueIsSet();
46 }
47
RenderData(IOCallback & output,bool,bool)48 filepos_t EbmlVoid::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */)
49 {
50 // write dummy data by 4KB chunks
51 static binary DummyBuf[4*1024];
52
53 uint64 SizeToWrite = GetSize();
54 while (SizeToWrite > 4*1024) {
55 output.writeFully(DummyBuf, 4*1024);
56 SizeToWrite -= 4*1024;
57 }
58 output.writeFully(DummyBuf, SizeToWrite);
59 return GetSize();
60 }
61
ReplaceWith(EbmlElement & EltToReplaceWith,IOCallback & output,bool ComeBackAfterward,bool bWithDefault)62 uint64 EbmlVoid::ReplaceWith(EbmlElement & EltToReplaceWith, IOCallback & output, bool ComeBackAfterward, bool bWithDefault)
63 {
64 EltToReplaceWith.UpdateSize(bWithDefault);
65 if (HeadSize() + GetSize() < EltToReplaceWith.GetSize() + EltToReplaceWith.HeadSize()) {
66 // the element can't be written here !
67 return INVALID_FILEPOS_T;
68 }
69 if (HeadSize() + GetSize() - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() == 1) {
70 // there is not enough space to put a filling element
71 return INVALID_FILEPOS_T;
72 }
73
74 uint64 CurrentPosition = output.getFilePointer();
75
76 output.setFilePointer(GetElementPosition());
77 EltToReplaceWith.Render(output, bWithDefault);
78
79 if (HeadSize() + GetSize() - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() > 1) {
80 // fill the rest with another void element
81 EbmlVoid aTmp;
82 aTmp.SetSize_(HeadSize() + GetSize() - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() - 1); // 1 is the length of the Void ID
83 int HeadBefore = aTmp.HeadSize();
84 aTmp.SetSize_(aTmp.GetSize() - CodedSizeLength(aTmp.GetSize(), aTmp.GetSizeLength(), aTmp.IsFiniteSize()));
85 int HeadAfter = aTmp.HeadSize();
86 if (HeadBefore != HeadAfter) {
87 aTmp.SetSizeLength(CodedSizeLength(aTmp.GetSize(), aTmp.GetSizeLength(), aTmp.IsFiniteSize()) - (HeadAfter - HeadBefore));
88 }
89 aTmp.RenderHead(output, false, bWithDefault); // the rest of the data is not rewritten
90 }
91
92 if (ComeBackAfterward) {
93 output.setFilePointer(CurrentPosition);
94 }
95
96 return GetSize() + HeadSize();
97 }
98
Overwrite(const EbmlElement & EltToVoid,IOCallback & output,bool ComeBackAfterward,bool bWithDefault)99 uint64 EbmlVoid::Overwrite(const EbmlElement & EltToVoid, IOCallback & output, bool ComeBackAfterward, bool bWithDefault)
100 {
101 // EltToVoid.UpdateSize(bWithDefault);
102 if (EltToVoid.GetElementPosition() == 0) {
103 // this element has never been written
104 return 0;
105 }
106 if (EltToVoid.GetSize() + EltToVoid.HeadSize() <2) {
107 // the element can't be written here !
108 return 0;
109 }
110
111 uint64 CurrentPosition = output.getFilePointer();
112
113 output.setFilePointer(EltToVoid.GetElementPosition());
114
115 // compute the size of the voided data based on the original one
116 SetSize(EltToVoid.GetSize() + EltToVoid.HeadSize() - 1); // 1 for the ID
117 SetSize(GetSize() - CodedSizeLength(GetSize(), GetSizeLength(), IsFiniteSize()));
118 // make sure we handle even the strange cases
119 //uint32 A1 = GetSize() + HeadSize();
120 //uint32 A2 = EltToVoid.GetSize() + EltToVoid.HeadSize();
121 if (GetSize() + HeadSize() != EltToVoid.GetSize() + EltToVoid.HeadSize()) {
122 SetSize(GetSize()-1);
123 SetSizeLength(CodedSizeLength(GetSize(), GetSizeLength(), IsFiniteSize()) + 1);
124 }
125
126 if (GetSize() != 0) {
127 RenderHead(output, false, bWithDefault); // the rest of the data is not rewritten
128 }
129
130 if (ComeBackAfterward) {
131 output.setFilePointer(CurrentPosition);
132 }
133
134 return EltToVoid.GetSize() + EltToVoid.HeadSize();
135 }
136
137 END_LIBEBML_NAMESPACE
138