JD2022-TU1/main/extern/libwebm/custom/mkvparser/ebmlreadhelpers.cpp

347 lines
5.7 KiB
C++

#include "ebmlreadhelpers.hpp"
#include "imkvreader.hpp"
#include "memory.hpp"
#include <stddef.h>
#include <assert.h>
#include <limits.h>
namespace mkvparser
{
long long ReadUInt(IMkvReader* pReader, long long pos, long& len)
{
assert(pReader);
assert(pos >= 0);
int status;
//#ifdef _DEBUG
// long long total, available;
// status = pReader->Length(&total, &available);
// assert(status >= 0);
// assert((total < 0) || (available <= total));
// assert(pos < available);
// assert((available - pos) >= 1); //assume here max u-int len is 8
//#endif
len = 1;
unsigned char b;
status = pReader->Read(pos, 1, &b);
if (status < 0) //error or underflow
return status;
if (status > 0) //interpreted as "underflow"
return E_BUFFER_NOT_FULL;
if (b == 0) //we can't handle u-int values larger than 8 bytes
return E_FILE_FORMAT_INVALID;
unsigned char m = 0x80;
while (!(b & m))
{
m >>= 1;
++len;
}
//#ifdef _DEBUG
// assert((available - pos) >= len);
//#endif
long long result = b & (~m);
++pos;
for (int i = 1; i < len; ++i)
{
status = pReader->Read(pos, 1, &b);
if (status < 0)
{
len = 1;
return status;
}
if (status > 0)
{
len = 1;
return E_BUFFER_NOT_FULL;
}
result <<= 8;
result |= b;
++pos;
}
return result;
}
long long GetUIntLength(
IMkvReader* pReader,
long long pos,
long& len)
{
assert(pReader);
assert(pos >= 0);
long long total, available;
int status = pReader->Length(&total, &available);
assert(status >= 0);
assert((total < 0) || (available <= total));
len = 1;
if (pos >= available)
return pos; //too few bytes available
unsigned char b;
status = pReader->Read(pos, 1, &b);
if (status < 0)
return status;
assert(status == 0);
if (b == 0) //we can't handle u-int values larger than 8 bytes
return E_FILE_FORMAT_INVALID;
unsigned char m = 0x80;
while (!(b & m))
{
m >>= 1;
++len;
}
return 0; //success
}
long long UnserializeUInt(
IMkvReader* pReader,
long long pos,
long long size)
{
assert(pReader);
assert(pos >= 0);
if ((size <= 0) || (size > 8))
return E_FILE_FORMAT_INVALID;
long long result = 0;
for (long long i = 0; i < size; ++i)
{
unsigned char b;
const long status = pReader->Read(pos, 1, &b);
if (status < 0)
return status;
result <<= 8;
result |= b;
++pos;
}
return result;
}
long UnserializeFloat(
IMkvReader* pReader,
long long pos,
long long size_,
double& result)
{
assert(pReader);
assert(pos >= 0);
if ((size_ != 4) && (size_ != 8))
return E_FILE_FORMAT_INVALID;
const long size = static_cast<long>(size_);
unsigned char buf[8];
const int status = pReader->Read(pos, size, buf);
if (status < 0) //error
return status;
if (size == 4)
{
union
{
float f;
unsigned long ff;
};
ff = 0;
for (int i = 0;;)
{
ff |= buf[i];
if (++i >= 4)
break;
ff <<= 8;
}
result = f;
}
else
{
assert(size == 8);
union
{
double d;
unsigned long long dd;
};
dd = 0;
for (int i = 0;;)
{
dd |= buf[i];
if (++i >= 8)
break;
dd <<= 8;
}
result = d;
}
return 0;
}
long UnserializeInt(
IMkvReader* pReader,
long long pos,
long size,
long long& result)
{
assert(pReader);
assert(pos >= 0);
assert(size > 0);
assert(size <= 8);
{
signed char b;
const long status = pReader->Read(pos, 1, (unsigned char*)&b);
if (status < 0)
return status;
result = b;
++pos;
}
for (long i = 1; i < size; ++i)
{
unsigned char b;
const long status = pReader->Read(pos, 1, &b);
if (status < 0)
return status;
result <<= 8;
result |= b;
++pos;
}
return 0; //success
}
long UnserializeString(
IMkvReader* pReader,
long long pos,
long long size_,
char*& str)
{
mem::Free(str);
str = NULL;
if (size_ >= LONG_MAX) //we need (size+1) chars
return E_FILE_FORMAT_INVALID;
const long size = static_cast<long>(size_);
str = static_cast<char*>(mem::Allocate(size+1));
if (str == NULL)
return -1;
unsigned char* const buf = reinterpret_cast<unsigned char*>(str);
const long status = pReader->Read(pos, size, buf);
if (status)
{
mem::Free(str);
str = NULL;
return status;
}
str[size] = '\0';
return 0; //success
}
long ParseElementHeader(
IMkvReader* pReader,
long long& pos,
long long stop,
long long& id,
long long& size)
{
if ((stop >= 0) && (pos >= stop))
return E_FILE_FORMAT_INVALID;
long len;
id = ReadUInt(pReader, pos, len);
if (id < 0)
return E_FILE_FORMAT_INVALID;
pos += len; //consume id
if ((stop >= 0) && (pos >= stop))
return E_FILE_FORMAT_INVALID;
size = ReadUInt(pReader, pos, len);
if (size < 0)
return E_FILE_FORMAT_INVALID;
pos += len; //consume length of size
//pos now designates payload
if ((stop >= 0) && ((pos + size) > stop))
return E_FILE_FORMAT_INVALID;
return 0; //success
}
} // namespace mkvparser