1 /*
2 * $Id: ebmlvoid.c 642 2010-11-28 08:38:47Z robux4 $
3 * Copyright (c) 2008-2010, Matroska (non-profit organisation)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Matroska assocation nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY the Matroska association ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL The Matroska Foundation BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include "ebml/ebml.h"
29 #include "ebml/ebml_internal.h"
30
IsDefaultValue(const ebml_element * Element)31 static bool_t IsDefaultValue(const ebml_element *Element)
32 {
33 return 0;
34 }
35
ReadData(ebml_element * Element,stream * Input,const ebml_parser_context * ParserContext,bool_t AllowDummyElt,int Scope,size_t DepthCheckCRC)36 static err_t ReadData(ebml_element *Element, stream *Input, const ebml_parser_context *ParserContext, bool_t AllowDummyElt, int Scope, size_t DepthCheckCRC)
37 {
38 EBML_ElementSkipData(Element,Input,ParserContext,NULL,AllowDummyElt);
39 return ERR_NONE;
40 }
41
42 #if defined(CONFIG_EBML_WRITING)
RenderData(ebml_element * Element,stream * Output,bool_t bForceWithoutMandatory,bool_t bWithDefault,filepos_t * Rendered)43 static err_t RenderData(ebml_element *Element, stream *Output, bool_t bForceWithoutMandatory, bool_t bWithDefault, filepos_t *Rendered)
44 {
45 size_t Written, Left = (size_t)Element->DataSize;
46 err_t Err = ERR_NONE;
47 uint8_t Buf[2*1024]; // write 2 KB chunks at a time
48 memset(Buf,0,sizeof(Buf));
49 while (Err==ERR_NONE && Left)
50 {
51 Err = Stream_Write(Output,Buf,min(Left,sizeof(Buf)),&Written);
52 if (Err == ERR_NONE)
53 Left -= min(Left,sizeof(Buf));
54 }
55 if (Rendered)
56 *Rendered = Element->DataSize - Left;
57 return Err;
58 }
59 #endif
60
Copy(const ebml_element * Element,const void * Cookie)61 static ebml_element *Copy(const ebml_element *Element, const void *Cookie)
62 {
63 ebml_element *Result = EBML_ElementCreate(Element,Element->Context,0,Cookie);
64 if (Result)
65 {
66 Result->bValueIsSet = Element->bValueIsSet;
67 Result->DataSize = Element->DataSize;
68 Result->ElementPosition = Element->ElementPosition;
69 Result->SizeLength = Element->SizeLength;
70 Result->SizePosition = Element->SizePosition;
71 Result->bNeedDataSizeUpdate = Element->bNeedDataSizeUpdate;
72 }
73 return Result;
74 }
75
META_START(EBMLVoid_Class,EBML_VOID_CLASS)76 META_START(EBMLVoid_Class,EBML_VOID_CLASS)
77 META_VMT(TYPE_FUNC,ebml_element_vmt,IsDefaultValue,IsDefaultValue)
78 META_VMT(TYPE_FUNC,ebml_element_vmt,ReadData,ReadData)
79 #if defined(CONFIG_EBML_WRITING)
80 META_VMT(TYPE_FUNC,ebml_element_vmt,RenderData,RenderData)
81 #endif
82 META_VMT(TYPE_FUNC,ebml_element_vmt,Copy,Copy)
83 META_END(EBML_ELEMENT_CLASS)
84
85 #if defined(CONFIG_EBML_WRITING)
86 bool_t EBML_VoidSetFullSize(ebml_element *Void, filepos_t DataSize)
87 {
88 assert(Node_IsPartOf(Void,EBML_VOID_CLASS));
89 Void->DataSize = DataSize - 1 - EBML_CodedSizeLength(DataSize,0,1); // 1 is the length of the Void ID
90 Void->bValueIsSet = 1;
91 Void->bNeedDataSizeUpdate = 0;
92 return Void->DataSize >= 0;
93 }
94
EBML_VoidReplaceWith(ebml_element * Void,ebml_element * ReplacedWith,stream * Output,bool_t ComeBackAfterward,bool_t bWithDefault)95 filepos_t EBML_VoidReplaceWith(ebml_element *Void, ebml_element *ReplacedWith, stream *Output, bool_t ComeBackAfterward, bool_t bWithDefault)
96 {
97 filepos_t CurrentPosition;
98 assert(Node_IsPartOf(Void,EBML_VOID_CLASS));
99
100 EBML_ElementUpdateSize(ReplacedWith,bWithDefault,0);
101 if (EBML_ElementFullSize(Void,1) < EBML_ElementFullSize(ReplacedWith,1))
102 // the element can't be written here !
103 return INVALID_FILEPOS_T;
104 if (EBML_ElementFullSize(Void,1) - EBML_ElementFullSize(ReplacedWith,1) == 1)
105 // there is not enough space to put a filling element
106 return INVALID_FILEPOS_T;
107
108 CurrentPosition = Stream_Seek(Output,0,SEEK_CUR);
109
110 Stream_Seek(Output,Void->ElementPosition,SEEK_SET);
111 EBML_ElementRender(ReplacedWith,Output,bWithDefault,0,1,NULL);
112
113 if (EBML_ElementFullSize(Void,1) - EBML_ElementFullSize(ReplacedWith,1) > 1)
114 {
115 // fill the rest with another void element
116 ebml_element *aTmp = EBML_ElementCreate(Void,Void->Context,0,NULL);
117 if (aTmp)
118 {
119 filepos_t HeadBefore,HeadAfter;
120 EBML_VoidSetFullSize(aTmp, EBML_ElementFullSize(Void,1) - EBML_ElementFullSize(ReplacedWith,1));
121 HeadBefore = EBML_ElementFullSize(aTmp,1) - aTmp->DataSize;
122 aTmp->DataSize = aTmp->DataSize - EBML_CodedSizeLength(aTmp->DataSize, aTmp->SizeLength, EBML_ElementIsFiniteSize(aTmp));
123 HeadAfter = EBML_ElementFullSize(aTmp,1) - aTmp->DataSize;
124 if (HeadBefore != HeadAfter)
125 aTmp->SizeLength = (int8_t)(EBML_CodedSizeLength(aTmp->DataSize, aTmp->SizeLength, EBML_ElementIsFiniteSize(aTmp)) - (HeadAfter - HeadBefore));
126 EBML_ElementRenderHead(aTmp,Output,0,NULL);
127 NodeDelete((node*)aTmp);
128 }
129 }
130
131 if (ComeBackAfterward)
132 Stream_Seek(Output,CurrentPosition,SEEK_SET);
133
134 return EBML_ElementFullSize(Void,1);
135 }
136 #endif
137