1 /*
2  * $Id$
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 
ReadData(ebml_binary * Element,stream * Input,const ebml_parser_context * ParserContext,bool_t AllowDummyElt,int Scope,size_t DepthCheckCRC)31 static err_t ReadData(ebml_binary *Element, stream *Input, const ebml_parser_context *ParserContext, bool_t AllowDummyElt, int Scope, size_t DepthCheckCRC)
32 {
33     err_t Result;
34 
35     Element->Base.bValueIsSet = 0;
36 
37     if (Scope == SCOPE_NO_DATA)
38         return ERR_NONE;
39 
40     if (Stream_Seek(Input,EBML_ElementPositionData((ebml_element*)Element),SEEK_SET)==INVALID_FILEPOS_T)
41     {
42         Result = ERR_READ;
43         goto failed;
44     }
45 
46     if (!ArrayResize(&Element->Data,(size_t)Element->Base.DataSize,0))
47     {
48         Result = ERR_OUT_OF_MEMORY;
49         goto failed;
50     }
51 
52     Result = Stream_Read(Input,ARRAYBEGIN(Element->Data,void),(size_t)Element->Base.DataSize,NULL);
53     if (Result == ERR_NONE)
54         Element->Base.bValueIsSet = 1;
55 failed:
56     return Result;
57 }
58 
59 #if defined(CONFIG_EBML_WRITING)
RenderData(ebml_binary * Element,stream * Output,bool_t bForceWithoutMandatory,bool_t bWithDefault,filepos_t * Rendered)60 static err_t RenderData(ebml_binary *Element, stream *Output, bool_t bForceWithoutMandatory, bool_t bWithDefault, filepos_t *Rendered)
61 {
62     size_t Written;
63     err_t Err = Stream_Write(Output,ARRAYBEGIN(Element->Data,uint8_t),ARRAYCOUNT(Element->Data,uint8_t),&Written);
64     if (Rendered)
65         *Rendered = Written;
66     return Err;
67 }
68 #endif
69 
Delete(ebml_binary * Element)70 static void Delete(ebml_binary *Element)
71 {
72     ArrayClear(&Element->Data);
73 }
74 
IsDefaultValue(const ebml_binary * Element)75 static bool_t IsDefaultValue(const ebml_binary *Element)
76 {
77     return 0; // TODO: a default binary value needs a size too (use a structure to set the value in the structure)
78 }
79 
UpdateDataSize(ebml_binary * Element,bool_t bWithDefault,bool_t bForceWithoutMandatory)80 static filepos_t UpdateDataSize(ebml_binary *Element, bool_t bWithDefault, bool_t bForceWithoutMandatory)
81 {
82 	Element->Base.DataSize = ARRAYCOUNT(Element->Data,uint8_t);
83 
84 	return INHERITED(Element,ebml_element_vmt,EBML_BINARY_CLASS)->UpdateDataSize(Element, bWithDefault, bForceWithoutMandatory);
85 }
86 
ValidateSize(const ebml_element * p)87 static bool_t ValidateSize(const ebml_element *p)
88 {
89     return EBML_ElementIsFiniteSize(p);
90 }
91 
Copy(const ebml_binary * Element,const void * Cookie)92 static ebml_binary *Copy(const ebml_binary *Element, const void *Cookie)
93 {
94     ebml_binary *Result = (ebml_binary*)EBML_ElementCreate(Element,Element->Base.Context,0,Cookie);
95     if (Result)
96     {
97         ArrayCopy(&Result->Data,&Element->Data);
98         Result->Base.bValueIsSet = Element->Base.bValueIsSet;
99         Result->Base.DataSize = Element->Base.DataSize;
100         Result->Base.ElementPosition = Element->Base.ElementPosition;
101         Result->Base.SizeLength = Element->Base.SizeLength;
102         Result->Base.SizePosition = Element->Base.SizePosition;
103         Result->Base.bNeedDataSizeUpdate = Element->Base.bNeedDataSizeUpdate;
104     }
105     return Result;
106 }
107 
META_START(EBMLBinary_Class,EBML_BINARY_CLASS)108 META_START(EBMLBinary_Class,EBML_BINARY_CLASS)
109 META_CLASS(SIZE,sizeof(ebml_binary))
110 META_CLASS(DELETE,Delete)
111 META_DATA(TYPE_ARRAY,0,ebml_binary,Data)
112 META_VMT(TYPE_FUNC,ebml_element_vmt,ValidateSize,ValidateSize)
113 META_VMT(TYPE_FUNC,ebml_element_vmt,ReadData,ReadData)
114 META_VMT(TYPE_FUNC,ebml_element_vmt,IsDefaultValue,IsDefaultValue)
115 META_VMT(TYPE_FUNC,ebml_element_vmt,UpdateDataSize,UpdateDataSize)
116 #if defined(CONFIG_EBML_WRITING)
117 META_VMT(TYPE_FUNC,ebml_element_vmt,RenderData,RenderData)
118 #endif
119 META_VMT(TYPE_FUNC,ebml_element_vmt,Copy,Copy)
120 META_END(EBML_ELEMENT_CLASS)
121 
122 err_t EBML_BinarySetData(ebml_binary *Element, const uint8_t *Data, size_t DataSize)
123 {
124     if (!ArrayResize(&Element->Data,DataSize,0))
125         return ERR_OUT_OF_MEMORY;
126     memcpy(ARRAYBEGIN(Element->Data,void),Data,DataSize);
127     Element->Base.DataSize = DataSize;
128     Element->Base.bNeedDataSizeUpdate = 0;
129     Element->Base.bValueIsSet = 1;
130     return ERR_NONE;
131 }
132 
EBML_BinaryGetData(ebml_binary * Element)133 const uint8_t *EBML_BinaryGetData(ebml_binary *Element)
134 {
135     if (!ARRAYCOUNT(Element->Data,uint8_t))
136         return NULL;
137     return ARRAYBEGIN(Element->Data,uint8_t);
138 }
139