winamp/Src/omBrowser/xmlServiceParser.cpp

331 lines
7.7 KiB
C++

#include "main.h"
#include "./xmlServiceParser.h"
#include "../xml/obj_xml.h"
#include "./service.h"
#include "./ifc_omservicehost.h"
#include "./ifc_omstoragehandler.h"
#include "./ifc_omstoragehandlerenum.h"
#include "./ifc_omstorageext.h"
#include <shlwapi.h>
#include <strsafe.h>
typedef void (CALLBACK *TAGCALLBACK)(XmlServiceParser* /*reader*/, OmService* /*editor*/, LPCWSTR /*value*/);
typedef struct __TAGRECORD
{
LPCWSTR name;
TAGCALLBACK callback;
} TAGRECORD;
static void CALLBACK ParserXml_ReadId(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
INT iVal;
if (StrToIntEx(value, STIF_SUPPORT_HEX, &iVal))
{
service->SetId(iVal);
}
}
static void CALLBACK ParserXml_ReadName(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetName(value, FALSE);
}
static void CALLBACK ParserXml_ReadUrl(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetUrl(value, FALSE);
}
static void CALLBACK ParserXml_ReadAuth(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
INT iVal;
if (StrToIntEx(value, STIF_SUPPORT_HEX, &iVal))
{
// service->SetAuth(iVal);
}
}
static void CALLBACK ParserXml_ReadIcon(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetIcon(value, FALSE);
}
static void CALLBACK ParserXml_ReadThumbnail(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetThumbnail(value, FALSE);
}
static void CALLBACK ParserXml_ReadScreenshot(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetScreenshot(value, FALSE);
}
static void CALLBACK ParserXml_ReadVersion(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
INT iVal;
if (StrToIntEx(value, STIF_SUPPORT_HEX, &iVal))
service->SetVersion(iVal);
}
static void CALLBACK ParserXml_ReadGeneration(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
INT iVal;
if (StrToIntEx(value, STIF_SUPPORT_HEX, &iVal))
{
service->SetGeneration(iVal);
}
}
static void CALLBACK ParserXml_ReadDescription(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetDescription(value, FALSE);
}
static void CALLBACK ParserXml_ReadAuthorFirst(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetAuthorFirst(value, FALSE);
}
static void CALLBACK ParserXml_ReadAuthorLast(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetAuthorLast(value, FALSE);
}
static void CALLBACK ParserXml_ReadPublished(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetPublished(value, FALSE);
}
static void CALLBACK ParserXml_ReadUpdated(XmlServiceParser *reader, OmService *service, LPCWSTR value)
{
service->SetUpdated(value, FALSE);
}
static const TAGRECORD szTagTable[] =
{
{ L"id", ParserXml_ReadId },
{ L"name", ParserXml_ReadName },
{ L"version", ParserXml_ReadVersion },
{ L"icon_url", ParserXml_ReadIcon },
{ L"entry_url", ParserXml_ReadUrl },
{ L"generation", ParserXml_ReadGeneration },
{ L"author_comments_long", ParserXml_ReadDescription },
{ L"author_firstname", ParserXml_ReadAuthorFirst},
{ L"author_lastname", ParserXml_ReadAuthorLast },
{ L"date_published", ParserXml_ReadPublished },
{ L"date_updated", ParserXml_ReadUpdated },
{ L"thumbnail", ParserXml_ReadThumbnail },
{ L"screenshot", ParserXml_ReadScreenshot },
};
XmlServiceParser::XmlServiceParser()
: checkList(NULL), checkSize(0), parser(NULL), service(NULL), result(E_UNEXPECTED)
{
}
XmlServiceParser::~XmlServiceParser()
{
Finish(NULL, NULL);
if (NULL != checkList)
free(checkList);
size_t index = handlerList.size();
while (index--)
handlerList[index]->Release();
}
HRESULT XmlServiceParser::RegisterHandlers(ifc_omstoragehandlerenum *handlerEnum)
{
if (E_PENDING == result)
return E_PENDING;
if (NULL != checkList)
{
free(checkList);
checkList = NULL;
checkSize = 0;
}
size_t index = handlerList.size();
while(index--) handlerList[index]->Release();
handlerList.clear();
if (NULL != handlerEnum)
{
ifc_omstoragehandler *handler;
handlerEnum->Reset();
while(S_OK == handlerEnum->Next(1, &handler, NULL))
{
handlerList.push_back(handler);
}
}
return S_OK;
}
HRESULT XmlServiceParser::Initialize(obj_xml *reader, LPCWSTR match, ifc_omservicehost *host)
{
result = E_UNEXPECTED;
if (NULL != parser) return E_UNEXPECTED;
if (NULL == reader) return E_INVALIDARG;
HRESULT hr;
WCHAR szBuffer[1024] = {0};
LPWSTR cursor = szBuffer;
size_t remaining = ARRAYSIZE(szBuffer);
if (NULL == checkList)
{
size_t checkCount = ARRAYSIZE(szTagTable) + handlerList.size();
checkSize = checkCount/8 + ((checkCount%8) ? 1 : 0);
checkList = (BYTE*)calloc(checkSize, sizeof(BYTE));
if (NULL != checkList)
ZeroMemory(checkList, checkSize);
}
hr = StringCchCopyEx(cursor, remaining, match, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
if (FAILED(hr)) return E_UNEXPECTED;
hr = StringCchCopyEx(cursor, remaining, ((cursor != szBuffer) ? L"\f*" : L"*"), &cursor, &remaining, STRSAFE_IGNORE_NULLS);
if (FAILED(hr)) return E_UNEXPECTED;
parser = reader;
parser->AddRef();
parser->xmlreader_registerCallback(szBuffer, this);
hr = OmService::CreateInstance(0, host, &service);
if (FAILED(hr)) return hr;
service->BeginUpdate();
result = E_PENDING;
return S_OK;
}
HRESULT XmlServiceParser::Finish(HRESULT *parserResult, ifc_omservice **ppService)
{
if (NULL == parser)
return E_UNEXPECTED;
if (E_PENDING == result)
result= S_OK;
buffer.Clear();
if (NULL != checkList)
ZeroMemory(checkList, checkSize);
parser->xmlreader_unregisterCallback(this);
parser->Release();
parser = NULL;
if (NULL != service && 0 == service->GetId())
{
if (SUCCEEDED(result))
result = E_UNEXPECTED;
service->Release();
service = NULL;
}
if (NULL != parserResult)
*parserResult = result;
if (NULL != ppService)
{
if (SUCCEEDED(result))
{
*ppService = service;
service->AddRef();
}
else
{
*ppService = NULL;
}
}
if (NULL != service)
{
service->SetModified(0, (UINT)-1);
service->EndUpdate();
service->Release();
service = NULL;
}
result = E_UNEXPECTED;
return S_OK;
}
HRESULT XmlServiceParser::GetActive()
{
return (E_PENDING == result) ? S_OK : S_FALSE;
}
void XmlServiceParser::OnStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
buffer.Clear();
}
void XmlServiceParser::OnEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
{
size_t i;
for (i = 0; i < ARRAYSIZE(szTagTable); i++)
{
if (NULL == checkList || 0 == (checkList[i/8] & (0x01 << (i%8))) && E_PENDING == result)
{
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, szTagTable[i].name, -1, xmltag, -1))
{
checkList[i/8] |= (0x01 << (i%8));
szTagTable[i].callback(this, service, buffer.Get());
return;
}
}
}
size_t handlerSize = handlerList.size();
size_t iCheck = ARRAYSIZE(szTagTable);
for (i = 0; i < handlerSize; i++, iCheck++)
{
if (NULL == checkList || 0 == (checkList[iCheck/8] & (0x01 << (iCheck%8))) && E_PENDING == result)
{
LPCWSTR pszKey;
if (SUCCEEDED(handlerList[i]->GetKey(&pszKey)) &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, pszKey, -1, xmltag, -1))
{
checkList[iCheck/8] |= (0x01 << (iCheck%8));
handlerList[i]->Invoke(service, xmltag, buffer.Get());
return;
}
}
}
}
void XmlServiceParser::OnCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
{
buffer.Append(value);
}
void XmlServiceParser::OnError(int linenum, int errcode, const wchar_t *errstr)
{
result = E_FAIL;
if (NULL != service)
{
service->Release();
service = NULL;
}
}
#define CBCLASS XmlServiceParser
START_DISPATCH;
VCB(ONSTARTELEMENT, OnStartElement)
VCB(ONENDELEMENT, OnEndElement)
VCB(ONCHARDATA, OnCharData)
VCB(ONERROR, OnError)
END_DISPATCH;
#undef CBCLASS