winamp/Src/plist/loader.cpp

169 lines
5.1 KiB
C++

//------------------------------------------------------------------------
//
// iTunes XML Library Reader
// Copyright (C) 2003-2011 Nullsoft, Inc.
//
//------------------------------------------------------------------------
#include "loader.h"
#include <windows.h>
#include <commdlg.h>
#include <bfc/string/stringdict.h>
#define ATTRIB_TRUE 256
#define ATTRIB_FALSE 257
//------------------------------------------------------------------------
// xml tags
//------------------------------------------------------------------------
BEGIN_STRINGDICTIONARY(_itunestypes)
SDI(L"key", PLISTDATA_KEY);
SDI(L"dict", PLISTDATA_DICT);
SDI(L"integer", PLISTDATA_INTEGER);
SDI(L"string", PLISTDATA_STRING);
SDI(L"date", PLISTDATA_DATE);
SDI(L"array", PLISTDATA_ARRAY);
SDI(L"data", PLISTDATA_RAW);
SDI(L"true", ATTRIB_TRUE);
SDI(L"false", ATTRIB_FALSE);
END_STRINGDICTIONARY(_itunestypes, itunestypes)
//------------------------------------------------------------------------
plistLoader::plistLoader() : plistKey(L"root")
{
m_context.push(this);
}
//------------------------------------------------------------------------
plistLoader::~plistLoader()
{
}
//------------------------------------------------------------------------
// element opens (or singleton), push new key/dictionary/array, handle value singletons (true/false), defer job to closing tag for other data types
//------------------------------------------------------------------------
void plistLoader::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params) {
m_cdata = 0;
int a = itunestypes.getId(xmltag);
switch (a) {
case PLISTDATA_KEY:
m_cdata = L"";
m_context.push(new plistKey());
m_dict.top()->addKey((plistKey *)m_context.top());
break;
case PLISTDATA_DICT:
{
m_dict.push(new plistDict());
plistData *contextTop = m_context.top();
contextTop->setData(static_cast<plistDict *>(m_dict.top()));
}
break;
case PLISTDATA_ARRAY:
{
plistArray *new_array = new plistArray;
plistData *contextTop = m_context.top();
contextTop->setData(new_array);
m_context.push(new_array);
m_dict.push(new_array);
break;
}
case PLISTDATA_STRING:
break;
case PLISTDATA_INTEGER:
break;
case PLISTDATA_DATE:
break;
case PLISTDATA_RAW:
break;
case PLISTDATA_REAL:
break;
case ATTRIB_TRUE: {
m_context.top()->setData(new plistBoolean(true));
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
case ATTRIB_FALSE: {
m_context.top()->setData(new plistBoolean(false));
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
}
}
//------------------------------------------------------------------------
// element closes, set data for last key/array, pop key/array/dictionary from stack
//------------------------------------------------------------------------
void plistLoader::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag) {
int a = itunestypes.getId(xmltag);
switch (a) {
case PLISTDATA_KEY:
ASSERT(m_context.top()->getType() == PLISTDATA_KEY);
((plistKey*)m_context.top())->setName(m_cdata);
break;
case PLISTDATA_DICT:
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
m_dict.pop();
break;
case PLISTDATA_ARRAY: {
/*if (m_context.top()->getType() == PLISTDATA_KEY)*/ m_context.pop();
//ASSERT(m_context.top()->getType() == PLISTDATA_ARRAY);
//plistArray *a = (plistArray *)m_context.top();
//m_context.pop();
//m_context.top()->setData(a);
m_dict.pop();
break;
}
case PLISTDATA_STRING: {
plistString *s = new plistString(m_cdata);
m_context.top()->setData(s);
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
case PLISTDATA_INTEGER: {
plistInteger *i = new plistInteger();
i->setString(m_cdata);
m_context.top()->setData(i);
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
case PLISTDATA_REAL: {
plistReal *r = new plistReal();
r->setString(m_cdata);
m_context.top()->setData(r);
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
case PLISTDATA_DATE: {
plistDate *d = new plistDate();
d->setString(m_cdata);
m_context.top()->setData(d);
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
case PLISTDATA_RAW: {
plistRaw *r = new plistRaw();
r->setString(m_cdata);
m_context.top()->setData(r);
if (m_context.top()->getType() == PLISTDATA_KEY) m_context.pop();
break;
}
}
m_cdata = 0;
}
//------------------------------------------------------------------------
// record c_data
//------------------------------------------------------------------------
void plistLoader::xmlReaderOnCharacterDataCallback(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *str) {
m_cdata += str;
}
#define CBCLASS plistLoader
START_DISPATCH;
VCB(ONSTARTELEMENT, xmlReaderOnStartElementCallback)
VCB(ONCHARDATA, xmlReaderOnCharacterDataCallback)
VCB(ONENDELEMENT, xmlReaderOnEndElementCallback)
END_DISPATCH;
#undef CBCLASS