📄 hxpluginarchive.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxtypes.h"
#include "hxcom.h"
#include "hxccf.h" // IHXCommonClassFactory
#include "ihxpckts.h" // IHXBuffer
#include "hlxclib/fcntl.h"
#include "chxdataf.h" // CHXDataFile
#include "debug.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#include "hxpluginarchive.h"
//
// special chars; these need escaping if in value text
//
const char TERM_CHAR = ';'; // denotes end of value for most objects
const char ESC_CHAR = '\\'; // escape char
HXPluginArchiveReader::HXPluginArchiveReader()
: m_pFile(0)
, m_idxFile(0)
, m_pFactory(0)
{
}
HXPluginArchiveReader::~HXPluginArchiveReader()
{
HX_DELETE(m_pFile);
HX_RELEASE(m_pFactory);
}
//
// Open
//
HX_RESULT HXPluginArchiveReader::Open(IUnknown* pContext, const char* pszFile)
{
DPRINTF(D_INFO, ("HXPluginArchiveReader::Open(): file = '%s'\n", pszFile));
HX_RESULT hr = HXR_FAIL;
HX_DELETE(m_pFile);
pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_pFactory);
m_pFile = CHXDataFile::Construct();
if (m_pFile)
{
hr = m_pFile->Open(pszFile, O_RDONLY, TRUE /*text*/);
if(SUCCEEDED(hr))
{
LoadFile();
}
}
else
{
hr = HXR_OUTOFMEMORY;
}
return hr;
}
void HXPluginArchiveReader::Close()
{
HX_DELETE(m_pFile);
}
void HXPluginArchiveReader::LoadFile()
{
#define BUF_SZ 0x0400 // read file in 1k chunks
CHXString strBuf;
char* buf = strBuf.GetBuffer(BUF_SZ + 1);
if( buf)
{
for(;;)
{
INT32 cch = (INT32)m_pFile->Read(buf, BUF_SZ);
if (cch <= 0)
{
// end of file
break;
}
buf[cch] = '\0';
m_strFile += buf;
}
}
m_strFile.TrimRight(); // ensure no trailing space so 'AtEnd()' is easier
m_idxFile = 0;
}
void HXPluginArchiveReader::GetNextToken(CHXString& str, char chTerm)
{
UINT32 cchFile = m_strFile.GetLength();
HX_ASSERT(chTerm != ESC_CHAR);
while( m_idxFile < cchFile)
{
char ch = m_strFile[m_idxFile];
if(chTerm == m_strFile[m_idxFile])
{
// found end of token; we're done
++m_idxFile;
break;
}
if( ESC_CHAR == ch )
{
// skip escape to read in escaped char
++m_idxFile;
if(m_idxFile == cchFile)
{
// unexpected: EOF in middle of escape sequence
HX_ASSERT(false);
break;
}
ch = m_strFile[m_idxFile];
}
str += ch;
++m_idxFile;
}
str.TrimLeft();
str.TrimRight();
}
//
// read name;val;name;val;;
//
//
bool HXPluginArchiveReader::Read(IHXValues*& pval)
{
HX_ASSERT(!AtEnd());
UINT32 cchFile = m_strFile.GetLength();
HX_ASSERT(m_pFactory);
m_pFactory->CreateInstance(CLSID_IHXValues,(void**)&pval);
if(!pval)
{
return false;
}
CHXString strName;
CHXString strVal;
// collect name-value pairs until we reach closing double TERM_CHAR
for(;;)
{
strName = "";
GetNextToken(strName, TERM_CHAR);
if(strName.IsEmpty())
{
// end of list (ends with empty token, i.e., double TERM_CHAR
return true;
}
if(m_idxFile == cchFile)
{
// corrupt file; end of file after name
HX_ASSERT(false);
return false;
}
strVal = "";
GetNextToken(strVal, TERM_CHAR);
if(m_idxFile == cchFile)
{
// corrupt file
HX_ASSERT(false);
return false;
}
if(strVal.IsEmpty())
{
// corrupt file
HX_ASSERT(false);
return false;
}
char type = strVal[0];
CHXString strNakedVal = strVal.Mid(1);
switch(type)
{
case 'N':
{
int val = atoi(strNakedVal);
pval->SetPropertyULONG32(strName, ULONG32(val));
}
break;
case 'B':
{
IHXBuffer* pbuff = HXBufferUtil::CreateBuffer(m_pFactory, strNakedVal);
if( pbuff)
{
pval->SetPropertyBuffer(strName, pbuff);
HX_RELEASE(pbuff);
}
}
break;
case 'S':
{
IHXBuffer* pbuff = HXBufferUtil::CreateBuffer(m_pFactory, strNakedVal);
if( pbuff)
{
pval->SetPropertyCString(strName, pbuff);
HX_RELEASE(pbuff);
}
}
break;
default:
HX_ASSERT(false);
return false;
}
}
HX_ASSERT(false);
return false;
}
void HXPluginArchiveReader::Read(bool& b)
{
HX_ASSERT(!AtEnd());
UINT32 val = 0;
Read(val);
b = (val ? true : false);
}
void HXPluginArchiveReader::Read(UINT16& val)
{
HX_ASSERT(!AtEnd());
UINT32 v;
Read(v);
HX_ASSERT(v <= 0xffff);
val = UINT16(v);
}
void HXPluginArchiveReader::Read(UINT32& val)
{
HX_ASSERT(!AtEnd());
CHXString str;
GetNextToken(str, TERM_CHAR);
val = atoi(str);
}
void HXPluginArchiveReader::Read(CHXString& str)
{
HX_ASSERT(!AtEnd());
GetNextToken(str, TERM_CHAR);
}
void HXPluginArchiveReader::Read(IHXBuffer*& pBuff)
{
HX_ASSERT(!AtEnd());
CHXString str;
GetNextToken(str, TERM_CHAR);
pBuff = HXBufferUtil::CreateBuffer(m_pFactory, str);
}
//
// HXPluginArchiveWriter
//
HXPluginArchiveWriter::HXPluginArchiveWriter()
: m_pFile(0)
, m_bAtLeastOneVal(false)
{
}
HXPluginArchiveWriter::~HXPluginArchiveWriter()
{
HX_DELETE(m_pFile);
}
//
// Open/create archive, wiping out existing if necessary
//
HX_RESULT HXPluginArchiveWriter::Open(IUnknown* pContext, const char* pszFile)
{
DPRINTF(D_INFO, ("HXPluginArchiveWriter::Open(): file = '%s'\n", pszFile));
HX_RESULT hr = HXR_FAIL;
HX_DELETE(m_pFile);
m_pFile = CHXDataFile::Construct();
if (m_pFile)
{
hr = m_pFile->Open(pszFile, O_WRONLY | O_CREAT | O_TRUNC, TRUE /*text*/);
}
else
{
hr = HXR_OUTOFMEMORY;
}
return hr;
}
void HXPluginArchiveWriter::Close()
{
HX_DELETE(m_pFile);
}
void HXPluginArchiveWriter::EscapeValue(const CHXString& str, CHXString& strOut)
{
//
// Escape special characters used for escaping and field termination
//
if( -1 == str.Find(ESC_CHAR) && -1 == str.Find(TERM_CHAR) )
{
// this may avoid copy if string class is optimized
strOut = str;
}
else
{
INT32 cch = str.GetLength();
for(INT32 idx = 0; idx < cch; ++idx)
{
char ch = str[idx];
if(ch == ESC_CHAR || ch == TERM_CHAR)
{
strOut += ESC_CHAR;
}
strOut += ch;
}
}
}
// write line break (for sake of human consumption of file contents)
void HXPluginArchiveWriter::Break()
{
const char* const BREAK_STRING = "\n";
const UINT32 CCH_BREAK_STRING = 1;
m_pFile->Write(BREAK_STRING, CCH_BREAK_STRING);
}
void HXPluginArchiveWriter::Write(const char* psz)
{
CHXString strEscaped;
EscapeValue(psz, strEscaped);
HX_ASSERT(m_pFile);
strEscaped += TERM_CHAR;
m_pFile->Write(strEscaped, strEscaped.GetLength());
}
void HXPluginArchiveWriter::Write(IHXBuffer* pBuffer)
{
HX_ASSERT(pBuffer);
const char* psz = (const char*)pBuffer->GetBuffer();
Write(psz);
}
void HXPluginArchiveWriter::Write(bool b)
{
UINT32 val = (b ? 1 : 0);
Write(val);
}
void HXPluginArchiveWriter::Write(UINT32 val)
{
CHXString str;
str.Format("%lu", val);
Write(str);
}
void HXPluginArchiveWriter::Write(UINT16 val)
{
Write(UINT32(val));
}
void HXPluginArchiveWriter::Write(IHXValues* pval)
{
HX_ASSERT(pval);
CHXString str;
ULONG32 ulValue;
const char* pszKey = NULL;
// Dump ULONG32 values
HX_RESULT hr = pval->GetFirstPropertyULONG32( pszKey, ulValue );
if( SUCCEEDED(hr) )
{
do
{
//key
Write(pszKey);
//value
str.Format("N%d", ulValue);
Write(str);
hr = pval->GetNextPropertyULONG32( pszKey, ulValue);
}
while( SUCCEEDED(hr) );
}
// Dump IHXBuffer values
IHXBuffer* pbuff;
hr = pval->GetFirstPropertyBuffer( pszKey, pbuff );
if( SUCCEEDED(hr) )
{
do
{
//key
Write(pszKey);
//value
str.Format("B%.*s", pbuff->GetSize(), pbuff->GetBuffer() );
Write(str);
HX_RELEASE(pbuff);
hr = pval->GetNextPropertyBuffer( pszKey,pbuff);
}
while( SUCCEEDED(hr) );
}
// Dump CString values
hr = pval->GetFirstPropertyCString( pszKey, pbuff );
if( SUCCEEDED(hr) )
{
do
{
//key
Write(pszKey);
//value
str.Format("S%.*s", pbuff->GetSize(), pbuff->GetBuffer() );
Write(str);
HX_RELEASE(pbuff);
hr = pval->GetNextPropertyCString( pszKey, pbuff);
}
while( SUCCEEDED(hr) );
}
// empty value terminates list
Write("");
}
//XXXLCM util
IHXBuffer* HXBufferUtil::CreateBuffer(IHXCommonClassFactory* pFact, const char* psz)
{
if(!psz)
{
psz = "";
}
IHXBuffer* pbuff = 0;
HX_RESULT hr = pFact->CreateInstance(CLSID_IHXBuffer, (void**)&pbuff);
if( SUCCEEDED(hr) )
{
hr = pbuff->Set( (BYTE*)psz, strlen(psz) + 1);
if( FAILED(hr) )
{
HX_RELEASE(pbuff);
}
}
return pbuff;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -