|
|
// 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; }
|