1/****************************************************************************
2** libebml : parse EBML files, see http://embl.sourceforge.net/
3**
4** <file/class description>
5**
6** Copyright (C) 2002-2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23**
24** See http://www.matroska.org/license/lgpl/ 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
39START_LIBEBML_NAMESPACE
40
41EbmlId EbmlVoid_TheId(0xEC, 1);
42const EbmlCallbacks EbmlVoid::ClassInfos(EbmlVoid::Create, EbmlVoid_TheId, "EBMLVoid", EbmlVoid_Context);
43
44EbmlVoid::EbmlVoid()
45{
46	bValueIsSet = true;
47}
48
49uint32 EbmlVoid::RenderData(IOCallback & output, bool bForceRender, bool bKeepIntact)
50{
51	// write dummy data by 4KB chunks
52	static binary DummyBuf[4*1024];
53
54	uint64 SizeToWrite = Size;
55	while (SizeToWrite > 4*1024)
56	{
57		output.writeFully(DummyBuf, 4*1024);
58		SizeToWrite -= 4*1024;
59	}
60	output.writeFully(DummyBuf, SizeToWrite);
61	return Size;
62}
63
64uint64 EbmlVoid::ReplaceWith(EbmlElement & EltToReplaceWith, IOCallback & output, bool ComeBackAfterward, bool bKeepIntact)
65{
66	EltToReplaceWith.UpdateSize(bKeepIntact);
67	if (HeadSize() + Size < EltToReplaceWith.GetSize() + EltToReplaceWith.HeadSize()) {
68		// the element can't be written here !
69		return 0;
70	}
71	if (HeadSize() + Size - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() == 1) {
72		// there is not enough space to put a filling element
73		return 0;
74	}
75
76	uint64 CurrentPosition = output.getFilePointer();
77
78	output.setFilePointer(GetElementPosition());
79	EltToReplaceWith.Render(output, bKeepIntact);
80
81	if (HeadSize() + Size - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() > 1) {
82	  // fill the rest with another void element
83	  EbmlVoid aTmp;
84	  aTmp.SetSize(HeadSize() + Size - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() - 1); // 1 is the length of the Void ID
85	  int HeadBefore = aTmp.HeadSize();
86	  aTmp.SetSize(aTmp.GetSize() - CodedSizeLength(aTmp.Size, aTmp.SizeLength, aTmp.bSizeIsFinite));
87	  int HeadAfter = aTmp.HeadSize();
88	  if (HeadBefore != HeadAfter) {
89		  aTmp.SetSizeLength(CodedSizeLength(aTmp.Size, aTmp.SizeLength, aTmp.bSizeIsFinite) - (HeadAfter - HeadBefore));
90	  }
91	  aTmp.RenderHead(output, false, bKeepIntact); // the rest of the data is not rewritten
92	}
93
94	if (ComeBackAfterward) {
95		output.setFilePointer(CurrentPosition);
96	}
97
98	return Size + HeadSize();
99}
100
101uint64 EbmlVoid::Overwrite(const EbmlElement & EltToVoid, IOCallback & output, bool ComeBackAfterward, bool bKeepIntact)
102{
103//	EltToVoid.UpdateSize(bKeepIntact);
104	if (EltToVoid.GetElementPosition() == 0) {
105		// this element has never been written
106		return 0;
107	}
108	if (EltToVoid.GetSize() + EltToVoid.HeadSize() <2) {
109		// the element can't be written here !
110		return 0;
111	}
112
113	uint64 CurrentPosition = output.getFilePointer();
114
115	output.setFilePointer(EltToVoid.GetElementPosition());
116
117	// compute the size of the voided data based on the original one
118	Size = EltToVoid.GetSize() + EltToVoid.HeadSize() - 1; // 1 for the ID
119	Size -= CodedSizeLength(Size, SizeLength, bSizeIsFinite);
120	// make sure we handle even the strange cases
121	//uint32 A1 = Size + HeadSize();
122	//uint32 A2 = EltToVoid.GetSize() + EltToVoid.HeadSize();
123	if (Size + HeadSize() != EltToVoid.GetSize() + EltToVoid.HeadSize()) {
124		Size--;
125		SetSizeLength(CodedSizeLength(Size, SizeLength, bSizeIsFinite) + 1);
126	}
127
128	if (Size != 0) {
129		RenderHead(output, false, bKeepIntact); // the rest of the data is not rewritten
130	}
131
132	if (ComeBackAfterward) {
133		output.setFilePointer(CurrentPosition);
134	}
135
136	return EltToVoid.GetSize() + EltToVoid.HeadSize();
137}
138
139END_LIBEBML_NAMESPACE
140