diff options
Diffstat (limited to 'Src/plist')
-rw-r--r-- | Src/plist/loader.cpp | 169 | ||||
-rw-r--r-- | Src/plist/loader.h | 36 | ||||
-rw-r--r-- | Src/plist/plist.sln | 30 | ||||
-rw-r--r-- | Src/plist/plist.vcxproj | 217 | ||||
-rw-r--r-- | Src/plist/plist.vcxproj.filters | 30 | ||||
-rw-r--r-- | Src/plist/types.cpp | 240 | ||||
-rw-r--r-- | Src/plist/types.h | 262 |
7 files changed, 984 insertions, 0 deletions
diff --git a/Src/plist/loader.cpp b/Src/plist/loader.cpp new file mode 100644 index 00000000..c3675593 --- /dev/null +++ b/Src/plist/loader.cpp @@ -0,0 +1,169 @@ +//------------------------------------------------------------------------ +// +// 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
\ No newline at end of file diff --git a/Src/plist/loader.h b/Src/plist/loader.h new file mode 100644 index 00000000..195d11b3 --- /dev/null +++ b/Src/plist/loader.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------ +// +// iTunes XML Library Reader +// Copyright (C) 2003-2012 Nullsoft, Inc. +// +//------------------------------------------------------------------------ + +#ifndef NULLSOFT_PLIST_LOADER_H +#define NULLSOFT_PLIST_LOADER_H + +#include "types.h" +#include "../xml/ifc_xmlreadercallback.h" +#include <bfc/string/stringw.h> +#include <bfc/stack.h> + +//------------------------------------------------------------------------ +class plistLoader : public ifc_xmlreadercallback, public plistKey { +public: + plistLoader(); + virtual ~plistLoader(); + + virtual void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params); + virtual void xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag); + virtual void xmlReaderOnCharacterDataCallback(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *str); +private: + Stack<plistData *> m_context; // either a key or an array, this is where data gets inserted next + Stack<plistKeyholder *> m_dict; + StringW m_cdata; + +protected: + RECVS_DISPATCH; +}; + +#endif + +//------------------------------------------------------------------------
\ No newline at end of file diff --git a/Src/plist/plist.sln b/Src/plist/plist.sln new file mode 100644 index 00000000..e9c7ec5f --- /dev/null +++ b/Src/plist/plist.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plist", "plist.vcxproj", "{5ED1729B-EA41-4163-9506-741A8B76F625}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|Win32.ActiveCfg = Debug|Win32 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|Win32.Build.0 = Debug|Win32 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|x64.ActiveCfg = Debug|x64 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|x64.Build.0 = Debug|x64 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Release|Win32.ActiveCfg = Release|Win32 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Release|Win32.Build.0 = Release|Win32 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Release|x64.ActiveCfg = Release|x64 + {5ED1729B-EA41-4163-9506-741A8B76F625}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8A265E7E-ACA5-46A3-B174-2A25F526A06D} + EndGlobalSection +EndGlobal diff --git a/Src/plist/plist.vcxproj b/Src/plist/plist.vcxproj new file mode 100644 index 00000000..44a2c278 --- /dev/null +++ b/Src/plist/plist.vcxproj @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{5ED1729B-EA41-4163-9506-741A8B76F625}</ProjectGuid> + <RootNamespace>plist</RootNamespace> + <Keyword>Win32Proj</Keyword> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Label="Vcpkg"> + <VcpkgEnableManifest>false</VcpkgEnableManifest> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>MinSpace</Optimization> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <Optimization>MinSpace</Optimization> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="loader.cpp" /> + <ClCompile Include="types.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="loader.h" /> + <ClInclude Include="types.h" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Wasabi\Wasabi.vcxproj"> + <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/Src/plist/plist.vcxproj.filters b/Src/plist/plist.vcxproj.filters new file mode 100644 index 00000000..934be6b2 --- /dev/null +++ b/Src/plist/plist.vcxproj.filters @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="loader.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="types.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="loader.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="types.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{cb593512-db76-4543-81a4-64da0d31f4ef}</UniqueIdentifier> + </Filter> + <Filter Include="Ressource Files"> + <UniqueIdentifier>{3d920b5c-c6fc-4524-b042-2848c3f5193c}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{b3a77050-99be-40d0-bb37-4b05194da732}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Src/plist/types.cpp b/Src/plist/types.cpp new file mode 100644 index 00000000..348359c2 --- /dev/null +++ b/Src/plist/types.cpp @@ -0,0 +1,240 @@ +//------------------------------------------------------------------------ +// +// iTunes XML Library Data Structures +// Copyright (C) 2003-2011 Nullsoft, Inc. +// +//------------------------------------------------------------------------ + +#include "types.h" +#include <bfc/util/base64.h> +#include <stdint.h> + +//------------------------------------------------------------------------ +void plistData::setString(const wchar_t *str) { + plistString string(str); + setData(&string); +} + +//------------------------------------------------------------------------ +// raw data +//------------------------------------------------------------------------ +void plistRaw::setData(plistData *d) { + while (d && d->getType() == PLISTDATA_KEY) d = ((plistKey*)d)->getData(); + if (!d) return; + switch (d->getType()) { + case PLISTDATA_RAW: { + int size; + void *m = ((plistRaw*)d)->getMem(&size); + setMem(m, size); + break; + } + case PLISTDATA_INTEGER: { + int v = (int)((plistInteger *)d)->getValue(); + setMem(&v, sizeof(v)); + break; + } + case PLISTDATA_REAL: { + double v = ((plistReal *)d)->getValue(); + setMem(&v, sizeof(v)); + break; + } + case PLISTDATA_DATE: { + time_t v = ((plistDate *)d)->getDate(); + setMem(&v, sizeof(v)); + break; + } + case PLISTDATA_STRING: { + const wchar_t *s = ((plistString *)d)->getString(); + MemBlock<wchar_t> t64; + size_t len = wcslen(s); + t64.setSize((int)len); + t64.setMemory(s, (int)len); + MemBlock<char> data; + Base64::decode(t64, data); + setMem(data, data.getSize()); + break; + } + case PLISTDATA_BOOLEAN: + { + int8_t b = !!((plistBoolean *)d)->getValue(); + setMem(&b, 1); + } + break; + case PLISTDATA_ARRAY: { + //OutputDebugString(L"Unsupported call to setData() with an array as a parameter\n"); + break; + } + } +} + +//------------------------------------------------------------------------ +const wchar_t *plistRaw::getString() const { + MemBlock<wchar_t> t64; + Base64::encode(mem, t64, 72); + encoded.ncpy(t64.getMemory(), t64.getSize()); + return encoded; +} + +//------------------------------------------------------------------------ +// integer +//------------------------------------------------------------------------ +void plistInteger::setData(plistData *d) { + while (d && d->getType() == PLISTDATA_KEY) d = ((plistKey*)d)->getData(); + if (!d) return; + switch (d->getType()) { + case PLISTDATA_RAW: { + int size; + void *m = ((plistRaw*)d)->getMem(&size); + switch(size) + { + case 1: + setValue(*((int8_t *)m)); + break; + case 2: + setValue(*((int16_t *)m)); + break; + case 4: + setValue(*((int32_t *)m)); + break; + case 8: + setValue(*((int64_t *)m)); + break; + } + break; + } + case PLISTDATA_BOOLEAN: + { + int64_t b = !!((plistBoolean *)d)->getValue(); + setValue(b); + } + break; + case PLISTDATA_INTEGER: { + setValue(((plistInteger *)d)->getValue()); + break; + } + case PLISTDATA_REAL: { + setValue((int64_t)((plistReal *)d)->getValue()); + break; + } + case PLISTDATA_DATE: { + setValue(((plistDate *)d)->getDate()); + break; + } + case PLISTDATA_STRING: { + const wchar_t *s = ((plistString *)d)->getString(); +#ifdef _WIN32 + setValue(_wtoi64(s)); +#else + setValue(wcstoll(s, 0, 10)); +#endif + break; + } + case PLISTDATA_ARRAY: { + //OutputDebugString(L"Unsupported conversion from array to int\n"); + break; + } + } +} + +//------------------------------------------------------------------------ +// string +//------------------------------------------------------------------------ +void plistString::setData(plistData *d) { + while (d && d->getType() == PLISTDATA_KEY) d = ((plistKey*)d)->getData(); + if (!d) return; + setString(d->getString()); +} + +//------------------------------------------------------------------------ +// date +//------------------------------------------------------------------------ +void plistDate::setData(plistData *d) { + while (d && d->getType() == PLISTDATA_KEY) d = ((plistKey*)d)->getData(); + if (!d) return; + switch (d->getType()) { + case PLISTDATA_RAW: { + int size; + void *m = ((plistRaw*)d)->getMem(&size); + if (size >= 4) + setDate(*(time_t*)m); // assume we have a time_t* + break; + } + case PLISTDATA_INTEGER: { + setDate((time_t)((plistInteger *)d)->getValue()); + break; + } + case PLISTDATA_DATE: { + setDate(((plistDate *)d)->getDate()); + break; + } + case PLISTDATA_REAL: { + setDate((int)((plistReal *)d)->getValue()); + break; + } + case PLISTDATA_STRING: { + setString(d->getString()); + break; + } + case PLISTDATA_ARRAY: { + OutputDebugString(L"Unsupported conversion from array to date\n"); + break; + } + } +} +void plistDate::setString(const wchar_t *_str) +{ + if (wcslen(_str) == 20) // naive (but safe) parser + { + tm import_time= {0,}; + import_time.tm_year = _wtoi(&_str[0])-1900; + import_time.tm_mon = _wtoi(&_str[5])-1; + import_time.tm_mday = _wtoi(&_str[8]); + import_time.tm_hour = _wtoi(&_str[11]); + import_time.tm_min = _wtoi(&_str[14]); + import_time.tm_sec = _wtoi(&_str[17]); + + when=_mkgmtime(&import_time); + } +} +//------------------------------------------------------------------------ +// real +//------------------------------------------------------------------------ +void plistReal::setData(plistData *d) { + while (d && d->getType() == PLISTDATA_KEY) d = ((plistKey*)d)->getData(); + if (!d) return; + switch (d->getType()) { + case PLISTDATA_RAW: { + int size; + void *m = ((plistRaw*)d)->getMem(&size); + if (size >= 8) + setValue(*((double *)m)); + break; + } + case PLISTDATA_INTEGER: { + setValue((double)((plistInteger *)d)->getValue()); + break; + } + case PLISTDATA_REAL: { + setValue(((plistReal *)d)->getValue()); + break; + } + case PLISTDATA_DATE: { + setValue((double)(((plistDate *)d)->getDate())); + break; + } + case PLISTDATA_STRING: { + const wchar_t *s = ((plistString *)d)->getString(); + setValue(WTOF(s)); + break; + } + case PLISTDATA_ARRAY: { + //OutputDebugString(L"Unsupported conversion from array to real\n"); + break; + } + } +} + +void plistBoolean::setData(plistData *d) +{ + // TODO: implement. but how necessary is this really? +}
\ No newline at end of file diff --git a/Src/plist/types.h b/Src/plist/types.h new file mode 100644 index 00000000..bc96d9ed --- /dev/null +++ b/Src/plist/types.h @@ -0,0 +1,262 @@ +//------------------------------------------------------------------------ +// +// Apple plist XML Library Data Structures +// Copyright (C) 2003 Nullsoft, Inc. +// +//------------------------------------------------------------------------ + +#ifndef NULLSOFT_PLIST_TYPES_H +#define NULLSOFT_PLIST_TYPES_H + +#include <bfc/memblock.h> +#include <time.h> +#include <bfc/string/bfcstring.h> +#include <bfc/string/stringw.h> +#include <bfc/ptrlist.h> + +//------------------------------------------------------------------------ +// Base type class +//------------------------------------------------------------------------ + +enum { + PLISTDATA_KEY = 0, + PLISTDATA_DICT, + PLISTDATA_INTEGER, + PLISTDATA_STRING, + PLISTDATA_DATE, + PLISTDATA_ARRAY, + PLISTDATA_REAL, + PLISTDATA_RAW, + PLISTDATA_BOOLEAN, +}; + + +class plistData +{ +public: + plistData(int _type) : type(_type) {} + plistData() : type(-1) {} + virtual ~plistData() {} + virtual int getType() const { return type; } + virtual void setType(int _type) { type = _type; } + virtual void setData(plistData *d)=0; + virtual const wchar_t *getString() const =0; + virtual const wchar_t *getTypeString() const =0; + virtual void setString(const wchar_t *str); +private: + int type; +}; + +//------------------------------------------------------------------------ +// A key is a string attached to another piece of data +//------------------------------------------------------------------------ +class plistKey : public plistData +{ +public: + plistKey() : name(L""), data(NULL), plistData(PLISTDATA_KEY) {} + plistKey(const wchar_t *_name, plistData *_data=NULL) : name(_name), data(_data), plistData(PLISTDATA_KEY) {} + virtual ~plistKey() { delete data; } + const wchar_t *getName() const { return name; } + void setName(const wchar_t *_name) { name = _name; } + plistData *getData() const { return data; } + virtual void setData(plistData *d) { data = d; } + virtual const wchar_t *getString() const { return getName(); } + virtual const wchar_t *getTypeString() const { return L"key"; } +private: + StringW name; + plistData *data; +}; + + +class plistKeyholder +{ +public: + virtual int addKey(plistKey *key) = 0; +}; +//------------------------------------------------------------------------ +// A dictionary contains a list of keys +//------------------------------------------------------------------------ +class plistDict : public plistData, public plistKeyholder +{ +public: + plistDict() : plistData(PLISTDATA_DICT) {} + virtual ~plistDict() { keys.deleteAll(); } + int getNumKeys() const { return keys.getNumItems(); } + plistKey *enumKey(int n) const { return keys.enumItem(n); } + int addKey(plistKey *key) { if (!keys.haveItem(key)) keys.addItem(key); return keys.getNumItems(); } + virtual void setData(plistData *d) { if (d->getType() != PLISTDATA_KEY) return; keys.addItem((plistKey*)d); } + int delKey(const wchar_t *name, int dodelete=1) { + foreach(keys) + if (WCSCASEEQLSAFE(name, keys.getfor()->getName())) { + if (dodelete) delete keys.getfor(); + keys.removeByPos(foreach_index); + break; + } + endfor; + return keys.getNumItems(); + } + plistKey *getKey(const wchar_t *name) const { + foreach(keys) + if (WCSCASEEQLSAFE(name, keys.getfor()->getName())) { + return keys.getfor(); + } + endfor; + return NULL; + } + virtual const wchar_t *getString() const { return L""; } + virtual const wchar_t *getTypeString() const { return L"dict"; } +private: + PtrList<plistKey> keys; +}; + +//------------------------------------------------------------------------ +// An array contains a number of data entries +//------------------------------------------------------------------------ +class plistArray : public plistData, public plistKeyholder +{ +public: + plistArray() : plistData(PLISTDATA_ARRAY) {} + virtual ~plistArray() { items.deleteAll(); } + int getNumItems() const { return items.getNumItems(); } + plistData *enumItem(int n) const { return items.enumItem(n); } + virtual void setData(plistData *d) { items.addItem(d); } + int addKey(plistKey *key) { items.addItem(key); return items.getNumItems(); } + virtual const wchar_t *getString() const { return L"(array)"; } + virtual const wchar_t *getTypeString() const { return L"array"; } +private: + PtrList<plistData> items; +}; + +//------------------------------------------------------------------------ +// Raw data +//------------------------------------------------------------------------ +class plistRaw : public plistData { +public: + plistRaw() : plistData(PLISTDATA_RAW) {} + virtual ~plistRaw() {} + virtual void *getMem(int *size) const { if (size) *size = mem.getSize(); return mem.getMemory(); } + virtual void setMem(void *m, int size) { mem.setSize(size); mem.setMemory((char *)m, size, 0); } + virtual void setData(plistData *d); + virtual const wchar_t *getString() const ; + virtual const wchar_t *getTypeString() const { return L"data"; } +private: + mutable MemBlock<char> mem; + mutable StringW encoded; +}; + +//------------------------------------------------------------------------ +// Int +//------------------------------------------------------------------------ +class plistInteger : public plistData { +public: + plistInteger(int64_t _value) : value(_value), plistData(PLISTDATA_INTEGER) {} + plistInteger() : value(0), plistData(PLISTDATA_INTEGER) {} + virtual ~plistInteger() {} + + virtual int64_t getValue() const { return value; } + virtual void setValue(int64_t _value) { value = _value; } + + virtual void setData(plistData *d); + + virtual const wchar_t *getString() const + { + static wchar_t s[64]; +#ifdef _MSC_VER + return _i64tow(getValue(), s, 10); +#elif defined(__GCC__) + sprintf(s, L"%lld", getValue()); + return s; +#else +#error define me! +#endif + } + virtual const wchar_t *getTypeString() const { return L"integer"; } +private: + int64_t value; +}; + +class plistBoolean : public plistData +{ +public: + plistBoolean(bool _value) : value(_value), plistData(PLISTDATA_BOOLEAN) {} + plistBoolean() : value(0), plistData(PLISTDATA_BOOLEAN) {} + virtual ~plistBoolean() {} + + virtual bool getValue() const { return value; } + virtual void setValue(bool _value) { value = _value; } + virtual void setData(plistData *d); + + virtual const wchar_t *getString() const + { + if (value) + return L"true"; + else + return L"false"; + } + virtual const wchar_t *getTypeString() const { return L"boolean"; } +private: + bool value; +}; + +//------------------------------------------------------------------------ +// String +//------------------------------------------------------------------------ +class plistString : public plistData { +public: + plistString(const wchar_t *_str) : str(_str), plistData(PLISTDATA_STRING) {} + plistString() : str(L""), plistData(PLISTDATA_STRING) {} + virtual ~plistString() {} + virtual const wchar_t *getString() const { return str; } + virtual void setString(const wchar_t *_str) { str = _str; } + virtual void setData(plistData *d); + virtual const wchar_t *getTypeString() const { return L"string"; } +private: + StringW str; +}; + +//------------------------------------------------------------------------ +// Real +//------------------------------------------------------------------------ +class plistReal : public plistData { +public: + plistReal(int _value) : value(_value), plistData(PLISTDATA_REAL) {} + plistReal() : value(0), plistData(PLISTDATA_REAL) {} + virtual ~plistReal() {} + virtual double getValue() const { return value; } + virtual void setValue(double _value) { value = _value; } + virtual void setData(plistData *d); + virtual const wchar_t *getString() const { static StringW s; s.printf(L"%f", getValue()); return s; } + virtual const wchar_t *getTypeString() const { return L"real"; } +private: + double value; +}; + +//------------------------------------------------------------------------ +// Date/Time +//------------------------------------------------------------------------ +class plistDate : public plistData { +public: + plistDate(time_t _when) : when(_when), plistData(PLISTDATA_DATE) {} + plistDate() : when(0), plistData(PLISTDATA_DATE) {} + virtual ~plistDate() {} + virtual time_t getDate() const { return when; } + virtual void setDate(time_t _when) { when = _when; } + virtual void setData(plistData *d); + virtual const wchar_t *getString() const { + struct tm *t = gmtime(&when); + if (t) { + static wchar_t time_format[256] = {0}; + wcsftime(time_format, 256, L"%Y-%m-%dT%H:%M:%SZ", t); + return time_format; + } + return L""; + } + virtual void setString(const wchar_t *_str); + virtual const wchar_t *getTypeString() const { return L"date"; } +private: + time_t when; +}; + +#endif + +//------------------------------------------------------------------------
\ No newline at end of file |