EbmlWriter.c revision 1b362b15af34006e6a11974088a46d42b903418e
1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10#include "EbmlWriter.h"
11#include <stdlib.h>
12#include <wchar.h>
13#include <string.h>
14#include <limits.h>
15#if defined(_MSC_VER)
16#define LITERALU64(n) n
17#else
18#define LITERALU64(n) n##LLU
19#endif
20
21void Ebml_WriteLen(EbmlGlobal *glob, int64_t val)
22{
23    /* TODO check and make sure we are not > than 0x0100000000000000LLU */
24    unsigned char size = 8; /* size in bytes to output */
25
26    /* mask to compare for byte size */
27    int64_t minVal = 0xff;
28
29    for (size = 1; size < 8; size ++)
30    {
31        if (val < minVal)
32            break;
33
34        minVal = (minVal << 7);
35    }
36
37    val |= (((uint64_t)0x80) << ((size - 1) * 7));
38
39    Ebml_Serialize(glob, (void *) &val, sizeof(val), size);
40}
41
42void Ebml_WriteString(EbmlGlobal *glob, const char *str)
43{
44    const size_t size_ = strlen(str);
45    const uint64_t  size = size_;
46    Ebml_WriteLen(glob, size);
47    /* TODO: it's not clear from the spec whether the nul terminator
48     * should be serialized too.  For now we omit the null terminator.
49     */
50    Ebml_Write(glob, str, (unsigned long)size);
51}
52
53void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr)
54{
55    const size_t strlen = wcslen(wstr);
56
57    /* TODO: it's not clear from the spec whether the nul terminator
58     * should be serialized too.  For now we include it.
59     */
60    const uint64_t  size = strlen;
61
62    Ebml_WriteLen(glob, size);
63    Ebml_Write(glob, wstr, (unsigned long)size);
64}
65
66void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id)
67{
68    int len;
69
70    if (class_id >= 0x01000000)
71        len = 4;
72    else if (class_id >= 0x00010000)
73        len = 3;
74    else if (class_id >= 0x00000100)
75        len = 2;
76    else
77        len = 1;
78
79    Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
80}
81
82void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui)
83{
84    unsigned char sizeSerialized = 8 | 0x80;
85    Ebml_WriteID(glob, class_id);
86    Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
87    Ebml_Serialize(glob, &ui, sizeof(ui), 8);
88}
89
90void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui)
91{
92    unsigned char size = 8; /* size in bytes to output */
93    unsigned char sizeSerialized = 0;
94    unsigned long minVal;
95
96    Ebml_WriteID(glob, class_id);
97    minVal = 0x7fLU; /* mask to compare for byte size */
98
99    for (size = 1; size < 4; size ++)
100    {
101        if (ui < minVal)
102        {
103            break;
104        }
105
106        minVal <<= 7;
107    }
108
109    sizeSerialized = 0x80 | size;
110    Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
111    Ebml_Serialize(glob, &ui, sizeof(ui), size);
112}
113/* TODO: perhaps this is a poor name for this id serializer helper function */
114void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin)
115{
116    int size;
117    for (size=4; size > 1; size--)
118    {
119        if (bin & 0x000000ff << ((size-1) * 8))
120            break;
121    }
122    Ebml_WriteID(glob, class_id);
123    Ebml_WriteLen(glob, size);
124    Ebml_WriteID(glob, bin);
125}
126
127void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d)
128{
129    unsigned char len = 0x88;
130
131    Ebml_WriteID(glob, class_id);
132    Ebml_Serialize(glob, &len, sizeof(len), 1);
133    Ebml_Serialize(glob,  &d, sizeof(d), 8);
134}
135
136void Ebml_WriteSigned16(EbmlGlobal *glob, short val)
137{
138    signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
139    Ebml_Serialize(glob, &out, sizeof(out), 3);
140}
141
142void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s)
143{
144    Ebml_WriteID(glob, class_id);
145    Ebml_WriteString(glob, s);
146}
147
148void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s)
149{
150    Ebml_WriteID(glob,  class_id);
151    Ebml_WriteUTF8(glob,  s);
152}
153
154void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length)
155{
156    Ebml_WriteID(glob, class_id);
157    Ebml_WriteLen(glob, data_length);
158    Ebml_Write(glob,  data, data_length);
159}
160
161void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize)
162{
163    unsigned char tmp = 0;
164    unsigned long i = 0;
165
166    Ebml_WriteID(glob, 0xEC);
167    Ebml_WriteLen(glob, vSize);
168
169    for (i = 0; i < vSize; i++)
170    {
171        Ebml_Write(glob, &tmp, 1);
172    }
173}
174
175/* TODO Serialize Date */
176