winamp/Src/Plugins/Input/in_flv/AMFObject.cpp
2024-09-24 14:54:57 +02:00

320 lines
6.5 KiB
C++

#include "AMFObject.h"
#include <strsafe.h>
void AMFMixedArray::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
AMFTypeList::iterator itr;
StringCchCopyEx(str, len, L"Mixed Array [\n", &str, &len, 0);
for (itr=array.begin();itr!=array.end();itr++)
{
for (int i=0;i<spaces;i++)
StringCchCopyEx(str, len, L" ", &str, &len,0);
if (itr->first.c_str() != 0 && itr->first.c_str()[0])
StringCchPrintfEx(str, len, &str, &len, 0, L"%s: ", itr->first.c_str());
if (itr->second)
itr->second->DebugPrint(spaces+1, str, len);
else
StringCchCopyEx(str, len, L"(null)\n", &str, &len, 0);
}
StringCchCopyEx(str, len, L"]\n", &str, &len, 0);
}
size_t AMFMixedArray::Read(uint8_t *data, size_t size)
{
size_t read = 0;
uint32_t maxIndex = FLV::Read32(data);
// TODO? array.reserve(maxIndex);
data += 4;
size -= 4;
read += 4;
while (size)
{
AMFString amfString;
size_t skip = amfString.Read(data, size);
data += skip;
size -= skip;
read += skip;
uint8_t type = *data;
data++;
size--;
read++;
AMFType *obj = MakeObject(type);
if (obj)
{
obj->type = type;
size_t skip = obj->Read(data, size);
data += skip;
size -= skip;
read += skip;
array[amfString.str] = obj;
}
else
break;
if (type == TYPE_TERMINATOR)
break;
}
return read;
}
AMFMixedArray::~AMFMixedArray()
{
for (AMFTypeList::iterator itr=array.begin();itr!=array.end();itr++)
{
delete itr->second;
}
}
void AMFObj::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchCopyEx(str, len, L"Object (TODO)\n", &str, &len, 0);
}
size_t AMFObj::Read(uint8_t *data, size_t size)
{
size_t read = 0;
while (size)
{
AMFString amfString;
size_t skip = amfString.Read(data, size);
data += skip;
size -= skip;
read += skip;
uint8_t type = *data;
data++;
size--;
read++;
AMFType *obj = MakeObject(type);
if (obj)
{
obj->type = type;
size_t skip = obj->Read(data, size);
data += skip;
size -= skip;
read += skip;
}
else
return false;
if (type == TYPE_TERMINATOR)
break;
}
return read;
}
void AMFArray::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchCopyEx(str, len, L"Array [\n", &str, &len, 0);
for (size_t i=0;i!=array.size();i++)
{
for (int s=0;s<spaces;s++)
StringCchCopyEx(str, len, L" ", &str, &len,0);
StringCchPrintfEx(str, len, &str, &len, 0, L"%u: ", i);
array[i]->DebugPrint(spaces+1, str, len);
}
StringCchCopyEx(str, len, L"]\n", &str, &len, 0);
}
size_t AMFArray::Read(uint8_t *data, size_t size)
{
size_t read = 0;
uint32_t arrayLength = FLV::Read32(data);
array.reserve(arrayLength);
data += 4;
read += 4;
size -= 4;
for (uint32_t i=0;i!=arrayLength;i++)
{
uint8_t type = *data;
data++;
read++;
size--;
AMFType *obj = MakeObject(type);
size_t skip = obj->Read(data, size);
//array[i]=obj;
array.push_back(obj);
data += skip;
read += skip;
size -= skip;
}
return read;
}
AMFArray::~AMFArray()
{
for (size_t i=0;i!=array.size();i++)
{
delete array[i];
}
}
/* --- String --- */
AMFString::AMFString() : str(0)
{}
AMFString::~AMFString()
{
free(str);
}
void AMFString::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchPrintfEx(str, len, &str, &len, 0, L"%s\n", this->str);
}
size_t AMFString::Read(uint8_t *data, size_t size)
{
if (size < 2)
return 0;
unsigned __int16 strlength = FLV::Read16(data);
data += 2;
size -= 2;
if (strlength > size)
return 0;
char *utf8string = (char *)calloc(strlength, sizeof(char));
memcpy(utf8string, data, strlength);
int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, 0, 0);
str = (wchar_t *)calloc(wideLen + 2, sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, str, wideLen);
str[wideLen] = 0;
free(utf8string);
return strlength + 2;
}
/* --- Long String --- */
AMFLongString::AMFLongString() : str(0)
{}
AMFLongString::~AMFLongString()
{
free(str);
}
void AMFLongString::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchPrintfEx(str, len, &str, &len, 0, L"%s\n", this->str);
}
size_t AMFLongString::Read(uint8_t *data, size_t size)
{
if (size < 4)
return 0;
uint32_t strlength = FLV::Read32(data);
data += 4;
size -= 4;
if (strlength > size)
return 0;
char *utf8string = (char *)calloc(strlength, sizeof(char));
memcpy(utf8string, data, strlength);
int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, 0, 0);
str = (wchar_t *)calloc(wideLen + 2, sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, utf8string, strlength, str, wideLen);
str[wideLen] = 0;
free(utf8string);
return strlength + 4;
}
/* --- Double --- */
void AMFDouble::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchPrintfEx(str, len, &str, &len, 0, L"%f\n", val);
}
/* --- Boolean --- */
void AMFBoolean::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchPrintfEx(str, len, &str, &len, 0, L"%s\n", boolean?L"true":L"false");
}
/* --- Time --- */
static size_t MakeDateString(__time64_t convertTime, wchar_t *dest, size_t destlen)
{
SYSTEMTIME sysTime;
tm *newtime = _localtime64(&convertTime);
dest[0] = 0; // so we can bail out easily
if (newtime)
{
sysTime.wYear = (WORD)(newtime->tm_year + 1900);
sysTime.wMonth = (WORD)(newtime->tm_mon + 1);
sysTime.wDayOfWeek = (WORD)newtime->tm_wday;
sysTime.wDay = (WORD)newtime->tm_mday;
sysTime.wHour = (WORD)newtime->tm_hour;
sysTime.wMinute = (WORD)newtime->tm_min;
sysTime.wSecond = (WORD)newtime->tm_sec;
sysTime.wMilliseconds = 0;
int charsWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &sysTime, NULL, dest, (int)destlen);
if (charsWritten)
{
size_t dateSize = charsWritten-1;
dest += dateSize;
destlen -= dateSize;
if (destlen)
{
*dest++ = L' ';
destlen--;
dateSize++;
}
int charsWritten2 = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &sysTime, NULL, dest, (int)destlen);
if (charsWritten2)
{
dateSize+=(charsWritten2-1);
}
return dateSize;
}
}
return 1;
}
void AMFTime::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
size_t written = MakeDateString((__time64_t)val, str, len);
str+=written;
len-=written;
if (len>=2)
{
str[0]='\n';
str[1]=0;
len--;
str++;
}
}
/* --- Terminator --- */
void AMFTerminator::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchCopyEx(str, len, L"array terminator\n", &str, &len, 0);
}
/* --- Reference --- */
void AMFReference::DebugPrint(int spaces, wchar_t *&str, size_t &len)
{
StringCchPrintfEx(str, len, &str, &len, 0, L"%u\n", val);
}