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