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
31 #if defined(CONFIG_EBML_UNICODE)
EBML_UniStringSetValue(ebml_string * Element,const tchar_t * Value)32 err_t EBML_UniStringSetValue(ebml_string *Element,const tchar_t *Value)
33 {
34 char Data[2048];
35 if (!Node_IsPartOf(Element,EBML_UNISTRING_CLASS))
36 return ERR_INVALID_DATA;
37 Node_ToUTF8(Element,Data,sizeof(Data)-1,Value);
38 Data[sizeof(Data)-1] = 0;
39 return EBML_StringSetValue(Element,Data);
40 }
41 #endif
42
EBML_StringSetValue(ebml_string * Element,const char * Value)43 err_t EBML_StringSetValue(ebml_string *Element,const char *Value)
44 {
45 if (Element->Base.bValueIsSet && Element->Buffer)
46 free((char*)Element->Buffer);
47 Element->Buffer = strdup(Value);
48 Element->Base.bValueIsSet = 1;
49 Element->Base.DataSize = strlen(Element->Buffer);
50 Element->Base.bNeedDataSizeUpdate = 0;
51 return ERR_NONE;
52 }
53
EBML_StringGet(ebml_string * Element,tchar_t * Out,size_t OutLen)54 void EBML_StringGet(ebml_string *Element,tchar_t *Out, size_t OutLen)
55 {
56 if (!Element->Buffer)
57 {
58 if (OutLen)
59 *Out = 0;
60 }
61 else
62 {
63 #if defined(CONFIG_EBML_UNICODE)
64 if (Node_IsPartOf(Element,EBML_UNISTRING_CLASS))
65 Node_FromUTF8(Element,Out,OutLen,Element->Buffer);
66 else
67 #endif
68 Node_FromStr(Element,Out,OutLen,Element->Buffer);
69 }
70 }
71
ReadData(ebml_string * Element,stream * Input,const ebml_parser_context * ParserContext,bool_t AllowDummyElt,int Scope,size_t DepthCheckCRC)72 static err_t ReadData(ebml_string *Element, stream *Input, const ebml_parser_context *ParserContext, bool_t AllowDummyElt, int Scope, size_t DepthCheckCRC)
73 {
74 err_t Result;
75 char *Buffer;
76
77 Element->Base.bValueIsSet = 0;
78
79 if (Scope == SCOPE_NO_DATA)
80 return ERR_NONE;
81
82 if (Stream_Seek(Input,EBML_ElementPositionData((ebml_element*)Element),SEEK_SET)==INVALID_FILEPOS_T)
83 {
84 return ERR_READ;
85 }
86
87 Buffer = malloc((size_t)Element->Base.DataSize+1);
88 if (!Buffer)
89 return ERR_OUT_OF_MEMORY;
90
91 Result = Stream_Read(Input,Buffer,(size_t)Element->Base.DataSize,NULL);
92 if (Result != ERR_NONE)
93 goto failed;
94
95 Buffer[Element->Base.DataSize] = 0;
96 Element->Buffer = Buffer;
97 Element->Base.bValueIsSet = 1;
98 return ERR_NONE;
99
100 failed:
101 free(Buffer);
102 Element->Buffer = NULL;
103 return Result;
104 }
105
106 #if defined(CONFIG_EBML_WRITING)
RenderData(ebml_string * Element,stream * Output,bool_t bForceWithoutMandatory,bool_t bWithDefault,filepos_t * Rendered)107 static err_t RenderData(ebml_string *Element, stream *Output, bool_t bForceWithoutMandatory, bool_t bWithDefault, filepos_t *Rendered)
108 {
109 size_t Written;
110 err_t Err = Stream_Write(Output,Element->Buffer,(size_t)Element->Base.DataSize,&Written);
111 if (Rendered)
112 *Rendered = Written;
113 if ((Err == ERR_NONE) && (Element->Base.DefaultSize > (int)Element->Base.DataSize))
114 {
115 char *Padding = malloc(Element->Base.DefaultSize - (int)Element->Base.DataSize);
116 if (!Padding)
117 return ERR_OUT_OF_MEMORY;
118 memset(Padding,0,Element->Base.DefaultSize - (int)Element->Base.DataSize);
119 Err = Stream_Write(Output,Padding,Element->Base.DefaultSize - (int)Element->Base.DataSize,&Written);
120 if (Rendered)
121 *Rendered += Written;
122 free(Padding);
123 }
124 return Err;
125 }
126 #endif
127
128 #if 0
129 err_t EBML_AsciiStringRead(ebml_string *Element, stream *Input, tchar_t *Out, size_t OutLen)
130 {
131 if (Node_IsPartOf(Element,EBML_STRING_CLASS))
132 return ERR_INVALID_DATA;
133 else
134 {
135 err_t Result = EBML_ElementReadData(Element, Input);
136 if (Result != ERR_NONE)
137 return Result;
138 Node_FromStr(Element,Out,OutLen,Element->Buffer);
139 return Result;
140 }
141 }
142
143 err_t EBML_UnicodeStringRead(ebml_string *Element, stream *Input, tchar_t *Out, size_t OutLen)
144 {
145 if (Node_IsPartOf(Element,EBML_UNISTRING_CLASS))
146 return ERR_INVALID_DATA;
147 else
148 {
149 err_t Result = EBML_ElementReadData(Element, Input);
150 if (Result != ERR_NONE)
151 return Result;
152 Node_FromUTF8(Element,Out,OutLen,Element->Buffer);
153 return Result;
154 }
155 }
156 #endif
157
Delete(ebml_string * p)158 static void Delete(ebml_string *p)
159 {
160 if (p->Buffer)
161 free((char*)p->Buffer);
162 }
163
UpdateDataSize(ebml_string * Element,bool_t bWithDefault,bool_t bForceWithoutMandatory)164 static filepos_t UpdateDataSize(ebml_string *Element, bool_t bWithDefault, bool_t bForceWithoutMandatory)
165 {
166 if (EBML_ElementNeedsDataSizeUpdate(Element, bWithDefault))
167 Element->Base.DataSize = strlen(Element->Buffer);
168
169 return INHERITED(Element,ebml_element_vmt,EBML_STRING_CLASS)->UpdateDataSize(Element, bWithDefault, bForceWithoutMandatory);
170 }
171
UpdateDataSizeUni(ebml_string * Element,bool_t bWithDefault,bool_t bForceWithoutMandatory)172 static filepos_t UpdateDataSizeUni(ebml_string *Element, bool_t bWithDefault, bool_t bForceWithoutMandatory)
173 {
174 if (EBML_ElementNeedsDataSizeUpdate(Element, bWithDefault))
175 Element->Base.DataSize = strlen(Element->Buffer);
176
177 return INHERITED(Element,ebml_element_vmt,EBML_UNISTRING_CLASS)->UpdateDataSize(Element, bWithDefault, bForceWithoutMandatory);
178 }
179
IsDefaultValue(const ebml_string * Element)180 static bool_t IsDefaultValue(const ebml_string *Element)
181 {
182 return Element->Base.Context->HasDefault && (!Element->Base.bValueIsSet || strcmp(Element->Buffer,(const char*)Element->Base.Context->DefaultValue)==0);
183 }
184
PostCreateString(ebml_element * Element,bool_t SetDefault)185 static void PostCreateString(ebml_element *Element, bool_t SetDefault)
186 {
187 INHERITED(Element,ebml_element_vmt,EBML_STRING_CLASS)->PostCreate(Element, SetDefault);
188 if (SetDefault && Element->Context->HasDefault)
189 EBML_StringSetValue((ebml_string*)Element, (const char *)Element->Context->DefaultValue);
190 }
191
PostCreateUniString(ebml_element * Element,bool_t SetDefault)192 static void PostCreateUniString(ebml_element *Element, bool_t SetDefault)
193 {
194 INHERITED(Element,ebml_element_vmt,EBML_UNISTRING_CLASS)->PostCreate(Element, SetDefault);
195 if (SetDefault && Element->Context->HasDefault)
196 EBML_StringSetValue((ebml_string*)Element, (const char *)Element->Context->DefaultValue);
197 }
198
Copy(const ebml_string * Element,const void * Cookie)199 static ebml_string *Copy(const ebml_string *Element, const void *Cookie)
200 {
201 ebml_string *Result = (ebml_string*)EBML_ElementCreate(Element,Element->Base.Context,0,Cookie);
202 if (Result)
203 {
204 Result->Buffer = strdup(Element->Buffer);
205 Result->Base.bValueIsSet = Element->Base.bValueIsSet;
206 Result->Base.DataSize = Element->Base.DataSize;
207 Result->Base.ElementPosition = Element->Base.ElementPosition;
208 Result->Base.SizeLength = Element->Base.SizeLength;
209 Result->Base.SizePosition = Element->Base.SizePosition;
210 Result->Base.bNeedDataSizeUpdate = Element->Base.bNeedDataSizeUpdate;
211 }
212 return Result;
213 }
214
215 META_START(EBMLString_Class,EBML_STRING_CLASS)
216 META_CLASS(SIZE,sizeof(ebml_string))
217 META_CLASS(DELETE,Delete)
218 META_VMT(TYPE_FUNC,ebml_element_vmt,ReadData,ReadData)
219 META_VMT(TYPE_FUNC,ebml_element_vmt,IsDefaultValue,IsDefaultValue)
220 META_VMT(TYPE_FUNC,ebml_element_vmt,UpdateDataSize,UpdateDataSize)
221 #if defined(CONFIG_EBML_WRITING)
222 META_VMT(TYPE_FUNC,ebml_element_vmt,RenderData,RenderData)
223 #endif
224 META_VMT(TYPE_FUNC,ebml_element_vmt,PostCreate,PostCreateString)
225 META_VMT(TYPE_FUNC,ebml_element_vmt,Copy,Copy)
226 META_END_CONTINUE(EBML_ELEMENT_CLASS)
227
228 META_START_CONTINUE(EBML_UNISTRING_CLASS)
229 META_CLASS(SIZE,sizeof(ebml_string))
230 META_CLASS(DELETE,Delete)
231 META_VMT(TYPE_FUNC,ebml_element_vmt,ReadData,ReadData)
232 META_VMT(TYPE_FUNC,ebml_element_vmt,IsDefaultValue,IsDefaultValue)
233 META_VMT(TYPE_FUNC,ebml_element_vmt,UpdateDataSize,UpdateDataSizeUni)
234 #if defined(CONFIG_EBML_WRITING)
235 META_VMT(TYPE_FUNC,ebml_element_vmt,RenderData,RenderData)
236 #endif
237 META_VMT(TYPE_FUNC,ebml_element_vmt,PostCreate,PostCreateUniString)
238 META_VMT(TYPE_FUNC,ebml_element_vmt,Copy,Copy)
239 META_END(EBML_ELEMENT_CLASS)
240