You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
7.7 KiB
274 lines
7.7 KiB
// AdFile.cpp: implementation of the CAdFile class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#undef max
|
|
#include "AdRot.h"
|
|
#include "AdFile.h"
|
|
#include "RotObj.h"
|
|
#include "sinstrm.h"
|
|
|
|
extern CMonitor* g_pMonitor;
|
|
|
|
#ifdef DBG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------
|
|
// CAdFileNotify
|
|
//--------------------------------------------------------------------
|
|
CAdFileNotify::CAdFileNotify()
|
|
: m_isNotified(0)
|
|
{
|
|
}
|
|
|
|
void
|
|
CAdFileNotify::Notify()
|
|
{
|
|
::InterlockedExchange( &m_isNotified, 1 );
|
|
}
|
|
|
|
bool
|
|
CAdFileNotify::IsNotified()
|
|
{
|
|
return ( ::InterlockedExchange( &m_isNotified, 0 ) ? true : false );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// CAdFile
|
|
//--------------------------------------------------------------------
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CAdFile::CAdFile()
|
|
: m_nBorder(defaultBorder),
|
|
m_nHeight(defaultHeight),
|
|
m_nWidth(defaultWidth),
|
|
m_nVSpace(defaultVSpace),
|
|
m_nHSpace(defaultHSpace),
|
|
m_strRedirector( _T("")),
|
|
m_fUTF8(false)
|
|
{
|
|
m_pNotify = new CAdFileNotify;
|
|
}
|
|
|
|
CAdFile::~CAdFile()
|
|
{
|
|
if ( g_pMonitor )
|
|
{
|
|
g_pMonitor->StopMonitoringFile( m_strFile.c_str() );
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// ProcessAdFile will check the given filename, if it matches the one it
|
|
// knows it currently has in memory, it will do nothing. If the filename
|
|
// differs, the old ad information will be dumped, and the new information
|
|
// parsed and stored.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
bool
|
|
CAdFile::ProcessAdFile(
|
|
String strAdFile )
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
bool rc = false;
|
|
UINT weightSum = 0;
|
|
|
|
// block all other readers and writers
|
|
CWriter wtr( *this );
|
|
m_ads.erase( m_ads.begin(), m_ads.end() );
|
|
|
|
|
|
// parse the file
|
|
FileInStream fs;
|
|
HRESULT hr = fs.Init( T2CA(strAdFile.c_str()) );
|
|
if ( SUCCEEDED(hr) && fs.is_open())
|
|
{
|
|
if ( ReadHeader( fs ) )
|
|
{
|
|
while ( !fs.eof() )
|
|
{
|
|
// read one "ad record"
|
|
String strGif;
|
|
String strLink;
|
|
String strAlt;
|
|
String strWeight;
|
|
ULONG lWeight = 0;
|
|
|
|
fs >> strGif >> strLink;
|
|
// this just gets us past the new line
|
|
fs.readLine( strAlt );
|
|
fs >> strWeight;
|
|
|
|
|
|
// check for a negative impression value. RaiseException if
|
|
// negative
|
|
|
|
if (strWeight[0] == '-') {
|
|
CAdRotator::RaiseException( IDS_ERROR_BAD_WEIGHT_VALUE );
|
|
goto err;
|
|
}
|
|
lWeight = strWeight.toUInt32();
|
|
|
|
weightSum += lWeight;
|
|
|
|
if (weightSum > 10000) {
|
|
CAdRotator::RaiseException( IDS_ERROR_WEIGHT_SUM_TOO_LARGE );
|
|
goto err;
|
|
}
|
|
|
|
if ( lWeight != 0 )
|
|
{
|
|
CAdDescPtr pAd = new CAdDescriptor( lWeight, strLink, strGif, strAlt );
|
|
if ( pAd.IsValid() )
|
|
{
|
|
// add one reference to the ad for each weight
|
|
for( int i = 0; i < lWeight; i++ )
|
|
{
|
|
m_ads.push_back( pAd );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( m_ads.size() > 0 )
|
|
{
|
|
if ( m_strFile != strAdFile )
|
|
{
|
|
g_pMonitor->StopMonitoringFile( m_strFile.c_str() );
|
|
m_strFile = strAdFile;
|
|
g_pMonitor->MonitorFile( m_strFile.c_str(), m_pNotify );
|
|
}
|
|
rc = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CAdRotator::RaiseException( IDS_ERROR_CANNOT_READ_ROTATION_SCHEDULE_FILE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CAdRotator::RaiseException( IDS_ERROR_CANNOT_LOAD_ROTATION_SCHEDULE_FILE );
|
|
}
|
|
err:
|
|
|
|
return rc;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Refresh will check to see if the cached information is out of date, if so
|
|
// it will re-read the file
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
bool
|
|
CAdFile::Refresh()
|
|
{
|
|
bool rc = false;
|
|
if ( m_pNotify->IsNotified() )
|
|
{
|
|
rc = ProcessAdFile( m_strFile );
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// ReadHeader will parse the header portion of the file. The header includes
|
|
// some or all of the following fields: HEIGHT, WIDTH, BORDER, REDIRECT,
|
|
// HSPACE, VSPACE. The fields are separated by newlines and the header is
|
|
// terminated by an asterix.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
bool
|
|
CAdFile::ReadHeader(
|
|
FileInStream& fs )
|
|
{
|
|
bool rc = false;
|
|
|
|
// set defaults
|
|
m_nHeight = defaultHeight;
|
|
m_nWidth = defaultWidth;
|
|
m_nHSpace = defaultHSpace;
|
|
m_nVSpace = defaultVSpace;
|
|
|
|
m_fUTF8 = fs.is_UTF8();
|
|
|
|
bool done = false;
|
|
while ( !fs.eof() && !done )
|
|
{
|
|
String strLine;
|
|
String strName;
|
|
fs.readLine( strLine );
|
|
StringInStream sis( strLine );
|
|
sis >> strName;
|
|
HRESULT hr = S_OK;
|
|
if ( _tcsicmp( strName.c_str(), _T("HEIGHT") ) == 0 )
|
|
{
|
|
hr = sis.readInt( m_nHeight );
|
|
}
|
|
else if ( _tcsicmp( strName.c_str(), _T("WIDTH") ) == 0 )
|
|
{
|
|
hr = sis.readInt( m_nWidth );
|
|
}
|
|
else if ( _tcsicmp( strName.c_str(), _T("VSPACE") ) == 0 )
|
|
{
|
|
hr = sis.readInt( m_nVSpace );
|
|
}
|
|
else if ( _tcsicmp( strName.c_str(), _T("HSPACE") ) == 0 )
|
|
{
|
|
hr = sis.readInt( m_nHSpace );
|
|
}
|
|
else if ( _tcsicmp( strName.c_str(), _T("REDIRECT") ) == 0 )
|
|
{
|
|
hr = sis.readString( m_strRedirector );
|
|
}
|
|
else if ( _tcsicmp( strName.c_str(), _T("BORDER" ) ) == 0 )
|
|
{
|
|
hr = sis.readInt16( m_nBorder );
|
|
}
|
|
else if ( _tcsicmp( strName.c_str(), _T("*") ) == 0 )
|
|
{
|
|
rc = true;
|
|
done = true;
|
|
}
|
|
else
|
|
{
|
|
CAdRotator::RaiseException( IDS_ERROR_UNKNOWN_HEADER_NAME );
|
|
}
|
|
/*
|
|
if ( hr != S_OK )
|
|
{
|
|
CAdRotator::RaiseException( IDS_ERROR_HEADER_HAS_NO_ASSOCIATED_VALUE );
|
|
}
|
|
*/
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// RandomAd chooses and ad at random from the list of ads. Since there
|
|
// are multiple references to ads based on the weight, we need only produce
|
|
// a random number between 0 and one less than the size of the list.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
CAdDescPtr
|
|
CAdFile::RandomAd() const
|
|
{
|
|
if (m_ads.size() > 0)
|
|
return m_ads[ rand() % m_ads.size() ];
|
|
else
|
|
return NULL;
|
|
}
|
|
|