ebmlstring.c 8.52 KB
Newer Older
1
/*
Steve Lhomme's avatar
Steve Lhomme committed
2
 * $Id$
3
 * Copyright (c) 2008-2010, Matroska (non-profit organisation)
4 5 6 7 8 9 10 11 12
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
13
 *     * Neither the name of the Matroska assocation nor the
14 15 16
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
17
 * THIS SOFTWARE IS PROVIDED BY the Matroska association ``AS IS'' AND ANY
18 19 20 21 22 23 24 25 26 27 28
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL The Matroska Foundation BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "ebml/ebml.h"
29
#include "ebml/ebml_internal.h"
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

#if defined(CONFIG_EBML_UNICODE)
err_t EBML_UniStringSetValue(ebml_string *Element,const tchar_t *Value)
{
    char Data[2048];
    if (!Node_IsPartOf(Element,EBML_UNISTRING_CLASS))
        return ERR_INVALID_DATA;
    Node_ToUTF8(Element,Data,sizeof(Data)-1,Value);
    Data[sizeof(Data)-1] = 0;
    return EBML_StringSetValue(Element,Data);
}
#endif

err_t EBML_StringSetValue(ebml_string *Element,const char *Value)
{
    if (Element->Base.bValueIsSet && Element->Buffer)
        free((char*)Element->Buffer);
    Element->Buffer = strdup(Value);
    Element->Base.bValueIsSet = 1;
49
    Element->Base.DataSize = strlen(Element->Buffer);
50
    Element->Base.bNeedDataSizeUpdate = 0;
51 52 53
    return ERR_NONE;
}

54 55
void EBML_StringGet(ebml_string *Element,tchar_t *Out, size_t OutLen)
{
56 57 58 59 60 61 62
	if (!Element->Buffer)
	{
		if (OutLen)
			*Out = 0;
	}
	else
	{
63
#if defined(CONFIG_EBML_UNICODE)
64 65 66
		if (Node_IsPartOf(Element,EBML_UNISTRING_CLASS))
			Node_FromUTF8(Element,Out,OutLen,Element->Buffer);
		else
67
#endif
68 69
			Node_FromStr(Element,Out,OutLen,Element->Buffer);
	}
70 71
}

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 75 76 77 78 79 80 81 82 83
{
    err_t Result;
    char *Buffer;

    Element->Base.bValueIsSet = 0;

    if (Scope == SCOPE_NO_DATA)
        return ERR_NONE;

    if (Stream_Seek(Input,EBML_ElementPositionData((ebml_element*)Element),SEEK_SET)==INVALID_FILEPOS_T)
    {
84
        return ERR_READ;
85 86
    }

87
    Buffer = malloc((size_t)Element->Base.DataSize+1);
88 89 90
    if (!Buffer)
        return ERR_OUT_OF_MEMORY;

91
    Result = Stream_Read(Input,Buffer,(size_t)Element->Base.DataSize,NULL);
92 93 94
    if (Result != ERR_NONE)
        goto failed;

95
    Buffer[Element->Base.DataSize] = 0;
96 97 98 99 100 101 102 103 104 105 106
    Element->Buffer = Buffer;
    Element->Base.bValueIsSet = 1;
    return ERR_NONE;

failed:
    free(Buffer);
    Element->Buffer = NULL;
    return Result;
}

#if defined(CONFIG_EBML_WRITING)
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 112
    if (Rendered)
        *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 117
        if (!Padding)
            return ERR_OUT_OF_MEMORY;
118 119
        memset(Padding,0,Element->Base.DefaultSize - (int)Element->Base.DataSize);
        Err = Stream_Write(Output,Padding,Element->Base.DefaultSize - (int)Element->Base.DataSize,&Written);
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        if (Rendered)
            *Rendered += Written;
        free(Padding);
    }
    return Err;
}
#endif

#if 0
err_t EBML_AsciiStringRead(ebml_string *Element, stream *Input, tchar_t *Out, size_t OutLen)
{
    if (Node_IsPartOf(Element,EBML_STRING_CLASS))
        return ERR_INVALID_DATA;
    else
    {
        err_t Result = EBML_ElementReadData(Element, Input);
        if (Result != ERR_NONE)
            return Result;
        Node_FromStr(Element,Out,OutLen,Element->Buffer);
        return Result;
    }
}

err_t EBML_UnicodeStringRead(ebml_string *Element, stream *Input, tchar_t *Out, size_t OutLen)
{
    if (Node_IsPartOf(Element,EBML_UNISTRING_CLASS))
        return ERR_INVALID_DATA;
    else
    {
        err_t Result = EBML_ElementReadData(Element, Input);
        if (Result != ERR_NONE)
            return Result;
        Node_FromUTF8(Element,Out,OutLen,Element->Buffer);
        return Result;
    }
}
#endif

static void Delete(ebml_string *p)
{
    if (p->Buffer)
        free((char*)p->Buffer);
}

164
static filepos_t UpdateDataSize(ebml_string *Element, bool_t bWithDefault, bool_t bForceWithoutMandatory)
165
{
166 167
    if (EBML_ElementNeedsDataSizeUpdate(Element, bWithDefault))
        Element->Base.DataSize = strlen(Element->Buffer);
168

169
	return INHERITED(Element,ebml_element_vmt,EBML_STRING_CLASS)->UpdateDataSize(Element, bWithDefault, bForceWithoutMandatory);
170
}
171

172
static filepos_t UpdateDataSizeUni(ebml_string *Element, bool_t bWithDefault, bool_t bForceWithoutMandatory)
173 174 175
{
    if (EBML_ElementNeedsDataSizeUpdate(Element, bWithDefault))
        Element->Base.DataSize = strlen(Element->Buffer);
176

177
	return INHERITED(Element,ebml_element_vmt,EBML_UNISTRING_CLASS)->UpdateDataSize(Element, bWithDefault, bForceWithoutMandatory);
178 179 180 181 182 183 184
}

static bool_t IsDefaultValue(const ebml_string *Element)
{
    return Element->Base.Context->HasDefault && (!Element->Base.bValueIsSet || strcmp(Element->Buffer,(const char*)Element->Base.Context->DefaultValue)==0);
}

185
static void PostCreateString(ebml_element *Element, bool_t SetDefault)
186
{
187 188 189
    INHERITED(Element,ebml_element_vmt,EBML_STRING_CLASS)->PostCreate(Element, SetDefault);
    if (SetDefault && Element->Context->HasDefault)
        EBML_StringSetValue((ebml_string*)Element, (const char *)Element->Context->DefaultValue);
190 191
}

192
static void PostCreateUniString(ebml_element *Element, bool_t SetDefault)
193
{
194 195 196
    INHERITED(Element,ebml_element_vmt,EBML_UNISTRING_CLASS)->PostCreate(Element, SetDefault);
    if (SetDefault && Element->Context->HasDefault)
        EBML_StringSetValue((ebml_string*)Element, (const char *)Element->Context->DefaultValue);
197 198
}

199 200 201 202 203 204 205 206 207 208 209
static ebml_string *Copy(const ebml_string *Element, const void *Cookie)
{
    ebml_string *Result = (ebml_string*)EBML_ElementCreate(Element,Element->Base.Context,0,Cookie);
    if (Result)
    {
        Result->Buffer = strdup(Element->Buffer);
        Result->Base.bValueIsSet = Element->Base.bValueIsSet;
        Result->Base.DataSize = Element->Base.DataSize;
        Result->Base.ElementPosition = Element->Base.ElementPosition;
        Result->Base.SizeLength = Element->Base.SizeLength;
        Result->Base.SizePosition = Element->Base.SizePosition;
210
        Result->Base.bNeedDataSizeUpdate = Element->Base.bNeedDataSizeUpdate;
211 212 213 214
    }
    return Result;
}

215 216 217 218 219
META_START(EBMLString_Class,EBML_STRING_CLASS)
META_CLASS(SIZE,sizeof(ebml_string))
META_CLASS(DELETE,Delete)
META_VMT(TYPE_FUNC,ebml_element_vmt,ReadData,ReadData)
META_VMT(TYPE_FUNC,ebml_element_vmt,IsDefaultValue,IsDefaultValue)
220
META_VMT(TYPE_FUNC,ebml_element_vmt,UpdateDataSize,UpdateDataSize)
221 222 223 224
#if defined(CONFIG_EBML_WRITING)
META_VMT(TYPE_FUNC,ebml_element_vmt,RenderData,RenderData)
#endif
META_VMT(TYPE_FUNC,ebml_element_vmt,PostCreate,PostCreateString)
225
META_VMT(TYPE_FUNC,ebml_element_vmt,Copy,Copy)
226 227 228 229 230 231 232
META_END_CONTINUE(EBML_ELEMENT_CLASS)

META_START_CONTINUE(EBML_UNISTRING_CLASS)
META_CLASS(SIZE,sizeof(ebml_string))
META_CLASS(DELETE,Delete)
META_VMT(TYPE_FUNC,ebml_element_vmt,ReadData,ReadData)
META_VMT(TYPE_FUNC,ebml_element_vmt,IsDefaultValue,IsDefaultValue)
233
META_VMT(TYPE_FUNC,ebml_element_vmt,UpdateDataSize,UpdateDataSizeUni)
234 235 236 237
#if defined(CONFIG_EBML_WRITING)
META_VMT(TYPE_FUNC,ebml_element_vmt,RenderData,RenderData)
#endif
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)