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