This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CAllPlayersStats
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "AllPlayersStats.h"
#include "PlayerReport.h"
#include "TextFile.h"
//------------------------------------------------------------------------------------------------------
// Function: CAllPlayersStats::init
// Purpose: intializes the object
//------------------------------------------------------------------------------------------------------
void CAllPlayersStats::init()
{
}
//------------------------------------------------------------------------------------------------------
// Function: CAllPlayersStats::generate
// Purpose: generates intermediate data from match info
//------------------------------------------------------------------------------------------------------
void CAllPlayersStats::generate()
{
}
//------------------------------------------------------------------------------------------------------
// Function: CAllPlayersStats::writeHTML
// Purpose: writes out html based on the intermediate data generated by generate()
// Input: html - the html file to output to
//------------------------------------------------------------------------------------------------------
void CAllPlayersStats::writeHTML(CHTMLFile& html)
{
string filename;
bool result=g_pApp->os->findfirstfile("*.tfs",filename);
if (!result)
return;
multimap<double,CPlrPersist,greater<double> > ranksort;
html.write("<table cols=1 cellspacing=0 border=0 cellpadding=10 bordercolor=black>\n");
while(1)
{
CTextFile f(filename);
pair<double,CPlrPersist> insertme;
insertme.second.read(f);
insertme.first=insertme.second.rank();
ranksort.insert(insertme);
if (!g_pApp->os->findnextfile(filename))
break;
}
g_pApp->os->findfileclose();
multimap<double,CPlrPersist,greater<double> >::iterator rankit=ranksort.begin();
for (rankit;rankit!=ranksort.end();++rankit)
{
bool rowstarted=false;
//double rank=rankit->first;
CPlrPersist* pcpp=&(rankit->second);
time_t cutoff=g_pMatchInfo->logOpenTime() - g_pApp->getCutoffSeconds();
if (pcpp->lastplayed >= cutoff || !g_pApp->eliminateOldPlayers)
{
if (!rowstarted)
{
rowstarted=true;
html.write("<tr>\n");
}
html.write("<td width=300 valign=top>");
CPlayerReport pr(pcpp);
pr.writeHTML(html);
html.write("</td>\n");
}
if (++rankit==ranksort.end())
{
if (rowstarted)
html.write("</tr>\n");
break;
}
//double rank=rankit->first;
CPlrPersist* pcpp2=&(rankit->second);
if (pcpp->lastplayed >= cutoff || !g_pApp->eliminateOldPlayers)
{
if (!rowstarted)
{
rowstarted=true;
html.write("<tr>\n");
}
html.write("<td width=300 valign=top>");
CPlayerReport pr2(pcpp2);
pr2.writeHTML(html);
html.write("</td>\n");
}
if (rowstarted)
html.write("</tr>\n");
}
html.write("</table>");
}
+45
View File
@@ -0,0 +1,45 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface to CAllPlayersStats
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef ALLPLAYERSSTATS_H
#define ALLPLAYERSSTATS_H
#ifdef WIN32
#pragma once
#endif
#pragma warning (disable: 4786)
#include "report.h"
#include <map>
#include <vector>
#include <string>
using namespace std;
//------------------------------------------------------------------------------------------------------
// Purpose: CAllPlayersStats is a whole page report element that reports specific
// data about each player that has played on the server. Data such as favourite
// weapon, rank, classes played, favourite class, and kills vs deaths.
//------------------------------------------------------------------------------------------------------
class CAllPlayersStats :public CReport
{
private:
void init();
public:
explicit CAllPlayersStats(){init();}
void generate();
void writeHTML(CHTMLFile& html);
};
#endif // ALLPLAYERSSTATS_H
+217
View File
@@ -0,0 +1,217 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CLogEventArgument
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#pragma warning (disable:4786)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "argument.h"
#include "memdbg.h"
using namespace std;
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::CLogEventArgument
// Purpose: Constructor that builds the object out of the passed in string of text
// Input: text - text representing the argument
//------------------------------------------------------------------------------------------------------
CLogEventArgument::CLogEventArgument(const char* text)
{
init(text);
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::CLogEventArgument
// Purpose: Default constructor
//------------------------------------------------------------------------------------------------------
CLogEventArgument::CLogEventArgument()
:m_ArgText(NULL),m_Valid(false)
{}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::init
// Purpose: initializes the argument
// Input: text - the text representing the argument
//------------------------------------------------------------------------------------------------------
void CLogEventArgument::init(const char* text)
{
int len=strlen(text);
m_ArgText=new TRACKED char[len+1];
strcpy(m_ArgText,text);
m_Valid=true;
}
char* findStartOfSvrID(char* cs)
{
char* read=&cs[strlen(cs)-1];
while (read != cs)
{
if (*read=='<' && *(read+1) != 'W') // if we've found a svrID
break;
read--;
}
return read;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::asPlayerGetID
// Purpose: treats the argument as a player name, and returns the player ID.
// Note: PlayerName args have this form: "name<pid><WON:wonid>"
// Output: the ID of the player represented by this argument
//------------------------------------------------------------------------------------------------------
int CLogEventArgument::asPlayerGetSvrPID() const
{
char* read=findStartOfSvrID(m_ArgText);
if (read==m_ArgText)
return -1;
int retval=-1;
sscanf(read,"<%i>",&retval);
return retval;
}
/*
PID CLogEventArgument::asPlayerGetPID() const
{
char* openPID=NULL;
int svrPID=INVALID_PID;
if (openPID=strchr(m_ArgText,'<'))
{
openPID++;
sscanf(openPID,"%i",&svrPID);
}
unsigned long wonID;
if (openPID=strstr(m_ArgText,"<WON:"))
{
openPID+=5;
sscanf(openPID,"%li",&wonID);
}
return PID(svrPID,wonID);
}
*/
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::asPlayerGetName
// Purpose: treats the argument as a player name, and copies/returns the player name.
// Note: PlayerName args have this form: "name<pid><WONID:wonid>"
// Input: copybuf - the buffer to copy the name into
// Output: char* the pointer to the buffer that the name was copied into
//------------------------------------------------------------------------------------------------------
char* CLogEventArgument::asPlayerGetName(char* copybuf) const
{
char* eon=findStartOfSvrID(m_ArgText);
bool noPID=(eon==m_ArgText);
char old=*eon;
if (!noPID)
*eon=0;
strcpy(copybuf,m_ArgText);
if (!noPID)
*eon=old;
return copybuf;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::asPlayerGetName
// Purpose: an alternate form of the above function that returns the playername
// as a C++ string, rather than buffercopying it around
// Output: string: the player's name
//------------------------------------------------------------------------------------------------------
string CLogEventArgument::asPlayerGetName() const
{
char* eon=findStartOfSvrID(m_ArgText);
bool noPID=(eon==m_ArgText);
char old=*eon;
if (!noPID)
*eon=0;
string s(m_ArgText);
if (!noPID)
*eon=old;
return s;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::asPlayerGetWONID
// Purpose: treats the argument as a player name, and returns the player's wonid
// Note: PlayerName args have this form: "name<pid><WON:wonid>"
// Output: int: the WONID of the player
//------------------------------------------------------------------------------------------------------
unsigned long CLogEventArgument::asPlayerGetWONID() const
{
char* openPID=NULL;
unsigned long retval=INVALID_WONID;
if (openPID=strstr(m_ArgText,"<WON:"))
{
openPID+=5; //move past the <WON: string
sscanf(openPID,"%lu",&retval);
}
return retval;
}
unsigned long CLogEventArgument::asPlayerGetPID() const
{
int svrPID=asPlayerGetSvrPID();
if (pidMap[svrPID]==0 || pidMap[svrPID]==-1)
pidMap[svrPID]=svrPID;
return pidMap[svrPID];
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::getFloatValue
// Purpose: treats the argument as a floating point value, and returns it
// Output: double
//------------------------------------------------------------------------------------------------------
double CLogEventArgument::getFloatValue() const
{
return atof(m_ArgText);
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::getStringValue
// Purpose: treats the argument as a string and returns a pointer to the argument
// text itself. note the pointer is const, so the argument can't be modified by
// the caller (unless they perform some nefarious casting on the returned pointer)
// Output: const char*
//------------------------------------------------------------------------------------------------------
const char* CLogEventArgument::getStringValue() const
{
return m_ArgText;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEventArgument::getStringValue
// Purpose: an alternate form of the above that copies the string into a caller
// supplied buffer then returns a pointer to that buffer
// Input: copybuf - the buffer into which the string is to be copied
// Output: char* the pointer to the buffer that the caller passed in
//------------------------------------------------------------------------------------------------------
char* CLogEventArgument::getStringValue(char* copybuf) const
{
strcpy(copybuf,m_ArgText);
return copybuf;
}
+63
View File
@@ -0,0 +1,63 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CLogEventArgument
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef ARGUMENT_H
#define ARGUMENT_H
#ifdef WIN32
#pragma once
#endif
#include "pid.h"
#include <vector>
#include <string>
//------------------------------------------------------------------------------------------------------
// Purpose: CLogEventArgument represents a variable in the text of an event.
// for example, "X" killed "Y" with "Z". X Y and Z are all represented by seperate
// instances of this class.
//------------------------------------------------------------------------------------------------------
class CLogEventArgument
{
public:
enum
{
INVALID_PID=-1,
INVALID_WONID=0,
VALUE_WID=64,
PLAYER_NAME_WID=VALUE_WID,
WONID_WID=(10+6), //<WON:xxxxxxxxxx>
PLAYERID_WID=4 // <xx> //only up to 99 players :(
};
private:
char* m_ArgText;
bool m_Valid;
public:
explicit CLogEventArgument(const char* text);
CLogEventArgument();
void init(const char* text);
//int asPlayerGetID() const;
int asPlayerGetSvrPID() const;
unsigned long asPlayerGetWONID() const;
PID asPlayerGetPID() const;
char* asPlayerGetName(char* copybuf) const;
std::string asPlayerGetName() const;
double getFloatValue() const;
const char* getStringValue() const;
char* getStringValue(char* copybuf) const;
bool isValid() const {return m_Valid;}
};
typedef std::vector<CLogEventArgument*> ArgVector;
#endif // ARGUMENT_H
+59
View File
@@ -0,0 +1,59 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CAward
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "Award.h"
//------------------------------------------------------------------------------------------------------
// Function: CAward::CAward
// Purpose: Constructor.
// Input: name - the name of the award
// pmi - a pointer to the match information
//------------------------------------------------------------------------------------------------------
CAward::CAward(char* name)
:awardName(name),fNoWinner(true),winnerID(-1)
{}
//------------------------------------------------------------------------------------------------------
// Function: CAward::generate
// Purpose: overrides generate to call the more-semantically correct getWinner()
// when dealing with subclasses of awards. Also after getWinner has determined
// which PID is the winner, this assigns the correct name to the winnerName field
//------------------------------------------------------------------------------------------------------
void CAward::generate()
{
winnerName="";
getWinner();
if (winnerID!=-1)
winnerName=g_pMatchInfo->playerName(winnerID);
}
//------------------------------------------------------------------------------------------------------
// Function: CAward::writeHTML
// Purpose: writes the award to the given html page
// Input: html - the page to output the award to
//------------------------------------------------------------------------------------------------------
void CAward::writeHTML(CHTMLFile& html)
{
if (fNoWinner || (winnerID == -1 && winnerName==""))
noWinner(html);
else
{
html.write("The <font class=brightawards>%s</font> award goes to %s! ",awardName.c_str(),winnerName.c_str());
extendedinfo(html);
}
html.br();
html.write("\n");
}
CAward::~CAward()
{
}
+56
View File
@@ -0,0 +1,56 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CAward, the base class for all awards
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef AWARD_H
#define AWARD_H
#ifdef WIN32
#pragma once
#endif
#pragma warning(disable :4786)
#include "Report.h"
#include <string>
//------------------------------------------------------------------------------------------------------
// Purpose: CAward is the base class for all awards, it is in turn a subclass of
// CReport. This class handles all the boring details of writing out the awards
// and things, so that the subclasses need only specify the name of the award
// and who won it, then this class will take care of the rest
//------------------------------------------------------------------------------------------------------
class CAward: public CReport
{
//from CReport:
protected:
virtual void generate();
protected:
std::string awardName;
std::string winnerName;
PID winnerID;
bool fNoWinner;
CAward(char* name);
virtual void extendedinfo(CHTMLFile& html){};
virtual void noWinner(CHTMLFile& html){};
public:
virtual void getWinner(){}
virtual void writeHTML(CHTMLFile& html);
virtual ~CAward();
};
#endif // AWARD_H
+27
View File
@@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Includes all of the awards' header files, to save on typing. :)
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef AWARDS_H
#define AWARDS_H
#ifdef WIN32
#pragma once
#endif
#include "SentryRebuildAward.h"
#include "CureAward.h"
#include "KamikazeAward.h"
#include "TalkativeAward.h"
#include "WeaponAwards.h"
#include "SharpshooterAward.h"
#include "TeamkillAward.h"
#include "SurvivalistAward.h"
#endif // AWARDS_H
+48
View File
@@ -0,0 +1,48 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef BINARYRESOURCE_H
#define BINARYRESOURCE_H
#ifdef WIN32
#pragma once
#endif
#include <string>
#include <stdio.h>
#include "util.h"
class CBinaryResource
{
private:
std::string filename;
size_t numBytes;
unsigned char* pData;
public:
CBinaryResource(char* name, size_t bytes,unsigned char* data)
:filename(name),numBytes(bytes),pData(data)
{}
bool writeOut()
{
FILE* f=fopen(filename.c_str(),"wb");
if (!f)
return false;
fwrite(pData,1,numBytes,f);
fclose(f);
#ifndef WIN32
chmod(filename.c_str(),PERMIT);
#endif
return true;
}
};
#endif // BINARYRESOURCE_H
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CCureAward
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "CureAward.h"
//------------------------------------------------------------------------------------------------------
// Function: CCureAward::getWinner
// Purpose: determines who cured the most people during the match
//------------------------------------------------------------------------------------------------------
void CCureAward::getWinner()
{
CEventListIterator it;
for (it=g_pMatchInfo->eventList()->begin(); it != g_pMatchInfo->eventList()->end(); ++it)
{
if ((*it)->getType()==CLogEvent::CURE)
{
PID doc=(*it)->getArgument(0)->asPlayerGetPID();
numcures[doc]++;
winnerID=doc;
fNoWinner=false;
}
}
map<PID,int>::iterator cureiter;
for (cureiter=numcures.begin();cureiter!=numcures.end();++cureiter)
{
PID currID=(*cureiter).first;
if (numcures[currID]>numcures[winnerID])
winnerID=currID;
}
}
//------------------------------------------------------------------------------------------------------
// Function: CCureAward::noWinner
// Purpose: writes html indicating that no one was cured during this match
// Input: html - the html file to write to
//------------------------------------------------------------------------------------------------------
void CCureAward::noWinner(CHTMLFile& html)
{
html.write("No one was cured during this match.");
}
//------------------------------------------------------------------------------------------------------
// Function: CCureAward::extendedinfo
// Purpose: reports how many people the winner cured
// Input: html - the html file to write to
//------------------------------------------------------------------------------------------------------
void CCureAward::extendedinfo(CHTMLFile& html)
{
if (numcures[winnerID]==1)
html.write("%s cured 1 sick person!",winnerName.c_str());
else
html.write("%s healed cured %li sick people!",winnerName.c_str(),numcures[winnerID]);
}
+21
View File
@@ -0,0 +1,21 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "Award.h"
#include <map>
using namespace std;
class CCureAward: public CAward
{
protected:
map <PID,int> numcures;
void noWinner(CHTMLFile& html);
void extendedinfo(CHTMLFile& html);
public:
explicit CCureAward():CAward("Life-Saver"){}
void getWinner();
};
+269
View File
@@ -0,0 +1,269 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#pragma warning (disable:4786)
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Implementation of CCustomAward
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include <string.h>
#include "TFStatsApplication.h"
#include "CustomAward.h"
#include "TextFile.h"
#include "memdbg.h"
//------------------------------------------------------------------------------------------------------
// Function: CCustomAward::extendedinfo
// Purpose: writes extra info about the award winner, like their score or something.
// The extra info string is defined by the user in the configuration file like the
//rest of a custom award's properties.
// Input: html - the html file to write to
//------------------------------------------------------------------------------------------------------
void CCustomAward::extendedinfo(CHTMLFile& html)
{
if (extraInfoMsg.empty())
return;
char str[500];
char outputstring[2000]={0};
strcpy(str,extraInfoMsg.c_str());
char delims[]={" \n\t"};
char* temp=NULL;
temp=strtok(str,delims);
while(temp!=NULL)
{
char word[500];
if (strnicmp(temp,"%player",strlen("%player"))==0)
{
char* more=&temp[strlen("%player")];
sprintf(word,"%s%s",winnerName.c_str(),more);
}
else if (strnicmp(temp,"%winner",strlen("%winner"))==0)
{
char* more=&temp[strlen("%winner")];
sprintf(word,"%s%s",winnerName.c_str(),more);
}
else if (strnicmp(temp,"%score",strlen("%score"))==0)
{
char* more=&temp[strlen("%score")];
if (!namemode)
sprintf(word,"%li%s",plrscores[winnerID],more);
else
sprintf(word,"%li%s",stringscores[winnerName],more);
}
else if (strnicmp(temp,"%number",strlen("%number"))==0)
{
//right now this is just the score
char* more=&temp[strlen("%number")];
if (!namemode)
sprintf(word,"%li%s",plrnums[winnerID],more);
else
sprintf(word,"%li%s",stringscores[winnerName],more);
}
else
strcpy(word,temp);
strcat(outputstring," ");
strcat(outputstring,word);
temp=strtok(NULL,delims);
}
html.write(outputstring);
}
//------------------------------------------------------------------------------------------------------
// Function: CCustomAward::noWinner
// Purpose: writes some html saying that no one won this award. The noWinnerMsg
// is defined by the user in the configuration file like all other custom
// award properties
// Input: html - the html file to write to
//------------------------------------------------------------------------------------------------------
void CCustomAward::noWinner(CHTMLFile& html)
{
if (noWinnerMsg.empty())
return;
html.write(noWinnerMsg.c_str());}
//------------------------------------------------------------------------------------------------------
// Function: CCustomAward::readCustomAward
// Purpose: Factory method to read an award from a config file and return an
// instance of the CCustomAward class
// Input: f - the configuration file to read from
// g_pMatchInfo - a pointer to a matchinfo object to give to the new award
// Output: CCustomAward*
//------------------------------------------------------------------------------------------------------
CCustomAward* CCustomAward::readCustomAward(CTextFile& f)
{
const char* token=f.getToken();
while (token)
{
if (!stricmp(token,"Award"))
break;
else if (!stricmp(token,"{"))
f.discardBlock();
token=f.getToken();
}
if (!token)
return NULL;
f.discard("{");
token=f.getToken();
CCustomAward* pCustAward=new TRACKED CCustomAward(g_pMatchInfo);
while (token)
{
if (stricmp(token,"trigger")==0)
{
CCustomAwardTrigger* ptrig=CCustomAwardTrigger::readTrigger(f);
pCustAward->triggers.push_back(ptrig);
}
else if (stricmp(token,"extraInfo")==0)
{
f.discard("=");
pCustAward->extraInfoMsg=f.readString();
f.discard(";");
}
else if (stricmp(token,"noWinnerMessage")==0)
{
f.discard("=");
pCustAward->noWinnerMsg=f.readString();
f.discard(";");
}
else if (stricmp(token,"name")==0)
{
f.discard("=");
pCustAward->awardName=f.readString();
f.discard(";");
}
else if (stricmp(token,"}")==0)
{
break;
}
else
g_pApp->fatalError("Unrecognized Award property name while parsing %s: \"%s\" is not a property of an Award!",f.fileName().c_str(),token);
token = f.getToken();
}
return pCustAward;
}
//------------------------------------------------------------------------------------------------------
// Function: CCustomAward::getWinner
// Purpose: generates the winner of this custom award.
//------------------------------------------------------------------------------------------------------
void CCustomAward::getWinner()
{
fNoWinner=true;
CEventListIterator it;
for (it=g_pMatchInfo->eventList()->begin();it!=g_pMatchInfo->eventList()->end();it++)
{
list<CCustomAwardTrigger*>::iterator tli;
for (tli=triggers.begin();tli!=triggers.end();++tli)
{
if ((*tli)->matches(*it))
{
//increase the players count by X score.
//scan for best at the end
//different triggers have the player name/id placed differently. :(
//if this returns -1, store based on name. (this way we can give awards to things other than player names
//while remaining in this award/trigger hierarchy structure)
PID ID =(*tli)->plrIDFromEvent(*it);
if (ID==-1)
{
string ws=(*tli)->getTrackString(*it);
stringscores[ws]+=(*tli)->plrValue;
stringnums[ws]++;
fNoWinner=false;
namemode=true;
}
else
{
plrscores[ID]+=(*tli)->plrValue;
plrnums[ID]++;
fNoWinner=false;
namemode=false;
}
}
}
}
if (fNoWinner)
return;
if (!namemode)
{
//now scan and find highest score.
map<PID,int>::iterator scores_it;
scores_it=plrscores.begin();
winnerID=(*scores_it).first;
int winnerScore=(*scores_it).second;
for (scores_it=plrscores.begin();scores_it!=plrscores.end();++scores_it)
{
int ID=(*scores_it).first;
int score=(*scores_it).second;
if (score > winnerScore)
{
winnerScore=score;
winnerID=ID;
}
}
}
else
{
//now scan and find highest score.
map<string,int>::iterator scores_it;
scores_it=stringscores.begin();
winnerID=-1;
winnerName=(*scores_it).first;
int winnerScore=(*scores_it).second;
for (scores_it=stringscores.begin();scores_it!=stringscores.end();++scores_it)
{
string name=(*scores_it).first;
int score=(*scores_it).second;
if (score > winnerScore)
{
winnerScore=score;
winnerName=name;
}
}
}
}
+62
View File
@@ -0,0 +1,62 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface to CCustomAward
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef CUSTOMAWARD_H
#define CUSTOMAWARD_H
#ifdef WIN32
#pragma once
#endif
#pragma warning(disable :4786)
#include "Award.h"
#include "TextFile.h"
#include "CustomAwardTriggers.h"
#include <list>
using namespace std;
//------------------------------------------------------------------------------------------------------
// Purpose: CCustomAward represents an award that is user-definable via
// a configuration file. Other than their runtime definitions, Custom awards
// act just like other static awards.
//------------------------------------------------------------------------------------------------------
class CCustomAward: public CAward
{
public:
//factory method.
static CCustomAward* readCustomAward(CTextFile& f);
protected:
list<CCustomAwardTrigger*> triggers;
bool namemode;
map<string,string> extraProps;
map<PID,int> plrscores; //this is wrt to the current award. score in this sense is not related to game score
// but simply a score that is relative to other contenders for the award.
map<PID,int> plrnums; //this is the number of times any of the triggers was activated
map<string,int> stringscores; //this is wrt to the current award. score in this sense is not related to game score
// but simply a score that is relative to other contenders for the award.
map<string,int> stringnums; //this is the number of times any of the triggers was activated
string noWinnerMsg;
string extraInfoMsg;
virtual void extendedinfo(CHTMLFile& html);
virtual void noWinner(CHTMLFile& html);
public:
explicit CCustomAward(CMatchInfo* pmi):CAward("custom_temp"){}
void getWinner();
};
#endif // CUSTOMAWARD_H
+80
View File
@@ -0,0 +1,80 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CCustomAwardList
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "CustomAwardList.h"
#include "memdbg.h"
//------------------------------------------------------------------------------------------------------
// Function: CCustomAwardList::readCustomAwards
// Purpose: Factory method to read from a file and return a list of custom awards
// Input: mapname - the name of the map determines the rule file to read the awards from
// pmi - a pointer to the Match Info which will be passed to each custom award
// Output: CCustomAwardList*
//------------------------------------------------------------------------------------------------------
CCustomAwardList* CCustomAwardList::readCustomAwards(string mapname)
{
char filename[255];
g_pApp->os->chdir(g_pApp->ruleDirectory.c_str());
sprintf(filename,"tfc.%s.rul",mapname.c_str());
CTextFile ctf1(filename);
CTextFile ctf2("tfc.rul");
if (!ctf1.isValid() && ctf2.isValid())
{
if (stricmp(filename,"tfc..rul")==0)
g_pApp->warning("Could not find mapname in the log file, map-specific custom rules will not be used");
else
g_pApp->warning("Could not find %s, map-specific custom rules will not be used",filename);
}
if (!ctf2.isValid() && ctf1.isValid())
{
g_pApp->warning("tfc.rul could not be found. Only map-specific rules will be used");
}
if (!ctf2.isValid() && !ctf1.isValid())
{
g_pApp->warning("Neither tfc.rul nor %s could be found. No custom rules will be used");
return NULL;
}
CCustomAwardList* newList=new TRACKED CCustomAwardList;
bool foundAward=false;
CCustomAward* pcca=CCustomAward::readCustomAward(ctf1);
while (pcca)
{
foundAward=true;
newList->theList.push_back(pcca);
pcca=CCustomAward::readCustomAward(ctf1);
}
pcca=CCustomAward::readCustomAward(ctf2);
while (pcca)
{
foundAward=true;
newList->theList.push_back(pcca);
pcca=CCustomAward::readCustomAward(ctf2);
}
if (!foundAward)
{
delete newList;
g_pApp->warning("Could not find any custom rules in either tfc.rul or %s. No custom rules will be used.\n",filename);
newList=NULL;
}
return newList;
}
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CCustomAwardList
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef CUSTOMAWARDLIST_H
#define CUSTOMAWARDLIST_H
#ifdef WIN32
#pragma once
#endif
#include "CustomAward.h"
#include <list>
using namespace std;
typedef list<CCustomAward*>::iterator CCustomAwardIterator;
//------------------------------------------------------------------------------------------------------
// Purpose: this is just a thin wrapper around a list of CCustomAward*s
// also provided is a static factory method to read a list of custom awards
// out of a configuration file
//------------------------------------------------------------------------------------------------------
class CCustomAwardList
{
public:
list<CCustomAward*> theList;
//factory method
static CCustomAwardList* readCustomAwards(string mapname);
CCustomAwardIterator begin(){return theList.begin();}
CCustomAwardIterator end(){return theList.end();}
};
#endif // CUSTOMAWARDLIST_H
+399
View File
@@ -0,0 +1,399 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#pragma warning (disable:4786)
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Implementation of all the custom award trigger classes
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "TFStatsApplication.h"
#include "CustomAwardTriggers.h"
#include "memdbg.h"
#include "util.h"
using namespace std;
//------------------------------------------------------------------------------------------------------
// Function: CCustomAwardTrigger::readTrigger
// Purpose: reads a trigger definition from the given rule file and returns a new trigger
// Input: f - a pointer to the TextFile object that represents the rule file to read from
// Output: CCustomAwardTrigger*
//------------------------------------------------------------------------------------------------------
CCustomAwardTrigger* CCustomAwardTrigger::readTrigger(CTextFile& f)
{
CCustomAwardTrigger* retval=NULL;
string type="fullsearch";
vector<string> keys;
int value = 1 ;
int teamValue = 1;
f.discard("{");
map<string,string> extraProps;
const char* token=f.getToken();
while (token)
{
if (stricmp(token,"value")==0)
{
f.discard("=");
value=atoi(f.readString());
f.discard(";");
}
else if (stricmp(token,"teamvalue")==0)
{
f.discard("=");
teamValue=atoi(f.readString());
f.discard(";");
}
else if (stricmp(token,"type")==0)
{
f.discard("=");
type=f.readString();
f.discard(";");
}
else if (stricmp(token,"key")==0)
{
f.discard("=");
char lowerbuf[500];
Util::str2lowercase(lowerbuf,f.readString());
keys.push_back(lowerbuf);
f.discard(";");
}
else if (stricmp(token,"}")==0)
{
break;
}
else
{
f.discard("=");
char lowerbuf[500];
char lowerbuf2[500];
//oops, have to do this first. CTextfile uses a static buffer to return strings
Util::str2lowercase(lowerbuf2,token);
Util::str2lowercase(lowerbuf,f.readString());
extraProps[lowerbuf2]=lowerbuf;
f.discard(";");
}
token=f.getToken();
}
if (type=="broadcast")
retval= new TRACKED CBroadcastTrigger(value,teamValue,keys,extraProps);
else if (type=="goal")
retval = new TRACKED CGoalTrigger(value,teamValue,keys,extraProps);
else if (type=="fullsearch")
retval = new TRACKED CFullSearchTrigger(value,teamValue,keys,extraProps);
else
g_pApp->fatalError("Invalid trigger type while parsing %s:\n\"%s\" is not a valid trigger type, please use \"broadcast\", \"goal\" or \"fullsearch\"",f.fileName().c_str(),type);
return retval;
}
//------------------------------------------------------------------------------------------------------
// Function: CBroadcastTrigger::CBroadcastTrigger
// Purpose: Constructor for CBroadcastTrigger
// Input: value - the value of the trigger relative to other triggers
// teamValue - the teamValue of the trigger (not used)
// keys - strings to search for in the text of any broadcast event
//------------------------------------------------------------------------------------------------------
CBroadcastTrigger::CBroadcastTrigger (int value, int teamValue, vector<string>& keys,map<string,string> extras)
:CCustomAwardTrigger(value,teamValue,extras)
{
//this line works in win32, but not in G++... g++ doesn't seem to have vector::assign
//broadcastStrings.assign(keys.begin(),keys.end());
//make a new temp object, and assign it to broadcastStrings
broadcastStrings=vector<string>(keys);
}
//------------------------------------------------------------------------------------------------------
// Function: CBroadcastTrigger::matches
// Purpose: Determines if a given event is a broadcast and matches any of the keys
// Input: le - the event we're testing
// Output: Returns true if the given event triggers this trigger
//------------------------------------------------------------------------------------------------------
bool CBroadcastTrigger::matches(const CLogEvent* le)
{
if (le->getType() == CLogEvent::NAMED_BROADCAST)// || le->getType() == CLogEvent::ANON_BROADCAST)
{
//broadcastID is arg0
string BroadID=le->getArgument(0)->getStringValue();
vector<string>::iterator it;
for (it=broadcastStrings.begin();it!=broadcastStrings.end();++it)
{
string s=*it;
if (BroadID==*it)
return true;
}
}
return false;
}
//------------------------------------------------------------------------------------------------------
// Function: CGoalTrigger::CGoalTrigger
// Purpose: Constructor for CGoalTrigger
// Input: value - the value of the trigger relative to other triggers
// teamValue - the teamValue of the trigger (not used)
// keys - the names of goals that will cause this trigger to trigger
//------------------------------------------------------------------------------------------------------
CGoalTrigger::CGoalTrigger(int value, int teamValue, vector<string>& keys,map<string,string> extras)
:CCustomAwardTrigger(value,teamValue,extras)
{
//this line works in win32, but not in G++... g++ doesn't seem to have vector::assign
//goalNames.assign(keys.begin(),keys.end());
//make a new temp object, and assign it to broadcastStrings
//does this introduce a memory leak?
goalNames=vector<string>(keys);
}
//------------------------------------------------------------------------------------------------------
// Function: CGoalTrigger::matches
// Purpose: Determines if a given event is a goal activation and matches any of the keys
// Input: le - the event we're testing
// Output: Returns true if the given event triggers this trigger
//------------------------------------------------------------------------------------------------------
bool CGoalTrigger::matches(const CLogEvent* le)
{
if (le->getType() == CLogEvent::NAMED_GOAL_ACTIVATE)
{
string n=le->getArgument(1)->getStringValue();
vector<string>::iterator it;
for (it=goalNames.begin();it!=goalNames.end();++it)
{
int diff=strnicmp(n.c_str(),(*it).c_str(),(*it).length());
if (diff==0)
return true;
}
}
return false;
}
//------------------------------------------------------------------------------------------------------
// Function: CFullSearchTrigger::CFullSearchTrigger
// Purpose: Constructor for CFullSearchTrigger
// Input: value - the value of the trigger relative to other triggers
// teamValue - the teamValue of the trigger (not used)
// ks - the names of FullSearchs that will cause this trigger to trigger
//------------------------------------------------------------------------------------------------------
CFullSearchTrigger::CFullSearchTrigger(int value, int teamValue, vector<string>& ks,map<string,string> extras)
:CCustomAwardTrigger(value,teamValue,extras)
{
//this line works in win32, but not in G++... g++ doesn't seem to have vector::assign
//FullSearchNames.assign(keys.begin(),keys.end());
//make a new temp object, and assign it to broadcastStrings
winnerVar=extraProps["winnervar"];
keys=vector<string>(ks);
}
bool killws(const char*& cs)
{
bool retval=false;
while(isspace(*cs))
{
retval=true;
cs++;
}
return retval;
}
#include <regex>
int regExprCompare(string sexpr,string scmp)
{
regex expression(sexpr);
cmatch what;
if(query_match(scmp.c_str(), scmp.c_str() + strlen(scmp.c_str()), what, expression))
{
//matched!
return 0;
}
else
return 1;
}
bool CFullSearchTrigger::compare(string str_msg,string str_key,map<string,string>& varmatches)
{
const char* msg=str_msg.c_str();
const char* key=str_key.c_str();
bool match=true;
char varbuf[100];
char cmpbuf[100];
while (1)
{
if (!*msg) break;
if (!*key) break;
//get a variable.
if (*key=='%')
{
int i=0;
while(*key && *key!=' ')
{
varbuf[i++]=*(key++);
}
varbuf[i]=0;
if (winnerVar=="")
winnerVar=varbuf;
killws(msg);
if (*msg=='\"')
{
msg++;
int i=0;
while (*msg && *msg!='\"')
{
cmpbuf[i++]=*msg++;
}
cmpbuf[i]=0;
msg++; //skip past last "
}
else
{
int i=0;
while (*msg!=' ')
{
cmpbuf[i++]=*msg++;
}
cmpbuf[i]=0;
}
string matchexpr=extraProps[varbuf];
if (matchexpr=="")
{
//if blank, match any quote delimited string or space delimited word
varmatches.insert(pair<string,string>(varbuf,cmpbuf));
}
else if (matchexpr.at(0)!='!' && matchexpr.at(1)!='!')
{
//do a normal string compare
if (stricmp(matchexpr.c_str(),cmpbuf)==0)
varmatches.insert(pair<string,string>(varbuf,cmpbuf));
else
return false;
}
else
{
//in tfstats, reg expressions start with !! so skip past that
const char* rexpr=matchexpr.c_str()+2;
string test=rexpr;
if (regExprCompare(rexpr,cmpbuf)==0)
varmatches.insert(pair<string,string>(varbuf,cmpbuf));
else
return false;
}
}
bool movedptr1 = killws(msg);
bool movedptr2 = killws(key);
if (!movedptr1 && !movedptr2)
{
if (!*msg) break;
if (*msg!=*key)
{
match=false;
break;
}
msg++;
key++;
}
if (!*msg) break;
}
return match;
}
//------------------------------------------------------------------------------------------------------
// Function: CFullSearchTrigger::matches
// Purpose:
// Input: le - the event we're testing
// Output: Returns true if the given event triggers this trigger
//------------------------------------------------------------------------------------------------------
bool CFullSearchTrigger::matches(const CLogEvent* le)
{
//test against full text
//clear out the state from the last match attempt
map<string,string> varmatches;
bool match=compare(le->getFullMessage(),keys[0],varmatches);
#ifdef _CUSTOMDEBUG
#ifdef _DEBUG
if (match)
{
map<string,string>::iterator it=varmatches.begin();
for (it;it!=varmatches.end();++it)
{
debug_printf("matched %s with %s\n",it->first.c_str(),it->second.c_str());
}
}
#endif
#endif
return match;
}
#include "pid.h"
PID CFullSearchTrigger::plrIDFromEvent(const CLogEvent* ple)
{
#ifdef WIN32
if (winnerVar.compare(0,5,"%plr_")==0)
#else
if (winnerVar.at(0)=='%' &&
winnerVar.at(1)=='p' &&
winnerVar.at(2)=='l' &&
winnerVar.at(3)=='r' &&
winnerVar.at(4)=='_')
#endif
{
map<string,string> varmatches;
compare(ple->getFullMessage(),keys[0],varmatches);
string name=varmatches[winnerVar];
int svrID=Util::string2svrID(name);
return pidMap[svrID];
}
else
return -1;
}
//this class does
string CFullSearchTrigger::getTrackString(const CLogEvent* ple)
{
map<string,string> varmatches;
compare(ple->getFullMessage(),keys[0],varmatches);
return varmatches[winnerVar];
}
+112
View File
@@ -0,0 +1,112 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interfaces of the CustomAwardTrigger tree. Both types of
// Custom award triggers and their base class
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef CUSTOMAWARDTRIGGERS_H
#define CUSTOMAWARDTRIGGERS_H
#ifdef WIN32
#pragma once
#endif
#pragma warning(disable :4786)
#include "TextFile.h"
#include "LogEvent.h"
#include <vector>
#include <list>
#include <map>
using std::map;
using std::list;
using std::vector;
using std::string;
//------------------------------------------------------------------------------------------------------
// Purpose: CCustomAwardTrigger is the base class for both types of award
// triggers. An award trigger is an object that recognizes a certain type of event
// in the log file, and if it matches that event, then it "triggers" and the custom
// award which owns it increments the counter for the player who triggered the
// trigger.
//------------------------------------------------------------------------------------------------------
class CCustomAwardTrigger
{
public:
static CCustomAwardTrigger* readTrigger(CTextFile& f);
int plrValue;
int teamValue;
map<string,string> extraProps;
virtual bool matches(const CLogEvent* le)=0;
virtual PID plrIDFromEvent(const CLogEvent* ple){return -1;}
virtual string getTrackString(const CLogEvent* ple){return "";}
CCustomAwardTrigger(int value, int tmVal, map<string,string> extras){plrValue=value;teamValue=tmVal;extraProps=extras;}
};
//------------------------------------------------------------------------------------------------------
// Purpose: CBroadcastTrigger scans broadcast events for matching data
//------------------------------------------------------------------------------------------------------
class CBroadcastTrigger: public CCustomAwardTrigger
{
public:
CBroadcastTrigger(int value, int teamValue, vector<string>& keys,map<string,string> extras);
vector<string> broadcastStrings;
virtual bool matches(const CLogEvent* le);
virtual PID plrIDFromEvent(const CLogEvent* ple){return ple->getArgument(1)->asPlayerGetPID();}
//this class doesn't need this function
//virtual string getTrackString(const CLogEvent* ple){return "";}
};
//------------------------------------------------------------------------------------------------------
// Purpose: CGoalTrigger scans goal activations for matching data
//------------------------------------------------------------------------------------------------------
class CGoalTrigger: public CCustomAwardTrigger
{
public:
CGoalTrigger(int value, int teamValue, vector<string>& keys,map<string,string> extras);
vector<string> goalNames;
virtual bool matches(const CLogEvent* le);
virtual PID plrIDFromEvent(const CLogEvent* ple){return ple->getArgument(0)->asPlayerGetPID();}
//this class doesn't need this function
//virtual string getTrackString(const CLogEvent* ple){return "";}
};
//------------------------------------------------------------------------------------------------------
// Purpose: CFullSearchTrigger scans FullSearch activations for matching data
//------------------------------------------------------------------------------------------------------
class CFullSearchTrigger: public CCustomAwardTrigger
{
public:
int regExpCompare(string exp,string cmp);
map<string,string> varexpressions;
CFullSearchTrigger(int value, int teamValue, vector<string>& ks,map<string,string> extras);
vector<string> keys;
string winnerVar;
bool compare(string str_msg,string str_key,map<string,string>& varmatches);
virtual bool matches(const CLogEvent* le);
virtual PID plrIDFromEvent(const CLogEvent* ple);
//this class does
virtual string getTrackString(const CLogEvent* ple);
};
#endif // CUSTOMAWARDTRIGGERS_H
+63
View File
@@ -0,0 +1,63 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CCVarList
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "cvars.h"
//------------------------------------------------------------------------------------------------------
// Function: CCVarList::writeHTML
// Purpose: generates and writes the report. generate() is not used in this object
// because there is no real intermediate data. Really data is just taken from the
// event list, massaged abit, and written out to the html file. There is no calculation
// of stats or figures so no intermedidate data creation is needed.
// Input: html - the html file that we want to write to.
//------------------------------------------------------------------------------------------------------
void CCVarList::writeHTML(CHTMLFile& html)
{
CEventListIterator it;
html.write("<table border=0 width=100%% cols=%li><tr>\n",HTML_TABLE_NUM_COLS);
bool startOfRow=true;
for (it=g_pMatchInfo->eventList()->begin(); it != g_pMatchInfo->eventList()->end(); ++it)
{
if ((*it)->getType()==CLogEvent::CVAR_ASSIGN)
{
char var[100];
char val[100];
if (!(*it)->getArgument(0) || !(*it)->getArgument(1))
return;
(*it)->getArgument(0)->getStringValue(var);
(*it)->getArgument(1)->getStringValue(val);
//mask off any passwords that the server op may not want to be displayed
if (stricmp(var,"rcon_password")==0 || stricmp(var,"sv_password")==0 || stricmp(var,"password")==0)
{
html.write("<!-- %s not shown! -->\n",var);
continue;
}
if (startOfRow)
{
html.write("</tr>\n<tr>");
startOfRow=false;
}
else
startOfRow=true;
html.write("\t<td><font class=cvar> %s = %s </font> </td>\n",var,val);
}
}
html.write("</tr></table>");
}
+39
View File
@@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CCVarList
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef CVARS_H
#define CVARS_H
#ifdef WIN32
#pragma once
#endif
#include "report.h"
//------------------------------------------------------------------------------------------------------
// Purpose: CCVarList is a report element that outputs a two column table with
// the cvars that were in effect while the match was running. Cvars that contain
// various passwords are omitted from the listing.
//------------------------------------------------------------------------------------------------------
class CCVarList :public CReport
{
private:
enum Consts
{
HTML_TABLE_WIDTH=500,
HTML_TABLE_NUM_COLS=2,
};
public:
explicit CCVarList(){}
void writeHTML(CHTMLFile& html);
};
#endif // CVARS_H
+159
View File
@@ -0,0 +1,159 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CDialogueReadout
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "DialogueReadout.h"
#include "util.h"
//------------------------------------------------------------------------------------------------------
// Function: CDialogueReadout::writeHTML
// Purpose: generates and writes the report. generate() is not used in this object
// because there is no real intermediate data. Really data is just taken from the
// event list, massaged abit, and written out to the html file. There is no calculation
// of stats or figures so no intermedidate data creation is needed.
// Input: html - the html file that we want to write to.
//------------------------------------------------------------------------------------------------------
void CDialogueReadout::writeHTML(CHTMLFile& html)
{
html.write("<img src=\"%s/game.dialog.on.gif\">\n",g_pApp->supportHTTPPath.c_str());
html.div("dialog");
CEventListIterator it;
bool MM2Messages=false;
if (g_pApp->cmdLineSwitches["displaymm2"]=="on" ||
g_pApp->cmdLineSwitches["displaymm2"]=="yes" ||
g_pApp->cmdLineSwitches["displaymm2"]=="true" ||
g_pApp->cmdLineSwitches["displaymm2"]=="1")
MM2Messages=true;
for (it=g_pMatchInfo->eventList()->begin(); it != g_pMatchInfo->eventList()->end(); ++it)
{
if ((*it)->getType()==CLogEvent::SAY || (MM2Messages && ((*it)->getType()==CLogEvent::SAY_TEAM)))
{
char talked[512]={0};
PID talkerPID=(*it)->getArgument(0)->asPlayerGetPID();
string talkerName=(*it)->getArgument(0)->asPlayerGetName();
for (int i=1;(*it)->getArgument(i);i++)
{
char temp[512];
(*it)->getArgument(i)->getStringValue(temp);
strcat(talked,"\"");
strcat(talked,temp);
strcat(talked,"\"");
}
bool isTeamMsg= (*it)->getType()==CLogEvent::SAY_TEAM;
int teamID=g_pMatchInfo->playerList()[talkerPID].teams.atTime((*it)->getTime());
const char* aa;
const char* bb;
if (teamID<4 && teamID >= 0)
{
aa="player";
bb=Util::teamcolormap[teamID];
}
else
{
aa="whitetext";
bb="";
}
html.write("<tr><td><font class=%s%s>%s%s:</font><font color=white> %s</font></tr></td>\n",aa,bb,talkerName.c_str(),isTeamMsg?" (Team)":"",talked);
html.br();
}
else if ( (*it)->getType()==CLogEvent::KILLED_BY_WORLD)
{
PID plr=(*it)->getArgument(0)->asPlayerGetPID();
string plrName=(*it)->getArgument(0)->asPlayerGetName();
int teamID=g_pMatchInfo->playerList()[plr].teams.atTime((*it)->getTime());
html.write("<tr><td><font class=player%s>%s</font><font color=white> died.</font></tr></td>\n",Util::teamcolormap[teamID],plrName.c_str());
html.br();
}
else if ((*it)->getType()==CLogEvent::SUICIDE)
{
PID plr=(*it)->getArgument(0)->asPlayerGetPID();
string plrName=(*it)->getArgument(0)->asPlayerGetName();
int teamID=g_pMatchInfo->playerList()[plr].teams.atTime((*it)->getTime());
html.write("<tr><td><font class=player%s>%s</font><font color=white> committed suicide.</font></tr></td>\n",Util::teamcolormap[teamID],plrName.c_str());
html.br();
}
else if ((*it)->getType()==CLogEvent::TEAM_JOIN)
{
PID plr=(*it)->getArgument(0)->asPlayerGetPID();
string plrName=(*it)->getArgument(0)->asPlayerGetName();
time_t eventtime=(*it)->getTime();
bool firstJoin=!g_pMatchInfo->playerList()[plr].teams.anythingAtTime(eventtime-1);
int oldTeamID=g_pMatchInfo->playerList()[plr].teams.atTime(eventtime-1);
int teamID=g_pMatchInfo->playerList()[plr].teams.atTime(eventtime);
string teamName=g_pMatchInfo->teamName(teamID);
if (firstJoin)
html.write("<tr><td><font class=player%s>%s</font><font color=white> joined team <font class=player%s>%s</font>.</font></tr></td>\n",Util::teamcolormap[teamID],plrName.c_str(),Util::teamcolormap[teamID],teamName.c_str());
else
html.write("<tr><td><font class=player%s>%s</font><font color=white> changed teams to <font class=player%s>%s</font>.</font></tr></td>\n",Util::teamcolormap[oldTeamID],plrName.c_str(),Util::teamcolormap[teamID],teamName.c_str());
html.br();
}
else if ((*it)->getType()==CLogEvent::FRAG)
{
PID killer=(*it)->getArgument(0)->asPlayerGetPID();
string killerName=(*it)->getArgument(0)->asPlayerGetName();
PID killee=(*it)->getArgument(1)->asPlayerGetPID();
string killeeName=(*it)->getArgument(1)->asPlayerGetName();
string weaponName = (*it)->getArgument(2)->getStringValue();
int killerTeamID=g_pMatchInfo->playerList()[killer].teams.atTime((*it)->getTime());
int killeeTeamID=g_pMatchInfo->playerList()[killee].teams.atTime((*it)->getTime());
bool countKill=true;
//gotta account for timer/infection double kills for medics!
if (weaponName=="infection")
{
//test to see if the previous event was a timer from the same player, and a kill, and with the timer.
CEventListIterator it2=it;
if ((--it2)!=g_pMatchInfo->eventList()->begin())
{
if ((*it2)->getType() == CLogEvent::FRAG)
if ((*it2)->getArgument(2)->getStringValue()=="timer")
if ((*it2)->getArgument(0)->asPlayerGetPID()==killer)
countKill=false;
}
}
if (countKill)
{
html.write("<tr><td><font class=player%s>%s</font><font color=white> killed </font><font class=player%s>%s</font><font color=white> with %s. </font></tr></td>\n",
Util::teamcolormap[killerTeamID],killerName.c_str(),Util::teamcolormap[killeeTeamID],killeeName.c_str(),weaponName.c_str());
html.br();
}
}
else if ((*it)->getType()==CLogEvent::TEAM_FRAG)
{
PID killer=(*it)->getArgument(0)->asPlayerGetPID();
string killerName=(*it)->getArgument(0)->asPlayerGetName();
PID killee=(*it)->getArgument(1)->asPlayerGetPID();
string killeeName=(*it)->getArgument(1)->asPlayerGetName();
int killerTeamID=g_pMatchInfo->playerList()[killer].teams.atTime((*it)->getTime());
int killeeTeamID=g_pMatchInfo->playerList()[killee].teams.atTime((*it)->getTime());
html.write("<tr><td><font class=player%s>%s</font><font color=white> teamkilled </font><font class=player%s>%s.</font></tr></td>\n",
Util::teamcolormap[killerTeamID],killerName.c_str(),Util::teamcolormap[killeeTeamID],killeeName.c_str());
html.br();
}
}
html.enddiv();
}
+32
View File
@@ -0,0 +1,32 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CDialogueReadout
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef DIALOGUEREADOUT_H
#define DIALOGUEREADOUT_H
#ifdef WIN32
#pragma once
#endif
#include "Report.h"
//------------------------------------------------------------------------------------------------------
// Purpose: CDialogueReadout is a full page report element that outputs a listing
// of all the dialogue in the match. It also reports deaths, and suicides since those
// usually beget lots of smack talking.
//------------------------------------------------------------------------------------------------------
class CDialogueReadout : public CReport
{
private:
public:
explicit CDialogueReadout(){}
void writeHTML(CHTMLFile& html);
};
#endif // DIALOGUEREADOUT_H
+61
View File
@@ -0,0 +1,61 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CEventList
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include <stdlib.h>
#include "TFStatsApplication.h"
#include "EventList.h"
#include "memdbg.h"
#pragma warning (disable : 4786)
//------------------------------------------------------------------------------------------------------
// Function: CEventList::readEventList
// Purpose: reads and returns a CEventList from a logfile
// Input: filename - the logfile to read from
// Output: CEventList*
//------------------------------------------------------------------------------------------------------
CEventList* CEventList::readEventList(const char* filename)
{
// ifstream ifs(filename);
CEventList* plogfile=new TRACKED CEventList();
if (!plogfile)
{
printf("TFStats ran out of memory!\n");
return NULL;
}
FILE* f=fopen(filename,"rt");
if (!f)
g_pApp->fatalError("Error opening %s, please make sure that the file exists and is not being accessed by other processes",filename);
while (!feof(f))
{
CLogEvent* curr=NULL;
curr=new TRACKED CLogEvent(f);
if (!curr->isValid())
{
delete curr;
break;//eof reached
}
plogfile->insert(plogfile->end(),curr);
}
fclose(f);
#ifndef WIN32
chmod(filename,PERMIT);
#endif
return plogfile;
}
+58
View File
@@ -0,0 +1,58 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CEventList
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef EVENTLIST_H
#define EVENTLIST_H
#ifdef WIN32
#pragma once
#endif
#pragma warning(disable :4786)
#include <list>
#include <map>
#include "LogEvent.h"
#include "util.h"
typedef std::list<const CLogEvent*> event_list;
typedef std::list<const CLogEvent*>::iterator CEventListIterator;
using namespace std;
#include <cstring>
#include <string>
//------------------------------------------------------------------------------------------------------
// Purpose: CEventList is just a thin wrapper around a list of CLogEvent objects
// It also provides a factory method to read and return a CEventList from a
// log file
//------------------------------------------------------------------------------------------------------
class CEventList
{
public:
static CEventList* readEventList(const char* filename);
void insert(CEventListIterator cli, const CLogEvent* cle){m_List.insert(cli,cle);}
CEventListIterator begin(){return m_List.begin();}
CEventListIterator end(){return m_List.end();}
bool empty(){return m_List.empty();}
private:
event_list m_List;
};
#endif // EVENTLIST_H
+131
View File
@@ -0,0 +1,131 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CHTMLFile. see HTML.h for details
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#pragma warning (disable:4786)
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string>
#include "TFStatsApplication.h"
#include "util.h"
#include "html.h"
//readability aids used when calling constructor
const bool CHTMLFile::printBody=true;
const bool CHTMLFile::dontPrintBody=false;
const bool CHTMLFile::linkStyle=true;
const bool CHTMLFile::dontLinkStyle=false;
using namespace std;
//------------------------------------------------------------------------------------------------------
// Function: CHTMLFile::CHTMLFile
// Purpose:
// Input: filename - name of the html file that will be written
// title - title of the html document
// fPrintBody - true if the <body> tag is to be written.
// bgimage - name of a background image, if desired
// leftmarg - pixels on the left margin (if desired)
// topmarg - pixels on the top margin (if desired)
//------------------------------------------------------------------------------------------------------
CHTMLFile::CHTMLFile(const char* filenm,const char* title,bool fPrintBody,const char* bgimage,int leftmarg, int topmarg)
{
strcpy(filename,filenm);
open(filename);
write("<HEAD>\n");
write("<TITLE> %s </TITLE>\n",title);
string csshttppath(g_pApp->supportHTTPPath);
csshttppath+="/style.css";
write("<link rel=\"stylesheet\" href=\"%s\" type=\"text/css\">\n",csshttppath.c_str());
write("</HEAD>\n");
fBody=fPrintBody;
if (fBody)
{
write("<BODY leftmargin=%li topmargin=%li ",leftmarg,topmarg);
if (bgimage)
write("background=%s",bgimage);
else
write("bgcolor = black");
write(">\n");
}
}
//------------------------------------------------------------------------------------------------------
// Function: CHTMLFile::open
// Purpose: opens the html file, and writes <html>
// Input: filename - the name of the file to open
//------------------------------------------------------------------------------------------------------
void CHTMLFile::open(const char* filename)
{
out=fopen(filename,"wt");
if (!out)
g_pApp->fatalError("Can't open output file \"%s\"!\nPlease make sure that the file does not exist OR\nif the file does exit, make sure it is not read-only",filename);
write("<HTML>\n");
}
//------------------------------------------------------------------------------------------------------
// Function: CHTMLFile::write
// Purpose: writes a string to the html file
// Input: fmt - format string, like printf suite of functions
// ... - list of arguments
//------------------------------------------------------------------------------------------------------
void CHTMLFile::write(const char* fmt,...)
{
va_list va;
va_start(va,fmt);
vfprintf(out,fmt,va);
}
//------------------------------------------------------------------------------------------------------
// Function: CHTMLFile::close
// Purpose: closes the html file, closing <body> and <html> tags if needed
//------------------------------------------------------------------------------------------------------
void CHTMLFile::close()
{
if (!out)
return;
if (fBody)
write("</BODY>\n");
write("</HTML>\n\n");
#ifndef WIN32
chmod(filename,PERMIT);
#endif
fclose(out);
out=NULL;
}
//------------------------------------------------------------------------------------------------------
// Function: CHTMLFile::~CHTMLFile
// Purpose: Destructor. closes the file
//------------------------------------------------------------------------------------------------------
CHTMLFile::~CHTMLFile()
{
close();
}
void CHTMLFile::hr(int len,bool alignleft)
{
write("<hr %s width=%li>\n",alignleft?"align=left":"",len);
}
+59
View File
@@ -0,0 +1,59 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CHTMLFile.
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef HTML_H
#define HTML_H
#ifdef WIN32
#pragma once
#endif
#include <stdio.h>
//------------------------------------------------------------------------------------------------------
// Purpose: CHTMLFile represents an HTML text file that is being created. It has
// some misc helper stuff, like writing the body tag for you, and linking to the style
// sheet. Also some little helper functions to do <br>s and <p>s
//------------------------------------------------------------------------------------------------------
class CHTMLFile
{
public:
static const bool printBody;
static const bool dontPrintBody;
static const bool linkStyle;
static const bool dontLinkStyle;
private:
FILE* out;
char filename[100];
bool fBody;
public:
CHTMLFile():out(NULL),fBody(false){}
CHTMLFile(const char*filenm ,const char* title,bool fPrintBody=true,const char* bgimage=NULL,int leftmarg=0,int topmarg=20);
void open(const char*);
void write(PRINTF_FORMAT_STRING const char*,...);
void hr(int len=0,bool alignleft=false);
void br(){write("<br>\n");}
void p(){write("<p>\n");};
void img(const char* i){write("<img src=%s>\n",i);}
void div(const char* cls){write("<div class=%s>\n",cls);}
void div(){write("<div>\n");}
void enddiv(){write("</div>");}
void close();
~CHTMLFile();
};
#endif // HTML_H
+66
View File
@@ -0,0 +1,66 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CKamikazeAward
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "KamikazeAward.h"
//------------------------------------------------------------------------------------------------------
// Function: CKamikazeAward::getWinner
// Purpose: determines the winner of the award
//------------------------------------------------------------------------------------------------------
void CKamikazeAward::getWinner()
{
CEventListIterator it;
for (it=g_pMatchInfo->eventList()->begin(); it != g_pMatchInfo->eventList()->end(); ++it)
{
if ((*it)->getType()==CLogEvent::SUICIDE || (*it)->getType()==CLogEvent::KILLED_BY_WORLD)
{
PID kami=(*it)->getArgument(0)->asPlayerGetPID();
numdeaths[kami]++;
winnerID=kami;
fNoWinner=false;
}
}
map<PID,int>::iterator kamiter;
for (kamiter=numdeaths.begin();kamiter!=numdeaths.end();++kamiter)
{
int currID=(*kamiter).first;
if (numdeaths[currID]>numdeaths[winnerID])
winnerID=currID;
}
}
//------------------------------------------------------------------------------------------------------
// Function: CKamikazeAward::noWinner
// Purpose: writes html indicating that no one won this award
// Input: html - the html file to write to
//------------------------------------------------------------------------------------------------------
void CKamikazeAward::noWinner(CHTMLFile& html)
{
html.write("No one killed themselves during this match! Good work!");
}
//------------------------------------------------------------------------------------------------------
// Function: CKamikazeAward::extendedinfo
// Purpose: reports how many times the winner killed him/herself
// Input: html - the html file to write to
//------------------------------------------------------------------------------------------------------
void CKamikazeAward::extendedinfo(CHTMLFile& html)
{
if (numdeaths[winnerID]==1)
html.write("%s suicided once.",winnerName.c_str());
else
html.write("%s was self-victimized %li times.",winnerName.c_str(),numdeaths[winnerID]);
}
+36
View File
@@ -0,0 +1,36 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CKamikazeAward
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef KAMIKAZEAWARD_H
#define KAMIKAZEAWARD_H
#ifdef WIN32
#pragma once
#endif
#include "Award.h"
#include <map>
using namespace std;
//------------------------------------------------------------------------------------------------------
// Purpose: CKamikazeAward is an award given to the player who kills him/herself
// the most often.
//------------------------------------------------------------------------------------------------------
class CKamikazeAward: public CAward
{
protected:
map<PID,int> numdeaths;
void noWinner(CHTMLFile& html);
void extendedinfo(CHTMLFile& html);
public:
explicit CKamikazeAward():CAward("Kamikaze"){}
void getWinner();
};
#endif // KAMIKAZEAWARD_H
+391
View File
@@ -0,0 +1,391 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CLogEvent
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "LogEvent.h"
#include "util.h"
#include "memdbg.h"
//For debugging more than anything
const char* CLogEvent::TypeNames[]=
{
{"No Type/Invalid!"},
{"Log File Initialize"},
{"Server Spawn"},
{"Server Shutdown"},
{"Log Closed"},
{"Server Misc"},
{"Server Name"},
{"Team Rename"},
{"Level Change"},
{"Cvar Assignment"},
{"Map CRC"},
{"Team Join"},
{"Connect"},
{"Enter game"},
{"Disconnect"},
{"Name Change"},
{"Frag!"},
{"Team frag!"},
{"Suicide!"},
{"Killed by world!"},
{"Build"},
{"Match Results Marker"},
{"Match Draw"},
{"Match Victor"},
{"Match Team Results"},
{"Talk"},
{"Team Talk"},
{"Cure"},
{"Named Goal Activated"},
{"Anon Goal Activated"},
{"Named Broadcast"},
{"Anon Broadcast"},
{"Change Class"},
};
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::getArgument
// Purpose: returns the iWhichArg'th argument
// Input: iWhichArg - the desired argument
// Output: const CLogEventArgument*
//------------------------------------------------------------------------------------------------------
const CLogEventArgument* CLogEvent::getArgument(int iWhichArg) const
{
if (iWhichArg < m_args.size())
return m_args[iWhichArg];
else
return NULL;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::parseArgs
// Purpose: extracts the arguments out of the event text.
//------------------------------------------------------------------------------------------------------
void CLogEvent::parseArgs()
{
char temp[512];
char* write=temp;
const char* read=m_EventMessage;
int i=0;
while (*read)
{
if (*read == '\"')
{
//parseArgument moves the read pointer to the char after the closing "
parseArgument(++read);
*(write++)='[';
*(write++)=(char)(i++)+48; //convert int to char by adding 48
*(write++)=']';
}
else
*write++=*read;
*read++;
}
*write=0;
Util::str2lowercase(temp,temp);
m_StrippedText=new TRACKED char[strlen(temp)+1];
strcpy(m_StrippedText,temp);
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::parseArgument
// Purpose: helper function for parseArgs, this actually removes the argument
// Input: raw - the string from which we want to remove the argument
//------------------------------------------------------------------------------------------------------
void CLogEvent::parseArgument(const char*& raw)
{
char* atemp;
if (!(atemp=strchr(raw,'\"')))
return;
*atemp=0; //null out the closing "
CLogEventArgument* newarg=new CLogEventArgument(raw);
newarg->init(raw);
m_args.push_back(newarg);
*atemp='\"'; //restore it.
raw=atemp; //advance the pointer
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::keywordsOccur
// Purpose: tests to see if all of the given keywords occur in the text for this event
// Input: s1 - first keyword (required)
// s2 - second keyword (optional)
// s3 - third keyword (optional)
// Output: Returns true if the event text contains all of the keywords passed in
//------------------------------------------------------------------------------------------------------
bool CLogEvent::keywordsOccur(char* s1,char* s2,char* s3)
{
bool result=(strstr(m_StrippedText,s1)!=NULL);
if (s2)
{
result = result && (strstr(m_StrippedText,s2)!=NULL);
if (s3)
{
result = result && (strstr(m_StrippedText,s3)!=NULL);
}
}
return result;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::determineType
// Purpose: this is a big dumb if statement to determine the type of this event
//------------------------------------------------------------------------------------------------------
//this is pretty cheesy
void CLogEvent::determineType()
{
//for now just do this in a big dumb if statement
if (keywordsOccur("killed","self","with"))
m_EventType=SUICIDE;
else if (keywordsOccur("log closed"))
m_EventType=LOG_CLOSED;
else if (keywordsOccur("server name is"))
m_EventType=SERVER_NAME;
else if (keywordsOccur("team name of"))
m_EventType=TEAM_RENAME;
else if (keywordsOccur("killed","by","world"))
m_EventType=KILLED_BY_WORLD;
else if (keywordsOccur("killed","(teammate)"))
m_EventType=TEAM_FRAG;
else if (keywordsOccur("killed","with"))
m_EventType=FRAG;
else if (keywordsOccur("say_team"))
m_EventType=SAY_TEAM;
else if (keywordsOccur("say"))
m_EventType=SAY;
else if (keywordsOccur("joined team"))
m_EventType=TEAM_JOIN;
else if (keywordsOccur("changed to team"))
m_EventType=TEAM_JOIN;
else if (keywordsOccur("log file started"))
m_EventType=LOG_FILE_INIT;
else if (keywordsOccur("spawning server"))
m_EventType=SERVER_SPAWN;
else if (keywordsOccur("connected","address"))
m_EventType=CONNECT;
else if (keywordsOccur("has entered the game"))
m_EventType=ENTER_GAME;
else if (keywordsOccur("disconnected"))
m_EventType=DISCONNECT;
else if (keywordsOccur("changed name to"))
m_EventType=NAME_CHANGE;
else if (keywordsOccur("built"))
m_EventType=BUILD;
else if (keywordsOccur("map crc"))
m_EventType=MAP_CRC;
else if (keywordsOccur("match","results","=------="))
m_EventType=MATCH_RESULTS_MARKER;
else if (keywordsOccur("activated the goal"))
m_EventType=NAMED_GOAL_ACTIVATE;
else if (keywordsOccur("goal", "was activated"))
m_EventType=ANON_GOAL_ACTIVATE;
else if (keywordsOccur("named broadcast"))
m_EventType=NAMED_BROADCAST;
else if (keywordsOccur("broadcast"))
m_EventType=ANON_BROADCAST;
else if (keywordsOccur("changed class"))
m_EventType=CLASS_CHANGE;
else if (keywordsOccur("-> draw <-"))
m_EventType=MATCH_DRAW;
else if (keywordsOccur("defeated"))
m_EventType=MATCH_VICTOR;
else if (keywordsOccur("results"))
m_EventType=MATCH_TEAM_RESULTS;
else if (keywordsOccur("="))
m_EventType=CVAR_ASSIGN;
else m_EventType=SERVER_MISC;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::CLogEvent
// Purpose: CLogEvent constructor
//------------------------------------------------------------------------------------------------------
CLogEvent::CLogEvent()
:m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID),m_EventMessage(NULL)
{}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::~CLogEvent
// Purpose: CLogEvent destructor
//------------------------------------------------------------------------------------------------------
CLogEvent::~CLogEvent()
{
//this errors?!
if (m_EventMessage)
delete[] m_EventMessage;
if (m_StrippedText)
delete[] m_StrippedText;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::print
// Purpose: debugging function, prints this event to a file
// Input: f - the file to print to
//------------------------------------------------------------------------------------------------------
void CLogEvent::print(FILE* f)
{
fprintf(f,"(%li) Event: %s\n",m_EventTime,m_EventMessage);
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::CLogEvent
// Purpose: CLogEvent constructor that reads an event from the specified file
// Input: f - the file to read from
//------------------------------------------------------------------------------------------------------
CLogEvent::CLogEvent(FILE* f)
:m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID),m_EventMessage(NULL)
{
readEvent(f);
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::readEvent
// Purpose: reads an event by reading each part, then checking if it was successful
// Input: f - the file to read from
//------------------------------------------------------------------------------------------------------
void CLogEvent::readEvent(FILE* f)
{
m_Valid=true;
if (m_Valid) readEventCode(f);
if (m_Valid) readEventTime(f);
if (m_Valid) readEventMessage(f);
if (m_Valid) parseArgs();
if (m_Valid) determineType();
if (m_Valid) m_Valid=!feof(f);
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::readEventCode
// Purpose: reads the event code, the first character on the line (should be 'L')
// Input: f - the file to read from
//------------------------------------------------------------------------------------------------------
void CLogEvent::readEventCode(FILE* f)
{
fscanf(f," %c ",&m_EventCode);
if (m_EventCode!='L')
m_Valid=false;
if (feof(f))
m_Valid=false;
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::readEventMessage
// Purpose: reads the text of the event message.
// Input: f - the file to read from
//------------------------------------------------------------------------------------------------------
void CLogEvent::readEventMessage(FILE* f)
{
char temp[512];
fgets(temp,512,f);
//special case hack for broadcasts
if (strncmp(temp,"Named Broadcast:",16)==0 || strncmp(temp,"Broadcast:",16)==0)
{
while(1)
{
fpos_t temp_pos;
fgetpos(f,&temp_pos);
CLogEvent cle(f);
fseek(f,temp_pos,SEEK_SET);
if (cle.isValid())
{
//if the next log event is valid, then this broadcast did not span lines
break;
}
else
{
temp[strlen(temp)-1]=' '; //rid ourselves of newline
temp[strlen(temp)]=0; //rid ourselves of newline
char buf[512];
fgets(buf,512,f);
strcat(temp,buf);
}
}
}
if (feof(f))
{
m_Valid=false;
}
else
{
temp[strlen(temp)-1]=0; //rid ourselves of newline
m_EventMessage=new TRACKED char[strlen(temp)+1];
strcpy(m_EventMessage,temp);
}
}
//------------------------------------------------------------------------------------------------------
// Function: CLogEvent::readEventTime
// Purpose: reads and converts the time the event happened into a time_t
// Input: f - the file to read from
//------------------------------------------------------------------------------------------------------
void CLogEvent::readEventTime(FILE* f)
{
int month=-1,day=-1,year=-1;
int hour=-1,minute=-1,second=-1;
fscanf(f," %d/%d/%d - %d:%d:%d: ",&month,&day,&year,&hour,&minute,&second);
if (month==-1 ||day==-1 ||year==-1 || hour==-1 || minute==-1 || second==-1)
m_Valid=false;
else if (feof(f))
m_Valid=false;
else
{
tm t;
t.tm_isdst=0;
t.tm_hour=hour;
t.tm_mday=day;
t.tm_min=minute;
t.tm_sec=second;
t.tm_year=year-1900; //note no y2k prob here, so says the CRT manual
//this allows values greater than 99, but it
//just wants the input with 1900 subtracted.
t.tm_mon=month-1; //jan = 0
m_EventTime=mktime(&t);
}
}
+144
View File
@@ -0,0 +1,144 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CLogEvent
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef LOGEVENT_H
#define LOGEVENT_H
#ifdef WIN32
#pragma once
#endif
#pragma warning(disable :4786)
#include "Argument.h"
#ifdef WIN32
//#include <strstrea.h>
#else
//#include <strstream.h>
#endif
#include <time.h>
//#include <iostream.h>
#include <stdio.h>
//------------------------------------------------------------------------------------------------------
// Purpose: CLogEvent represents an event in the log file. e.g. one line.
// It can have one of several types (enumerated below) and a list of arguments
// is attached as well.
//------------------------------------------------------------------------------------------------------
class CLogEvent
{
public:
enum Type
{
NOTYPE =0,
INVALID = 0,
LOG_FILE_INIT,
SERVER_SPAWN,
SERVER_SHUTDOWN,
LOG_CLOSED,
SERVER_MISC,
SERVER_NAME,
TEAM_RENAME,
LEVEL_CHANGE,
CVAR_ASSIGN,
MAP_CRC,
TEAM_JOIN,
CONNECT,
ENTER_GAME,
DISCONNECT,
NAME_CHANGE,
FRAG,
TEAM_FRAG,
SUICIDE,
KILLED_BY_WORLD,
BUILD,
MATCH_RESULTS_MARKER,
MATCH_DRAW,
MATCH_VICTOR,
MATCH_TEAM_RESULTS,
SAY,
SAY_TEAM,
CURE,
NAMED_GOAL_ACTIVATE,
ANON_GOAL_ACTIVATE,
NAMED_BROADCAST,
ANON_BROADCAST,
CLASS_CHANGE,
NUM_TYPES
};
char* m_StrippedText;
private:
ArgVector m_args;
char m_EventCode;
time_t m_EventTime;
bool m_Valid;
char* m_EventMessage;
Type m_EventType;
bool keywordsOccur(char* s1,char* s2=NULL,char* s3=NULL);
void parseArgs();
// void readEventTime(istream& is);
// void readEventCode(istream& is);
// void readEventMessage(istream& is);
void parseArgument(const char*& raw); //ref to pointer to constant char, gotta love it.
void determineType();
public:
CLogEvent* m_Next;
CLogEvent();
~CLogEvent();
bool isValid(){return m_Valid;}
// explicit CLogEvent(istream& is);
// virtual void readEvent(istream& is);
// virtual void print(ostream& os);
CLogEvent::Type getType() const {return m_EventType;}
time_t getTime() const {return m_EventTime;}
const CLogEventArgument* getArgument(int i) const;
const char* getFullMessage() const {return m_EventMessage;}
static const char* TypeNames[];
//unused stuff
protected:
void readEventTime(FILE* f);
void readEventCode(FILE* f);
void readEventMessage(FILE* f);
public:
explicit CLogEvent(FILE* f);
virtual void readEvent(FILE* f);
virtual void print(FILE* f=stdout);
};
#endif // LOGEVENT_H
+116
View File
@@ -0,0 +1,116 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if 0
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Implementation of CLogEvent's C++ IO Stream stuff. this isn't used currently
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "LogEvent.h"
#include <string.h>
//none of this is used. I opted for the FILE* implementation instead, this one was giving some weird results, and not working right.
CLogEvent::CLogEvent(istream& is)
:m_EventCode('\0'),m_EventTime(0),m_Valid(false),m_Next(NULL),m_StrippedText(NULL),m_EventType(INVALID)
{
readEvent(is);
}
void CLogEvent::print(ostream& os)
{
os << "(" <<m_EventTime<<") Event Type: "<<TypeNames[m_EventType]<<endl;
os << "Args: ";
for(int i=0;i<m_args.size();i++)
cout<< "\t"<<m_args[i]->getStringValue()<<endl;
}
void CLogEvent::readEvent(istream& is)
{
readEventCode(is);
readEventTime(is);
readEventMessage(is);
determineType();
if(is)
m_Valid=true;
else
m_Valid=false;
}
//note this function assumes you're at the start of a line
void CLogEvent::readEventCode(istream& is)
{
is>>m_EventCode;
}
void CLogEvent::readEventMessage(istream& is)
{
char temp[512]={0,0,0,0};
is.getline(temp,512,'\n');
m_EventMessage=new char[strlen(temp)];
strcpy(m_EventMessage,temp);
}
void CLogEvent::readEventTime(istream& is)
{
int month,day,year;
int hour,minute,second;
// fscanf(f," %i/%i/%i - %i:%i:%i: ",&month,&day,&year,&hour,&minute,&second);
is >> month;
is.ignore(); //'/'
is >> day;
is.ignore(); //'/'
is >> year;
is.ignore(3); //' - '
is >> hour;
is.ignore(); //':'
is >> minute;
is.ignore(); //':'
is >> second;
is.ignore(); //':'
tm t;
t.tm_isdst=0;
t.tm_hour=hour;
t.tm_mday=day;
t.tm_min=minute;
t.tm_sec=second;
t.tm_year=year-1900; //note no y2k prob here, so says the CRT manual
//this allows values greater than 99, but it
//just wants the input with 1900 subtracted.
t.tm_mon=month;
m_EventTime=mktime(&t);
}
#endif
+38
View File
@@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: dummy main.cpp
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "TFStatsApplication.h"
//------------------------------------------------------------------------------------------------------
// Function: main
// Purpose: dummy main. passes off execution to TFstats main
// Input: argc - argument count
// argv[] - argument list
//------------------------------------------------------------------------------------------------------
void main(int argc, const char* argv[])
{
//make OS application object, and operating system interface
g_pApp=new CTFStatsApplication;
g_pApp->majorVer=1;
g_pApp->minorVer=5;
#ifdef WIN32
g_pApp->os=new CTFStatsWin32Interface();
#else
g_pApp->os=new CTFStatsLinuxInterface();
#endif
//hand off execution to real main
g_pApp->main(argc,argv);
}
+251
View File
@@ -0,0 +1,251 @@
#
# TF Stats Makefile for Linux 2.0
#
# Jul '99 by Mike Harrington <mike@valvesoftware.com>
# (modified by Wes Cumberland <wesc@valvesoftware.com>)
#
#
VERSION=1.0.0.0
VERSION_FN=$(VERSION)$(GLIBC)
RPM_RELEASE=0
ifneq (,$(findstring libc6,$(shell if [ -e /lib/libc.so.6* ];then echo libc6;fi)))
GLIBC=-glibc
else
GLIBC=
endif
ifneq (,$(findstring alpha,$(shell uname -m)))
ARCH=axp
RPMARCH=alpha
else
ARCH=i386
RPMARCH=i386
endif
MOUNT_DIR=/momma
BUILD_DEBUG_DIR=$(MOUNT_DIR)/tfstats/debug
BUILD_RELEASE_DIR=$(MOUNT_DIR)/tfstats/release
TFSTATS_DIR=$(MOUNT_DIR)/tfstats
CC=/usr/bin/g++
STDCPP_INC= #/usr/local/lib/gcc-lib/H-libstdc++/include/g++-v3
STDCPP_LIB= #/usr/local/lib/gcc-lib/H-libstdc++/lib
BASE_CFLAGS=-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -Iregexp/include
RELEASE_CFLAGS=$(BASE_CFLAGS) -m486 -O1
RELEASE_NOOP_CFLAGS=$(BASE_CFLAGS) -m486
DEBUG_CFLAGS=$(BASE_CFLAGS) -g -D_DEBUG -DDEBUG -Wall
LDFLAGS= -static /momma/tfstats/regexp/lib/libregex++.a -ldl -lm \
-lstdc++
AR=ar
RANLIB=ranlib
DO_CC_NOOPT=$(CC) -DNO_NAMESPACE -D_WONCRYPT_NOEXCEPTIONS -w $(CFLAGS_NOOPT) -o $@ -c $<
DO_CC=$(CC) -DNO_NAMESPACE -D_WONCRYPT_NOEXCEPTIONS -w $(CFLAGS) -o $@ -c $<
DO_W_CC=$(CC) -DNO_NAMESPACE -D_WONCRYPT_NOEXCEPTIONS $(CFLAGS) -Wall -o $@ -c $<
DO_CRYPT_CC=$(CC) -x c++ -DNO_NAMESPACE -D_WONCRYPT_NOEXCEPTIONS $(CFLAGS) -I$(WON_INC) -o $@ -c $<
#############################################################################
# SETUP AND BUILD
#############################################################################
default: build_debug
TARGETS=\
$(BUILDDIR)/tfstats_l
make_build_dir:
for x in $(BUILDDIR) \
$(BUILDDIR)/tfstats ; do \
if [ ! -d $$x ];then mkdir $$x;fi;done
build_debug:
$(MAKE) targets BUILDDIR=$(BUILD_DEBUG_DIR) CFLAGS="$(DEBUG_CFLAGS)" CFLAGS_NOOPT="$(DEBUG_CFLAGS)"
build_release:
$(MAKE) targets BUILDDIR=$(BUILD_RELEASE_DIR) CFLAGS="$(RELEASE_CFLAGS)" CFLAGS_NOOPT="$(RELEASE_NOOP_CFLAGS)"
all: build_debug build_release
targets: $(TARGETS)
clean:
rm -f $(BUILD_DEBUG_DIR)/*.o
#############################################################################
# TF Stats Program
#############################################################################
TFSTATS_OBJS = \
$(BUILDDIR)/Argument.o \
$(BUILDDIR)/EventList.o \
$(BUILDDIR)/LogEvent.o \
$(BUILDDIR)/LogEventIOStreams.o \
$(BUILDDIR)/CureAward.o \
$(BUILDDIR)/KamikazeAward.o \
$(BUILDDIR)/SentryRebuildAward.o \
$(BUILDDIR)/SharpshooterAward.o \
$(BUILDDIR)/SurvivalistAward.o \
$(BUILDDIR)/TalkativeAward.o \
$(BUILDDIR)/TeamKillAward.o \
$(BUILDDIR)/WeaponAwards.o \
$(BUILDDIR)/CustomAward.o \
$(BUILDDIR)/CustomAwardList.o \
$(BUILDDIR)/CustomAwardTriggers.o \
$(BUILDDIR)/Award.o \
$(BUILDDIR)/CVars.o \
$(BUILDDIR)/DialogueReadout.o \
$(BUILDDIR)/MatchResults.o \
$(BUILDDIR)/scoreboard.o \
$(BUILDDIR)/WhoKilledWho.o \
$(BUILDDIR)/Report.o \
$(BUILDDIR)/HTML.o \
$(BUILDDIR)/main.o \
$(BUILDDIR)/TextFile.o \
$(BUILDDIR)/util.o \
$(BUILDDIR)/PlayerSpecifics.o \
$(BUILDDIR)/StaticOutputFiles.o \
$(BUILDDIR)/TFStatsReport.o \
$(BUILDDIR)/Player.o \
$(BUILDDIR)/MatchInfo.o \
$(BUILDDIR)/memdbg.o \
$(BUILDDIR)/pid.o \
$(BUILDDIR)/binresources.o \
$(BUILDDIR)/tfstatsapplication.o \
$(BUILDDIR)/plrpersist.o \
$(BUILDDIR)/tfstatsosinterface.o \
$(BUILDDIR)/allplayersstats.o \
$(BUILDDIR)/playerreport.o
$(BUILDDIR)/tfstats_l : $(TFSTATS_OBJS)
$(CC) $(CFLAGS) -L/usr/local/lib -o $@ $(TFSTATS_OBJS) $(LDFLAGS)
$(BUILDDIR)/buildnum.o : $(TFSTATS_DIR)/buildnum.cpp
$(DO_CC)
$(BUILDDIR)/Argument.o : $(TFSTATS_DIR)/Argument.cpp
$(DO_CC)
$(BUILDDIR)/EventList.o : $(TFSTATS_DIR)/EventList.cpp
$(DO_CC)
$(BUILDDIR)/LogEvent.o : $(TFSTATS_DIR)/LogEvent.cpp
$(DO_CC)
$(BUILDDIR)/Player.o : $(TFSTATS_DIR)/Player.cpp
$(DO_CC)
$(BUILDDIR)/MatchInfo.o : $(TFSTATS_DIR)/MatchInfo.cpp
$(DO_CC)
$(BUILDDIR)/LogEventIOStreams.o : $(TFSTATS_DIR)/LogEventIOStreams.cpp
$(DO_CC)
$(BUILDDIR)/CureAward.o : $(TFSTATS_DIR)/CureAward.cpp
$(DO_CC)
$(BUILDDIR)/KamikazeAward.o : $(TFSTATS_DIR)/KamikazeAward.cpp
$(DO_CC)
$(BUILDDIR)/SentryRebuildAward.o : $(TFSTATS_DIR)/SentryRebuildAward.cpp
$(DO_CC)
$(BUILDDIR)/SharpshooterAward.o : $(TFSTATS_DIR)/SharpshooterAward.cpp
$(DO_CC)
$(BUILDDIR)/SurvivalistAward.o : $(TFSTATS_DIR)/SurvivalistAward.cpp
$(DO_CC)
$(BUILDDIR)/TalkativeAward.o : $(TFSTATS_DIR)/TalkativeAward.cpp
$(DO_CC)
$(BUILDDIR)/TeamKillAward.o : $(TFSTATS_DIR)/TeamKillAward.cpp
$(DO_CC)
$(BUILDDIR)/WeaponAwards.o : $(TFSTATS_DIR)/WeaponAwards.cpp
$(DO_CC)
$(BUILDDIR)/CustomAward.o : $(TFSTATS_DIR)/CustomAward.cpp
$(DO_CC)
$(BUILDDIR)/CustomAwardList.o : $(TFSTATS_DIR)/CustomAwardList.cpp
$(DO_CC)
$(BUILDDIR)/CustomAwardTriggers.o : $(TFSTATS_DIR)/CustomAwardTriggers.cpp
$(DO_CC)
$(BUILDDIR)/Award.o : $(TFSTATS_DIR)/Award.cpp
$(DO_CC)
$(BUILDDIR)/CVars.o : $(TFSTATS_DIR)/CVars.cpp
$(DO_CC)
$(BUILDDIR)/DialogueReadout.o : $(TFSTATS_DIR)/DialogueReadout.cpp
$(DO_CC)
$(BUILDDIR)/MatchResults.o : $(TFSTATS_DIR)/MatchResults.cpp
$(DO_CC)
$(BUILDDIR)/scoreboard.o : $(TFSTATS_DIR)/scoreboard.cpp
$(DO_CC)
$(BUILDDIR)/WhoKilledWho.o : $(TFSTATS_DIR)/WhoKilledWho.cpp
$(DO_CC)
$(BUILDDIR)/Report.o : $(TFSTATS_DIR)/Report.cpp
$(DO_CC)
$(BUILDDIR)/HTML.o : $(TFSTATS_DIR)/HTML.cpp
$(DO_CC)
$(BUILDDIR)/main.o : $(TFSTATS_DIR)/main.cpp
$(DO_CC)
$(BUILDDIR)/TextFile.o : $(TFSTATS_DIR)/TextFile.cpp
$(DO_CC)
$(BUILDDIR)/util.o : $(TFSTATS_DIR)/util.cpp
$(DO_CC)
$(BUILDDIR)/binresources.o : $(TFSTATS_DIR)/binresources.cpp
$(DO_CC)
$(BUILDDIR)/PlayerSpecifics.o : $(TFSTATS_DIR)/PlayerSpecifics.cpp
$(DO_CC)
$(BUILDDIR)/StaticOutputFiles.o : $(TFSTATS_DIR)/StaticOutputFiles.cpp
$(DO_CC)
$(BUILDDIR)/TFStatsReport.o : $(TFSTATS_DIR)/TFStatsReport.cpp
$(DO_CC)
$(BUILDDIR)/memdbg.o : $(TFSTATS_DIR)/memdbg.cpp
$(DO_CC)
$(BUILDDIR)/pid.o : $(TFSTATS_DIR)/pid.cpp
$(DO_CC)
$(BUILDDIR)/tfstatsapplication.o : $(TFSTATS_DIR)/tfstatsapplication.cpp
$(DO_CC)
$(BUILDDIR)/playerreport.o : $(TFSTATS_DIR)/playerreport.cpp
$(DO_CC)
$(BUILDDIR)/plrpersist.o : $(TFSTATS_DIR)/plrpersist.cpp
$(DO_CC)
$(BUILDDIR)/tfstatsosinterface.o : $(TFSTATS_DIR)/tfstatsosinterface.cpp
$(DO_CC)
$(BUILDDIR)/allplayersstats.o : $(TFSTATS_DIR)/allplayersstats.cpp
$(DO_CC)
+460
View File
@@ -0,0 +1,460 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implemenatation of CMatchInfo
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "MatchInfo.h"
CMatchInfo* g_pMatchInfo=NULL; //global information about the match.
//------------------------------------------------------------------------------------------------------
// Function: CMatchInfo::generate
// Purpose: generates the match info structure from the log file
//------------------------------------------------------------------------------------------------------
void CMatchInfo::generate()
{
if (plogfile->empty())
g_pApp->fatalError("No data in log file!\nPlease ensure that you are running TFstats on a valid log file!");
CEventListIterator it=plogfile->begin();
logopentime=(*it)->getTime();
for (it;it!=plogfile->end();++it)
{
const CLogEvent* curr=(*it);
switch(curr->getType())
{
case CLogEvent::CONNECT:
{
int sid=curr->getArgument(0)->asPlayerGetSvrPID();
unsigned long WONid=curr->getArgument(0)->asPlayerGetWONID();
string plrName=curr->getArgument(0)->asPlayerGetName();
string ipAddress=curr->getArgument(1)->getStringValue();
PID pid;
PID foundpid=-1;
if (WONid!=-1)
{
bLanGame=false;
pid=pidMap[sid]=WONid;
}
else
{
bLanGame=true;
CPlayerList::iterator it=players.begin();
for (it;it!=players.end();++it)
{
PID currpid=it->first;
CPlayer& cp=it->second;
if (cp.ipAddress==ipAddress)
{
foundpid=currpid;
break;
}
}
if (it==players.end()) //if no ip addresses matched match by name
{
it = players.begin();
for (it;it!=players.end();++it)
{
PID currpid=it->first;
CPlayer& cp=it->second;
if (cp.aliases.contains(plrName))
{
foundpid=currpid;
break;
}
}
}
}
if (foundpid != -1)
{
pid=pidMap[sid]=foundpid;
}
else
{
pid=pidMap[sid]=sid;
}
//printf("Checkpoint %lu\n",__LINE__);
//printf("pid=%lu\n",pid);
if (players[pid].pid==-1)
players[pid].pid=pid;
players[pid].ipAddress=ipAddress;
players[pid].svrPID=sid;
players[pid].WONID=WONid;
//keep the pseudonym list updated
players[pid].nameFound(curr->getTime(),plrName);
}
break;
case CLogEvent::ENTER_GAME:
{
int sid=curr->getArgument(0)->asPlayerGetSvrPID();
//PID pid=curr->getArgument(0)->asPlayerGetFullPID();
unsigned long WONid=curr->getArgument(0)->asPlayerGetWONID();
PID pid;
if (WONid!=-1)
{
bLanGame=false;
pid=pidMap[sid]=WONid;
}
else
{
bLanGame=true;
//they may have matched based on IP or name.
//so check if the player structure pointed to by
//the sid is valid, if so, don't reassign pid
pid=pidMap[sid];
if (players[pid].ipAddress=="")
pid=pidMap[sid]=sid;
}
players[pid].svrPID=sid;
players[pid].WONID=WONid;
players[pid].pid=pid;
string nm=curr->getArgument(0)->asPlayerGetName();
//keep the pseudonym list updated
players[pid].nameFound(curr->getTime(),nm);
}
break;
case CLogEvent::CLASS_CHANGE:
{
PID pid=curr->getArgument(0)->asPlayerGetPID();
time_t changetime=curr->getTime();
player_class newpc=playerClassNameToClassID(curr->getArgument(1)->getStringValue());
//keep the pseudonym list updated
players[pid].nameFound(curr->getTime(),curr->getArgument(0)->asPlayerGetName());
string plrname=curr->getArgument(0)->asPlayerGetName();
players[pid].allclassesplayed.add(changetime,newpc);
int currTeam=players[pid].teams.atTime(changetime);
players[pid].perteam[currTeam].classesplayed.add(changetime,newpc);
}
break;
case CLogEvent::NAME_CHANGE:
{
//keep the pseudonym list updated
players[curr->getArgument(0)->asPlayerGetPID()].nameFound(curr->getTime(),curr->getArgument(1)->asPlayerGetName());
}
break;
case CLogEvent::SUICIDE:
{
PID pid=(*it)->getArgument(0)->asPlayerGetPID();
int team=players[pid].teams.atTime((*it)->getTime());
// players[pid].perteam[team].kills++;
players[pid].perteam[team].deaths++;
players[pid].perteam[team].suicides++;
//keep the pseudonym list updated
players[pid].nameFound(curr->getTime(),curr->getArgument(0)->asPlayerGetName());
}
break;
case CLogEvent::FRAG:
case CLogEvent::TEAM_FRAG:
{
PID killerid=(*it)->getArgument(0)->asPlayerGetPID();
PID killedid=(*it)->getArgument(1)->asPlayerGetPID();
int killerTeam=players[killerid].teams.atTime((*it)->getTime());
int killedTeam=players[killedid].teams.atTime((*it)->getTime());
CPlayer& p1=players[killerid];
CPlayer& p2=players[killedid];
if (curr->getType() == CLogEvent::TEAM_FRAG)
{
players[killerid].perteam[killerTeam].teamkills++;
players[killedid].perteam[killedTeam].teamkilled++;
}
else if (curr->getType() == CLogEvent::FRAG)
{
string weapName=(*it)->getArgument(2)->getStringValue();
bool countKill=true;
//gotta account for timer/infection double kills for medics!
if (weapName=="infection")
{
//test to see if the previous event was a timer from the same player, and a kill, and with the timer.
CEventListIterator it2=it;
if ((--it2)!=plogfile->begin())
{
if ((*it2)->getType() == CLogEvent::FRAG)
if ((*it2)->getArgument(2)->getStringValue()=="timer")
if ((*it2)->getArgument(0)->asPlayerGetPID()==killerid)
countKill=false;
}
}
if (countKill)
{
players[killerid].perteam[killerTeam].weaponKills[weapName]++;
players[killerid].perteam[killerTeam].kills++;
players[killedid].perteam[killedTeam].deaths++;
}
}
//keep the pseudonym list updated
players[killerid].nameFound(curr->getTime(),curr->getArgument(0)->asPlayerGetName());
players[killedid].nameFound(curr->getTime(),curr->getArgument(1)->asPlayerGetName());
}
break;
case CLogEvent::TEAM_JOIN:
{
int team=curr->getArgument(1)->getFloatValue();
team--; //teams are logged as 1-4. tfstats stores them as 0-3
PID pid=curr->getArgument(0)->asPlayerGetPID();
CPlayer& p=players[pid];
team_exists[team]=true;
int oldteam=team;
if(p.teams.anythingAtTime(curr->getTime()-1))
oldteam=p.teams.atTime(curr->getTime()-1);
else //if this is the first team join, count them as in the game
players[pid].logontime=curr->getTime();
//keep the pseudonym list updated
players[pid].nameFound(curr->getTime(),curr->getArgument(0)->asPlayerGetName());
players[pid].teams.add(curr->getTime(),team);
if (p.allclassesplayed.anythingAtTime(curr->getTime()))
{
player_class plrcurrclass=players[pid].allclassesplayed.atTime(curr->getTime());
players[pid].perteam[oldteam].classesplayed.cut(curr->getTime());
players[pid].perteam[team].classesplayed.add(curr->getTime(),plrcurrclass);
}
}
break;
case CLogEvent::TEAM_RENAME:
{
int teamid=curr->getArgument(0)->getFloatValue()-1;
string tname=curr->getArgument(1)->getStringValue();
teamnames[teamid]=tname;
}
break;
case CLogEvent::SERVER_NAME:
{
servername=curr->getArgument(0)->getStringValue();
}
break;
case CLogEvent::SERVER_SPAWN:
{
mapname=curr->getArgument(0)->getStringValue();
}
break;
case CLogEvent::DISCONNECT:
{
PID pid=curr->getArgument(0)->asPlayerGetPID();
players[pid].logofftime=curr->getTime();
players[pid].allclassesplayed.endTime=curr->getTime();
players[pid].allclassesplayed.cut(curr->getTime());
players[pid].teams.cut(curr->getTime());
players[pid].aliases.cut(curr->getTime());
int currTeam=players[pid].teams.atTime(curr->getTime());
players[pid].perteam[currTeam].classesplayed.cut(curr->getTime());
//keep the pseudonym list updated
if (pid!=-1) //sometimes disconnect messages have -1 for the pid
players[pid].nameFound(curr->getTime(),curr->getArgument(0)->asPlayerGetName());
}
break;
case CLogEvent::NAMED_BROADCAST:
{
//keep the pseudonym list updated
const CLogEventArgument* pArg=curr->getArgument(1);
PID pid=pArg->asPlayerGetPID();
players[pid].nameFound(curr->getTime(),curr->getArgument(1)->asPlayerGetName());
}
break;
case CLogEvent::NAMED_GOAL_ACTIVATE:
{
//keep the pseudonym list updated
players[curr->getArgument(0)->asPlayerGetPID()].nameFound(curr->getTime(),curr->getArgument(0)->asPlayerGetName());
}
break;
case CLogEvent::LOG_CLOSED:
{
logclosetime=curr->getTime();
}
break;
}
#ifdef _DEBUG
#ifdef _PARSEDEBUG
printf("%s:\n",CLogEvent::TypeNames[(int)curr->getType()]);
fflush(stdout);
printf("\t%s\n",curr->m_StrippedText);
fflush(stdout);
for (int i=0;curr->getArgument(i);i++)
{
if (i==0)
printf("\t\targs: ");
fflush(stdout);
printf("\"%s\" ",curr->getArgument(i)->getStringValue());
}
printf("\n");
#endif
#endif
}
if (logclosetime==0 && !plogfile->empty())
{
CEventListIterator it=plogfile->end();
--it;
logclosetime=(*it)->getTime();
}
map<PID,CPlayer>::iterator it2;
for(it2=players.begin();it2!=players.end();++it2)
{
CPlayer& p=(*it2).second;
if (p.aliases.endTime < logclosetime)
p.aliases.endTime=logclosetime;
p.name=p.aliases.favourite();
if (p.allclassesplayed.endTime < logclosetime)
p.allclassesplayed.endTime=logclosetime;
if (p.teams.endTime < logclosetime)
p.teams.endTime=logclosetime;
for (int i=0;i<MAX_TEAMS;i++)
{
//if you have no kills you have to play on a team at least 30 seconds to be counted part of it
//also give a one-suicide grace so they can killthemselves to get onto another team?
if (p.teams.howLong(i) < 30 && p.perteam[i].kills==0)// && p.perteam[i].deaths < 1)
p.teams.remove(i);
CTimeIndexedList<player_class>* v= &p.perteam[i].classesplayed;
p.perteam[i].classesplayed.endTime=logclosetime;
time_t t=p.teams.howLong(i);
p.perteam[i].timeon=t;
}
}
}
//------------------------------------------------------------------------------------------------------
// Function: CMatchInfo::getPlayerID
// Purpose: resolves a player name to that players PID
// Input: name - the name
// Output: PID the PID
//------------------------------------------------------------------------------------------------------
PID CMatchInfo::getPlayerID(string name)
{
CPlayerListIterator it;
//ugh! O(n)
for (it=playerBegin();it!=playerEnd();++it)
{
PID id=(*it).first;
CPlayer curr=(*it).second;
if (curr.name == name)
return id;
}
return -1;
}
/*
unsigned long CMatchInfo::getPlayerWONID(string name)
{
CPlayerListIterator it;
//ugh! O(n)
for (it=playerBegin();it!=playerEnd();++it)
{
CPlayer curr=(*it).second;
if (curr.name == name)
return curr.WONID;
}
return 0xffffffff;
}
*/
//------------------------------------------------------------------------------------------------------
// Function: CMatchInfo::CMatchInfo
// Purpose: Constructor
// Input: plf - the log file
// Output:
//------------------------------------------------------------------------------------------------------
CMatchInfo::CMatchInfo(CEventList* plf)
:numPlrs(0),logclosetime(0),plogfile(plf)
{
teamnames[0]="Blue";
teamnames[1]="Red";
teamnames[2]="Yellow";
teamnames[3]="Green";
team_exists[0]=team_exists[1]=team_exists[2]=team_exists[3]=false;
generate();
}
//------------------------------------------------------------------------------------------------------
// Function: CMatchInfo::teamID
// Purpose: resolves a team name to its ID
// Input: teamname - the team name
// Output: int the ID of the team
//------------------------------------------------------------------------------------------------------
int CMatchInfo::teamID(string teamname)
{
for (int i=0;i<MAX_TEAMS;i++)
if (stricmp(teamname.c_str(),teamnames[i].c_str())==0)
return i;
return -1;
}
//------------------------------------------------------------------------------------------------------
// Function: CMatchInfo::getTimeOn
// Purpose: returns how long the specified player has been playing
// Input: pid - the player being queried
// Output: time_t the time he/she played
//------------------------------------------------------------------------------------------------------
time_t CMatchInfo::getTimeOn(PID pid)
{
CPlayer& p=players[pid];
if (p.logofftime==0)
p.logofftime=logclosetime;
time_t timeon=p.logofftime-p.logontime;
return timeon;
}
+94
View File
@@ -0,0 +1,94 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CMatchInfo
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#pragma warning(disable:4786)
#ifndef MATCHINFO_H
#define MATCHINFO_H
#ifdef WIN32
#pragma once
#endif
#include <map>
#include <string>
#include "EventList.h"
#include "util.h"
#include "player.h"
#include "time.h"
using namespace std;
//------------------------------------------------------------------------------------------------------
// Purpose: CMatchInfo is a collection of data gleaned from the logfile. An
// instance of this class contains info that many different report elements and
// awards use, such as player names, teams, and things like that.
//------------------------------------------------------------------------------------------------------
class CMatchInfo
{
private:
CPlayerList players;
public:
CPlayerListIterator playerBegin(){return players.begin();}
CPlayerListIterator playerEnd(){return players.end();}
CPlayerList& playerList(){return players;}
private:
string teamnames[MAX_TEAMS];
bool team_exists[MAX_TEAMS];
string servername;
string mapname;
int numPlrs;
time_t logclosetime;
time_t logopentime;
CEventList* plogfile;
bool bLanGame;
public:
explicit CMatchInfo(CEventList* plf);
bool isLanGame(){return bLanGame;}
void generate();
CEventList* eventList(){return plogfile;}
int numPlayers(){return numPlrs;}
string mapName(){return mapname;}
char* playerName(PID pid,char* out){if (pid==1) return "PID=-1!"; strcpy(out,players[pid].name.c_str());return out;}
string playerName(PID pid){return pid==-1?string("PID=-1!"):players[pid].name;}
PID getPlayerID(string name);
//unsigned int getPlayerWONID(string name);
//unsigned int getPlayerWONID(PID pid){return players[pid].WONID;}
//int playerTeamID(PID p){return players[p].team;}
string teamName(int TID){return teamnames[TID];}
int teamID(string teamname);
bool teamExists(int tid){return team_exists[tid];}
string getServerName(){return servername;}
time_t getTimeOn(PID pid);
time_t logCloseTime(){return logclosetime;}
time_t logOpenTime(){return logopentime;}
};
extern CMatchInfo* g_pMatchInfo;
#endif // MATCHINFO_H
+227
View File
@@ -0,0 +1,227 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "MatchResults.h"
void CMatchResults::init()
{
memset(teams,0,sizeof(team)*MAX_TEAMS);
memset(loserString,0,STRLEN);
memset(winnerString,0,STRLEN);
valid=false;
draw=false;
numTeams=0;
}
void CMatchResults::generate()
{
CEventListIterator it=g_pMatchInfo->eventList()->end();
--it;
for (it=g_pMatchInfo->eventList()->begin();it!=g_pMatchInfo->eventList()->end();++it)
{
if ((*it)->getType()==CLogEvent::MATCH_RESULTS_MARKER)
valid=true;
else if ((*it)->getType()==CLogEvent::MATCH_DRAW)
{
draw=true;
}
else if ((*it)->getType()==CLogEvent::MATCH_VICTOR)
{
//winning teams are recited first, then losing teams. so start in "winning" mode
bool fWinMode=true;
char eventText[200];
strcpy(eventText,(*it)->getFullMessage());
char seps[] = " \n\t";
char *token;
token = strtok( eventText, seps );
while( token != NULL )
{
if (stricmp(token,"defeated")==0)
fWinMode=false;
else if (token[0]=='\"')
{
//found a team name
//depending on win/lose mode, assign that team appropriately
token++; //advance past the first quote
char* quote2=strchr(token,'\"');
*quote2='\0'; //null out the second quote;
//get team ID
int tID=g_pMatchInfo->teamID(token);
teams[tID].fWinner=fWinMode;
}
//Get next token
token = strtok( NULL, seps );
}
}
else if ((*it)->getType()==CLogEvent::MATCH_TEAM_RESULTS)
{
int team=g_pMatchInfo->teamID((*it)->getArgument(0)->getStringValue());
teams[team].valid=true;
teams[team].numplayers=(*it)->getArgument(1)->getFloatValue();
teams[team].frags=(*it)->getArgument(2)->getFloatValue();
teams[team].unacc_frags=(*it)->getArgument(3)->getFloatValue();
teams[team].score=(*it)->getArgument(4)->getFloatValue();
for (int i=0;i<MAX_TEAMS;i++)
{
teams[team].allies[i]= (i==team); //initially set team to be allied with itself.
}
//get allies
i=5;
CLogEventArgument const * pArg=(*it)->getArgument(i++);
while(pArg)
{
int ally=pArg->getFloatValue()-1;
teams[team].allies[ally]=true;
teams[ally].allies[team]=true; //one sided alliances don't exist.
pArg=(*it)->getArgument(i++);
}
}
}
}
char* CMatchResults::getWinnerTeamsString()
{
bool firstWinner=true;
for (int i=0;i<MAX_TEAMS;i++)
{
if (teams[i].valid && teams[i].fWinner)
{
if (!firstWinner)
strcat(winnerString," and ");
strcat(winnerString,g_pMatchInfo->teamName(i).c_str());
firstWinner=false;
}
}
return winnerString;
}
int CMatchResults::getWinnerTeamScore()
{
if (draw)
return teams[0].score;
for (int i=0;i<MAX_TEAMS;i++)
if (teams[i].valid && teams[i].fWinner)
return teams[i].score;
return 0;
}
void CMatchResults::calcRealWinners()
{
//first find the highest score.
int maxScoreTeam=0;
for (int i=0;i<MAX_TEAMS;i++)
{
teams[i].fWinner=false;
if (teams[i].score > teams[maxScoreTeam].score)
maxScoreTeam=i;
}
//mark that team as a winner, then mark all their allies as winners
teams[maxScoreTeam].fWinner=true;
for (int j=0;j<MAX_TEAMS;j++)
{
if (teams[maxScoreTeam].allies[j])
teams[j].fWinner=true;
}
}
char* CMatchResults::getLoserTeamsString()
{
bool firstLoser=true;
for (int i=0;i<MAX_TEAMS;i++)
{
if (teams[i].valid && !teams[i].fWinner)
{
if (!firstLoser)
strcat(loserString," and ");
strcat(loserString,g_pMatchInfo->teamName(i).c_str());
firstLoser=false;
}
}
return loserString;
}
int CMatchResults::getLoserTeamScore()
{
if (draw)
return teams[0].score;
for (int i=0;i<MAX_TEAMS;i++)
if (teams[i].valid && !teams[i].fWinner)
return teams[i].score;
return 0;
}
bool CMatchResults::Outnumbered(int WinnerOrLoser)
{
int losers=0;
int winners=0;
for (int i=0;i<MAX_TEAMS;i++)
{
if (teams[i].fWinner)
winners+=teams[i].numplayers;
else
losers+=teams[i].numplayers;
}
if (WinnerOrLoser == WINNER)
return losers > winners;
else
return losers < winners;
}
int CMatchResults::numWinningTeams()
{
int num=0;
for (int i=0;i<MAX_TEAMS;i++)
{
if (teams[i].fWinner) num++;
}
return num;
}
void CMatchResults::writeHTML(CHTMLFile& html)
{
calcRealWinners(); //deal with logging bug in DLL
html.write("<div class=headline>\n");
if (!valid)
html.write("No winner has been determined.");
else if (!draw)
{
bool fOutnumbered=false;
bool winPlural=numWinningTeams()==1;
html.write("%s %s! They scored %li points to %s's %li\n",getWinnerTeamsString(),winPlural?"wins":"win",getWinnerTeamScore(),getLoserTeamsString(),getLoserTeamScore());
}
else
html.write("The match ends in a draw! <br> All teams scored %li \n",getWinnerTeamScore());
html.write("</div>");
}
+57
View File
@@ -0,0 +1,57 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "report.h"
class CMatchResults: public CReport
{
public:
enum Consts
{
WINNER=1,
LOSER=0,
STRLEN=200,
};
private:
struct team
{
bool valid;
int score;
int frags;
int unacc_frags;
int numplayers;
bool fWinner;
bool allies[MAX_TEAMS];
};
team teams[MAX_TEAMS];
int numTeams;
char winnerString[STRLEN];
char loserString[STRLEN];
bool valid;
bool draw;
void init();
void calcRealWinners();
char* getWinnerTeamsString();
int getWinnerTeamScore();
bool Outnumbered(int WinnerOrLoser);
char* getLoserTeamsString();
int getLoserTeamScore();
int numWinningTeams();
public:
explicit CMatchResults(){init();}
void generate();
void writeHTML(CHTMLFile& html);
};
+122
View File
@@ -0,0 +1,122 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: code to track allocations via replacing the global new operator
// some of this code was written by Paul Andre LeBlanc
// <paul.a.leblanc@sympatico.ca> I got it off of dejanews.com
// usage: new TRACKED object-type
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include <new.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#ifdef _DEBUG
#ifdef _MEMDEBUG
#define _MDEBUG
#endif
#endif
#ifdef _MDEBUG
static int numBytesAllocated=0;
//these were written by me, wes cumberland, not paul andre leblanc
void * operator new(size_t size)
{
void *ptr = malloc(size);
numBytesAllocated+=size;
return ptr;
}
void * operator new[](size_t size)
{
void *ptr = malloc(size);
numBytesAllocated+=size;
return ptr;
}
void operator delete(void* ptr)
{
free(ptr);
}
void operator delete[](void* ptr)
{
free(ptr);
}
//this code will track allocations
//this code was written by Paul Andre LeBlanc <paul.a.leblanc@sympatico.ca>
//I got it off of dejanews.com
void *operator new(size_t size, const char *file, const int line)
{
void *ptr = new char[size];
numBytesAllocated+=size;
cout << "new: Allocating " << size << " bytes in file " << file << ", line " << line << ", address is " << ptr << " (" << numBytesAllocated<<" total allocated)"<< endl;
return ptr;
}
void *operator new[](size_t size, const char *file, const int line) {
void *ptr = new char[size];
numBytesAllocated+=size;
cout << "new[]: Allocating " << size << " bytes in file " << file << ", line " << line << ", address is " << ptr << " (" << numBytesAllocated<<" total allocated)" << endl;
return ptr;
}
void operator delete(void *ptr, const char *file, const int line) {
cout << "delete: Freeing memory allocated at file " << file << ", line " << line << ", address is " << ptr << endl;
delete [] (char *) ptr;
}
void operator delete[](void *ptr, const char *file, const int line)
{
cout << "delete[]: Freeing memory allocated at file " << file << ", line " << line << ", address is " << ptr << endl;
delete [] (char *) ptr;
}
#endif
//------------------------------------------------------------------------------------------------------
// Function: TFStats_win32_new_handler
// Purpose: this function will be called if TFStats runs out of memory (unlikely)
// this is a win32 specific version, the linux version does not pass an argument
// Input: sz - the size of the allocation that failed
// Output: int
//------------------------------------------------------------------------------------------------------
int TFStats_win32_new_handler(size_t sz)
{
printf("TFStats ran out of memory trying to allocate %li bytes\n",sz);
return 0;
}
//------------------------------------------------------------------------------------------------------
// Function: TFStats_linux_new_handler
// Purpose: this function will be called if TFStats runs out of memory (unlikely)
// this is a linux specific version, the win32 version passes an argument
//------------------------------------------------------------------------------------------------------
void TFStats_linux_new_handler(void)
{
printf("TFStats ran out of memory!\n");
}
//------------------------------------------------------------------------------------------------------
// Function: TFStats_setNewHandler
// Purpose: sets the new handler to the TFStats new handler
//------------------------------------------------------------------------------------------------------
void TFStats_setNewHandler()
{
#ifdef WIN32
_set_new_handler(TFStats_win32_new_handler);
_set_new_mode(1);
#else
std::set_new_handler(TFStats_linux_new_handler);
//std::set_new_mode(1);
#endif
}
+55
View File
@@ -0,0 +1,55 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: declarations to track allocations via replacing the global new operator
// some of this code was written by Paul Andre LeBlanc
// <paul.a.leblanc@sympatico.ca> I got it off of dejanews.com
// usage: new TRACKED object-type
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef MEMDBG_H
#define MEMDBG_H
#ifdef WIN32
#pragma once
#endif
#ifdef _DEBUG
#ifdef _MEMDEBUG
#define _MDEBUG
#endif
#endif
#ifdef _MDEBUG
#define TRACKED (__FILE__, __LINE__)
#else
#define TRACKED
#endif
#ifdef _MDEBUG
void *operator new(size_t size, const char *file, const int line);
void *operator new[](size_t size, const char *file, const int line);
void operator delete(void *ptr, const char *file, const int line);
void operator delete[](void *ptr, const char *file, const int line);
//replacing global new for debugging purposes.
//these were written by me, wes cumberland, not paul andre leblanc
void* operator new(size_t size);
void* operator new[](size_t size);
void operator delete(void* v);
void operator delete[](void* v);
#endif
//leave this in, even for release build
int TFStats_win32_new_handler(size_t sz);
void TFStats_linux_new_handler(void);
void TFStats_setNewHandler();
#endif // MEMDBG_H
+11
View File
@@ -0,0 +1,11 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "pid.h"
#include <map>
std::map<int,PID> pidMap;
+22
View File
@@ -0,0 +1,22 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: interface and implementation of PID.
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef PID_H
#define PID_H
#ifdef WIN32
#pragma once
#pragma warning(disable:4786)
#endif
typedef unsigned long PID;
#include <map>
extern std::map<int,PID> pidMap;
#endif // PID_H
+129
View File
@@ -0,0 +1,129 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#pragma warning (disable:4786)
#include <string>
#include "Player.h"
#include "MatchInfo.h"
using namespace std;
CPlayer::CPlayer()
:teams()
{
WONID=pid=svrPID=-1;
logontime=logofftime=reconnects=0;
name="uninitted";
}
void CPlayer::nameFound(time_t t, string alias)
{
if (aliases.atTime(t)!=alias)
{
aliases.add(t,alias);
}
name=aliases.favourite();
}
time_t CPlayer::plr_per_team_data::timeOn()
{
/*if (logofftime==0)
{
logofftime=g_pMatchInfo->logCloseTime();
}
return logofftime-logontime;
*/
return timeon;
}
time_t CPlayer::totalTimeOn()
{
if (logofftime==0)
{
logofftime=g_pMatchInfo->logCloseTime();
}
return logofftime-logontime;
}
double CPlayer::plr_per_team_data::rank()
{
double d = (kills-deaths);
double time=((double)timeOn())/1000.0;
if (time < .000001)
return d;
return d/time;
}
string CPlayer::plr_per_team_data::faveWeapon()
{
if (faveweapon=="" && weaponKills.begin()!=weaponKills.end())
{
faveweapkills=0;
//noKills=false;
map<string,int>::iterator weapIt=weaponKills.begin();
string& fave=(string&) (*weapIt).first;
int faveKills=(*weapIt).second;
for (weapIt;weapIt!=weaponKills.end();++weapIt)
{
const string& weapName=(*weapIt).first;
int kills=(*weapIt).second;
if (kills < faveKills)
continue;
fave=weapName;
faveKills=kills;
}
faveweapkills=faveKills;
faveweapon=fave;
}
return faveweapon;
}
int CPlayer::plr_per_team_data::faveWeapKills()
{
if (faveweapkills==0)
{
//calculate favourite weapon stats
faveWeapon();
}
return faveweapkills;
}
void CPlayer::merge()
{
perteam[ALL_TEAMS].kills=perteam[0].kills+perteam[1].kills+perteam[2].kills+perteam[3].kills;
perteam[ALL_TEAMS].deaths=perteam[0].deaths+perteam[1].deaths+perteam[2].deaths+perteam[3].deaths;
perteam[ALL_TEAMS].suicides=perteam[0].suicides+perteam[1].suicides+perteam[2].suicides+perteam[3].suicides;
perteam[ALL_TEAMS].teamkills=perteam[0].teamkills+perteam[1].teamkills+perteam[2].teamkills+perteam[3].teamkills;
perteam[ALL_TEAMS].teamkilled=perteam[0].teamkilled+perteam[1].teamkilled+perteam[2].teamkilled+perteam[3].teamkilled;
perteam[ALL_TEAMS].timeon=perteam[0].timeon+perteam[1].timeon+perteam[2].timeon+perteam[3].timeon;
for (int i=0;i<MAX_TEAMS;i++)
{
map<std::string,int>::iterator it;
for (it=perteam[i].weaponKills.begin();it!=perteam[i].weaponKills.end();++it)
{
string weapname=(*it).first;
int kills=(*it).second;
perteam[ALL_TEAMS].weaponKills[weapname]+=kills;
}
}
//this is probably only a shallow copy, but that's ok
perteam[ALL_TEAMS].classesplayed=allclassesplayed;
}
+94
View File
@@ -0,0 +1,94 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CPlayer
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#pragma warning (disable:4786)
#ifndef PLAYER_H
#define PLAYER_H
#ifdef WIN32
#pragma once
#endif
#include <time.h>
#include <map>
#include <string>
#include "util.h"
#include "TimeIndexedList.h"
#include "pid.h"
class CMatchInfo;
class CPlayer
{
public:
struct plr_per_team_data
{
int kills;
int deaths;
int suicides;
//double rank;
int teamkills;
int teamkilled;
std::map<std::string,int> weaponKills;
std::string faveweapon;
int faveweapkills;
double rank();
std::string faveWeapon();
int faveWeapKills();
plr_per_team_data(){kills=deaths=suicides=teamkills=teamkilled=faveweapkills=0;}
CTimeIndexedList<player_class> classesplayed; //stores class, indexed by the time when that class was switched to.
time_t timeon;
time_t timeOn();
};
CTimeIndexedList<player_class> allclassesplayed; //stores class, indexed by the time when that class was switched to.
CTimeIndexedList<int> teams;
plr_per_team_data perteam[MAX_TEAMS+1];
CTimeIndexedList<std::string> aliases;
std::string name; //this will be set to the favourite name of the player
//int team;
int svrPID;
unsigned long WONID;
string ipAddress;
int reconnects;
PID pid;
time_t logontime;
time_t logofftime;
time_t totalTimeOn();
// int teamID(){return team;}
CPlayer();
void nameFound(time_t t, std::string alias);
//merge stats from all teams into 5th "team" (all teams)
void merge();
};
#include "pid.h"
typedef std::map<PID,CPlayer> CPlayerList;
typedef CPlayerList::iterator CPlayerListIterator;
#endif // PLAYER_H
+263
View File
@@ -0,0 +1,263 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CPlayerReport;
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "util.h"
#include "PlayerReport.h"
#include "PlrPersist.h"
map<unsigned long,bool> CPlayerReport::alreadyPersisted;
map<unsigned long,bool> CPlayerReport::alreadyWroteCombStats;
//------------------------------------------------------------------------------------------------------
// Function: CPlayerReport::writeHTML
// Purpose: writes the player's stats out as HTML
// Input: html - the html file to which we're writing
//------------------------------------------------------------------------------------------------------
void CPlayerReport::writeHTML(CHTMLFile& html)
{
//if we're writing the stats for a persistent player, just pass execution off to that function!
if (reportingPersistedPlayer)
{
writePersistHTML(html);
return;
}
pPlayer->totalTimeOn(); //this ensures that the logoff time is correct
if (iWhichTeam==ALL_TEAMS)
pPlayer->merge();
else if (!pPlayer->teams.contains(iWhichTeam))
{
return;
}
int tid=iWhichTeam;
if (tid==ALL_TEAMS)
html.write("<font class=headline>%s</font><br>\n",pPlayer->name.c_str());
else
html.write("<font class=player%s2>%s</font><hr align=left width=60%%>\n",Util::teamcolormap[tid],pPlayer->name.c_str());
if (pPlayer->aliases.size() > 1)
{
map<string,bool> namePrinted;
namePrinted[pPlayer->name.c_str()]=true;
html.write("<font class=whitetext>aliases:</font> <font class=awards2>");
CTimeIndexedList<string>::iterator nmiter=pPlayer->aliases.begin();
bool printed1=false;
for (nmiter;nmiter!=pPlayer->aliases.end();++nmiter)
{
if (namePrinted[nmiter->data]!=true)
{
if (printed1)
html.write(", ");
html.write(nmiter->data.c_str());
namePrinted[nmiter->data]=true;
printed1=true;
}
}
html.write("</font><br>\n");
}
html.write("<font class=whitetext>rank:</font> <font class=awards2> %.2lf </font><br>\n",pPlayer->perteam[tid].rank());
html.write("<font class=whitetext>kills/deaths:</font> <font class=awards2>%li/%li </font><br>\n",pPlayer->perteam[tid].kills,pPlayer->perteam[tid].deaths);
html.write("<font class=whitetext>time:</font> <font class=awards2> %01li:%02li:%02li </font><br>\n",Util::time_t2hours(pPlayer->perteam[tid].timeOn()),Util::time_t2mins(pPlayer->perteam[tid].timeOn()),Util::time_t2secs(pPlayer->perteam[tid].timeOn()));
int numClassesPlayed=pPlayer->perteam[tid].classesplayed.numDifferent();
player_class faveClass=pPlayer->perteam[tid].classesplayed.favourite();
if (numClassesPlayed == 1)
{
if (faveClass!=PC_UNDEFINED)
html.write("<font class=whitetext>class:</font> <font class=awards2> %s </font><br>\n",plrClassNames[faveClass]);
}
else if (numClassesPlayed > 1)
{
if (faveClass!=PC_UNDEFINED)
html.write("<font class=whitetext>favorite class:</font> <font class=awards2> %s </font><br>\n",plrClassNames[faveClass]);
html.write("<font class=whitetext>classes played:</font> <font class=awards2> ");
bool printedone=false;
for(int pc=PC_SCOUT;pc!=PC_OBSERVER;++pc)
{
if (pPlayer->perteam[tid].classesplayed.contains((player_class)pc))
{
if (printedone)
html.write(", ");
html.write(plrClassNames[pc]);
printedone=true;
}
}
html.write(" </font><br>\n");
}
const string weap=pPlayer->perteam[tid].faveWeapon();
const string faveWeap=Util::getFriendlyWeaponName(weap);
if (pPlayer->perteam[tid].kills!=0)
{
char lowerWeapName[50];
Util::str2lowercase(lowerWeapName,faveWeap.c_str());
html.write("<font class=whitetext>favorite weapon:</font> <font class=awards2> %s</font><br>\n",faveWeap.c_str());
html.write("<font class=whitetext>kills with %s:</font> <font class=awards2> %li</font><br>\n",lowerWeapName,pPlayer->perteam[tid].faveWeapKills());
}
int numTeamsPlayed=pPlayer->teams.numDifferent();
if (numTeamsPlayed > 1)
{
if (iWhichTeam==ALL_TEAMS)
html.write("<font class=whitetext>Played on</font> <font class=whitetext> ");
else
html.write("<font class=whitetext>Also played on</font> <font class=whitetext> ");
map<int,bool> alreadyPrinted;
CTimeIndexedList<int>::iterator tmiter=pPlayer->teams.begin();
bool printed1=false;
for (tmiter;tmiter!=pPlayer->teams.end();++tmiter)
{
int team=tmiter->data;
if (team != iWhichTeam && !alreadyPrinted[team])
{
if (printed1)
html.write(" and ");
html.write("<font class=player%s>%s</font>",Util::teamcolormap[team],Util::teamcolormap[team]);//
printed1=true;
alreadyPrinted[team]=true;
}
}
html.write("</font><br>\n");
}
if (numTeamsPlayed > 1 && iWhichTeam != ALL_TEAMS)
{
html.write("<a class=whitetext href=\"%lu.html\"> <u> Combined stats for this match </u> </a> <br> \n",pPlayer->pid);
if (!alreadyWroteCombStats[pPlayer->pid])
{
CPlayerReport cpr(pPlayer,ALL_TEAMS);
char numbuf[200];
char namebuf[200];
sprintf(numbuf,"%lu.html",pPlayer->pid);
sprintf(namebuf,"Combined match statistics for %s",pPlayer->name.c_str());
cpr.makeHTMLPage(numbuf,namebuf);
alreadyWroteCombStats[pPlayer->pid]=true;
}
}
if (g_pApp->cmdLineSwitches["persistplayerstats"]=="yes" && !g_pMatchInfo->isLanGame())
html.write("<a class=whitetext href=\"%s/allplayers.html#%lu\"> <u> Combined stats on this server </u> </a> <br> \n",g_pApp->playerHTTPPath.c_str(),pPlayer->WONID,pPlayer->name.c_str());
if (g_pMatchInfo->isLanGame())
return;
if (alreadyPersisted[pPlayer->WONID] || reportingPersistedPlayer)
return;
alreadyPersisted[pPlayer->WONID]=true;
if (g_pApp->cmdLineSwitches["persistplayerstats"]=="yes")
{
CPlrPersist cpp;
CPlrPersist onDisk;
cpp.generate(*pPlayer);
onDisk.read(pPlayer->WONID);
cpp.merge(onDisk);
cpp.write();
}
}
//------------------------------------------------------------------------------------------------------
// Function: CPlayerReport::writePersistHTML
// Purpose: writes a persistent player's stats out. these look slightly different
// than normal players stats
// Input: html - the html file to write the html to
//------------------------------------------------------------------------------------------------------
void CPlayerReport::writePersistHTML(CHTMLFile& html)
{
html.write("<a name=\"%lu\">\n",pPersist->WONID);
html.write("<font class=headline2>%s</font><hr align=left width=60%%>\n",pPersist->faveName().c_str());
map<string,bool> namePrinted;
namePrinted[pPersist->faveName()]=true;
map<string,int>::iterator nmiter=pPersist->nickmap.begin();
bool printed1=false;
for (nmiter;nmiter!=pPersist->nickmap.end();++nmiter)
{
if (namePrinted[nmiter->first]!=true)
{
if (!printed1)
html.write("<font class=whitetext>other names used:</font> <font class=awards2>");
if (printed1)
html.write(", ");
html.write(nmiter->first.c_str());
namePrinted[nmiter->first]=true;
printed1=true;
}
}
if (printed1)
html.write("</font><br>\n");
html.write("<font class=whitetext>rank:</font> <font class=awards2> %.2lf </font><br>\n",pPersist->rank());
html.write("<font class=whitetext>kills/deaths:</font> <font class=awards2>%li/%li </font><br>\n",pPersist->kills,pPersist->deaths);
html.write("<font class=whitetext>time:</font> <font class=awards2> %01li:%02li:%02li </font><br>\n",Util::time_t2hours(pPersist->timeon),Util::time_t2mins(pPersist->timeon),Util::time_t2secs(pPersist->timeon));
html.write("<font class=whitetext>matches played:</font> <font class=awards2> %li </font><br>\n",pPersist->matches);
string faveClass=pPersist->faveClass();
if (faveClass!="Undefined")
html.write("<font class=whitetext>favorite class:</font> <font class=awards2> %s </font><br>\n",faveClass.c_str());
bool printedone=false;
map<string,int>::iterator classit=pPersist->classmap.begin();
map<string,bool> classPrinted;
classPrinted[pPersist->faveClass()]=true;
for(classit;classit!=pPersist->classmap.end();++classit)
{
if (classPrinted[classit->first]==false)
{
if (!printedone)
html.write("<font class=whitetext>other classes played:</font> <font class=awards2> ");
if (printedone)
html.write(", ");
html.write(classit->first.c_str());
classPrinted[classit->first]=true;
printedone=true;
}
}
if (printedone)
html.write(" </font><br>\n");
const string weap=pPersist->faveWeap();
const string faveWeap=Util::getFriendlyWeaponName(weap);
if (pPersist->kills!=0)
{
char lowerWeapName[50];
Util::str2lowercase(lowerWeapName,faveWeap.c_str());
html.write("<font class=whitetext>favorite weapon:</font> <font class=awards2> %s</font><br>\n",faveWeap.c_str());
html.write("<font class=whitetext>kills with %s:</font> <font class=awards2> %li</font><br>\n",lowerWeapName,pPersist->faveweapkills);
}
}
+45
View File
@@ -0,0 +1,45 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface of CPlayerReport
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef PLAYERREPORT_H
#define PLAYERREPORT_H
#ifdef WIN32
#pragma once
#endif
#include "Player.h"
#include "Report.h"
#include "PlrPersist.h"
//------------------------------------------------------------------------------------------------------
// Purpose: Reports a specific player's stats.
//------------------------------------------------------------------------------------------------------
class CPlayerReport: public CReport
{
private:
CPlayer* pPlayer;
CPlrPersist* pPersist;
int iWhichTeam;
static map<unsigned long,bool> alreadyPersisted;
static map<unsigned long,bool> alreadyWroteCombStats;
bool reportingPersistedPlayer;
void writePersistHTML(CHTMLFile& html);
public:
CPlayerReport(CPlayer* pP,int t):pPlayer(pP),iWhichTeam(t){reportingPersistedPlayer=false;}
CPlayerReport(CPlrPersist* pPP):pPersist(pPP) {iWhichTeam=-1;reportingPersistedPlayer=true;}
virtual void writeHTML(CHTMLFile& html);
};
#endif // PLAYERREPORT_H
+96
View File
@@ -0,0 +1,96 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CPlayerSpecifics
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "PlayerSpecifics.h"
#include "PlayerReport.h"
//------------------------------------------------------------------------------------------------------
// Function: CPlayerSpecifics::init
// Purpose: intializes the object
//------------------------------------------------------------------------------------------------------
void CPlayerSpecifics::init()
{
}
//------------------------------------------------------------------------------------------------------
// Function: CPlayerSpecifics::generate
// Purpose: generates intermediate data from match info
//------------------------------------------------------------------------------------------------------
void CPlayerSpecifics::generate()
{
}
//------------------------------------------------------------------------------------------------------
// Function: CPlayerSpecifics::writeHTML
// Purpose: writes out html based on the intermediate data generated by generate()
// Input: html - the html file to output to
//------------------------------------------------------------------------------------------------------
void CPlayerSpecifics::writeHTML(CHTMLFile& html)
{
int numteams=0;
for (int t=0;t<MAX_TEAMS;t++)
if (g_pMatchInfo->teamExists(t)) numteams++;
html.write("<table cols=%li cellspacing=0 border=0 cellpadding=10 bordercolor=black>\n",numteams);
CPlayerListIterator i;
//multimap<double,CPlayer,greater<double> > ranksort;
//split playerlist into teams;
multimap<double,CPlayer,greater<double> > rankedteams[MAX_TEAMS];
for (i=g_pMatchInfo->playerBegin();i!=g_pMatchInfo->playerEnd();++i)
{
PID pid=(*i).first;
CPlayer p=(*i).second;
for (int t=0;t<MAX_TEAMS;t++)
{
if (p.teams.contains(t))
{
double rank=p.perteam[t].rank();
pair<double,CPlayer> insertme(rank,p);
rankedteams[t].insert(insertme);
}
}
}
while(!rankedteams[0].empty() || !rankedteams[1].empty() || !rankedteams[2].empty() || !rankedteams[3].empty())
{
html.write("<tr>\n");
int t;
for (t=0;t<MAX_TEAMS;t++)
{
if (!g_pMatchInfo->teamExists(t))
continue;
html.write("<td width=250 valign=top>");
if (rankedteams[t].begin()==rankedteams[t].end())
continue;
else
{
CPlayer& plr=(*(rankedteams[t].begin())).second;
CPlayerReport cpr(&plr,t);
cpr.writeHTML(html);
rankedteams[t].erase(rankedteams[t].begin());
//break;
}
html.write("</td>\n");
}
html.write("</tr>\n");
}
html.write("</table>");
}
+45
View File
@@ -0,0 +1,45 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface to CPlayerSpecifics
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef PLAYERSPECIFICS_H
#define PLAYERSPECIFICS_H
#ifdef WIN32
#pragma once
#endif
#pragma warning (disable: 4786)
#include "report.h"
#include <map>
#include <vector>
#include <string>
using namespace std;
//------------------------------------------------------------------------------------------------------
// Purpose: CPlayerSpecifics is a whole page report element that reports specific
// data about each player in the game. Data such as favourite weapon, rank,
// classes played, favourite class, and kills vs deaths.
//------------------------------------------------------------------------------------------------------
class CPlayerSpecifics :public CReport
{
private:
void init();
public:
explicit CPlayerSpecifics(){init();}
void generate();
void writeHTML(CHTMLFile& html);
};
#endif // PLAYERSPECIFICS_H
+419
View File
@@ -0,0 +1,419 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#pragma warning (disable:4786)
#include "PlrPersist.h"
#include "TextFile.h"
#include <map>
#include <string>
using namespace std;
//------------------------------------------------------------------------------------------------------
// Function: CPlrPersist::generate
// Purpose: fills in the fields of this with the data in the given CPlayer object
// Input: cp - the player object to get data from
//------------------------------------------------------------------------------------------------------
void CPlrPersist::generate(CPlayer& cp)
{
kills=deaths=timeon=0;
valid=true;
WONID=cp.WONID;
matches=1;
lastplayed=cp.logofftime;
//do perteam stuff
CTimeIndexedList<int>::iterator teamiter=cp.teams.begin();
for (teamiter;teamiter!=cp.teams.end();++teamiter)
{
int tdt=teamiter->data;
kills+=cp.perteam[teamiter->data].kills;
deaths+=cp.perteam[teamiter->data].deaths;
timeon+=cp.perteam[teamiter->data].timeon;
map<string,int>::iterator it;
it=cp.perteam[teamiter->data].weaponKills.begin();
for (it;it!=cp.perteam[teamiter->data].weaponKills.end();++it)
{
string name=it->first;
int kills=it->second;
weapmap[name]+=kills;
}
}
CTimeIndexedList<player_class>::iterator clsit=cp.allclassesplayed.begin();
for (clsit;clsit!=cp.allclassesplayed.end();++clsit)
{
string classname=plrClassNames[clsit->data];
classmap[classname]+=cp.allclassesplayed.howLong(clsit->data);
}
CTimeIndexedList<string>::iterator nameiter;
for (nameiter=cp.aliases.begin();nameiter!=cp.aliases.end();++nameiter)
{
nickmap[nameiter->data]+=cp.aliases.howLong(nameiter->data);
}
pair<time_t,time_t> startstop;
startstop.first=cp.logontime;
startstop.second=cp.logofftime;
playtimes.push_back(startstop);
}
//------------------------------------------------------------------------------------------------------
// Function: CPlrPersist::merge
// Purpose: merges the stats of another CPlrPersist object into this one.
// This is the key operation of this class. This is how player stats are kept up
// to date over time. If the two data files have playtimes that overlap, they
// are not merged (unless the mergeOverlaps flag is true)
// Input: other - the CPlrPersist object that we want to merge into this one
// mergeOverlaps - if true, overlapping playtimes are ignored.
//------------------------------------------------------------------------------------------------------
void CPlrPersist::merge(CPlrPersist& other,bool mergeOverlaps)
{
if (!other.valid)
return; //don't modify
if (WONID!=other.WONID)
{
g_pApp->warning("merging stats for two different WONIDs (%lu, %lu)",WONID,other.WONID);
}
else
{
//do playtimes first to see if overlaps occur
list<pair<time_t,time_t> >::iterator itOther=other.playtimes.begin();
for (itOther;itOther!=other.playtimes.end();++itOther)
{
list<pair<time_t,time_t> >::iterator overlap=timesOverlap(itOther->first,itOther->second);
time_t overlapSecond=overlap->second;
time_t overlapFirst=overlap->first;
if (mergeOverlaps || overlap==playtimes.end())
playtimes.push_back(*itOther);
else
{
g_pApp->warning("not merging stats for WON ID# %lu, playtime ranges overlap\n\t((%lu-%lu) overlaps with (%lu-%lu))",WONID,itOther->first,itOther->second,overlap->first,overlap->second);
return;
}
}
}
matches+=other.matches;
kills+=other.kills;
deaths+=other.deaths;
timeon+=other.timeon;
if (other.lastplayed > lastplayed)
lastplayed=other.lastplayed;
//do names
map<string,int>::iterator it;
it=other.nickmap.begin();
for (it;it!=other.nickmap.end();++it)
{
string name=it->first;
int time=it->second;
nickmap[name]+=time;
}
//do weapons
it=other.weapmap.begin();
for (it;it!=other.weapmap.end();++it)
{
string name=it->first;
int kills=it->second;
weapmap[name]+=kills;
}
//do classes
it=other.classmap.begin();
for (it;it!=other.classmap.end();++it)
{
string name=it->first;
int time=it->second;
classmap[name]+=time;
}
}
//------------------------------------------------------------------------------------------------------
// Function: CPlrPersist::read
// Purpose: fills in the fields of this by reading data out of a file
// Input: f - the file from which to read the data
//------------------------------------------------------------------------------------------------------
void CPlrPersist::read(CTextFile& f)
{
if (!f.isValid())
{
kills=deaths=timeon=0; WONID=-1;
valid=false;
return;
}
if(WONID==-1)
{
//parse it out of f;
string s=f.fileName();
char buf[100];
int startpos=s.find_last_of(g_pApp->os->pathSeperator());
int endpos=s.find_last_of(".");
if (endpos == -1)
return;
if (startpos==-1)
startpos=0;
s.copy(buf,(endpos-startpos),startpos);
buf[endpos-startpos]=0;
WONID=strtoul(buf,NULL,10);
if (!WONID)
{
WONID=-1;
valid=false;
return;
}
}
valid=false;
if (!f.eof()) kills=f.readInt(); else return;
if (!f.eof()) deaths=f.readInt(); else return;
if (!f.eof()) timeon=f.readULong(); else return;
if (!f.eof()) matches=f.readInt(); else return;
if (!f.eof()) lastplayed=f.readULong(); else return;
string next;
if (!f.eof())
{
f.discard("names");
next= f.peekNextString();
while ( next!="endnames")
{
string name=f.readString();
int timeon=f.readInt();
nickmap[name]=timeon;
next=f.peekNextString();
}
f.discard("endnames");
} else return;
if (!f.eof())
{
f.discard("weapons");
next= f.peekNextString();
while (next!="endweapons")
{
string name=f.readString();
int kills=f.readInt();
weapmap[name]=kills;
next=f.peekNextString();
}
f.discard("endweapons");
} else return;
if (!f.eof())
{
f.discard("classes");
next= f.peekNextString();
while (next!="endclasses")
{
string name=f.readString();
int timeused=f.readInt();
classmap[name]=timeused;
next=f.peekNextString();
}
f.discard("endclasses");
} else return;
if (!f.eof())
{
f.discard("playtimes");
next= f.peekNextString();
while (next!="endplaytimes")
{
pair<time_t,time_t> startstop;
startstop.first=f.readULong();
startstop.second=f.readULong();
playtimes.push_back(startstop);
next=f.peekNextString();
}
f.discard("endplaytimes");
} else return;
valid=true;
}
//------------------------------------------------------------------------------------------------------
// Function: CPlrPersist::read
// Purpose: converts the WONID to a file name (<wonid>.tfs) and passes execution
// off to the above read function.
// Input: WONID - the WONID of the player whose datafile we want to read
//------------------------------------------------------------------------------------------------------
void CPlrPersist::read(unsigned long WONID)
{
string file=g_pApp->playerDirectory;
char buf[100];
file+=g_pApp->os->ultoa(WONID,buf,10);
file+=".tfs";
this->WONID=WONID;
CTextFile f(file.c_str());
read(f);
}
void CPlrPersist::write()
{
string file=g_pApp->playerDirectory;
char buf[100];
file+=g_pApp->os->ultoa(WONID,buf,10);
file+=".tfs";
FILE* fout=fopen(file.c_str(),"wt");
fprintf(fout,"%li //kills\n",kills);
fprintf(fout,"%li //deaths\n",deaths);
fprintf(fout,"%lu //timeon\n",timeon);
fprintf(fout,"%li //matches played\n",matches);
fprintf(fout,"%lu //last played\n",lastplayed);
map<string,int>::iterator it;
fprintf(fout,"names\n");
it=nickmap.begin();
for (it;it!=nickmap.end();++it)
{
string name=it->first;
int time=it->second;
fprintf(fout,"\t\"%s\" %li //has used the name \"%s\" for %02li:%02li:%02li\n",name.c_str(),time,name.c_str(),Util::time_t2hours(time),Util::time_t2mins(time),Util::time_t2secs(time));
}
fprintf(fout,"endnames\n");
fprintf(fout,"weapons\n");
it=weapmap.begin();
for (it;it!=weapmap.end();++it)
{
string name=it->first;
int kills=it->second;
fprintf(fout,"\t\"%s\" %li //has killed %li people with \"%s\"\n",name.c_str(),kills,kills,name.c_str());
}
fprintf(fout,"endweapons\n");
fprintf(fout,"classes\n");
it=classmap.begin();
for (it;it!=classmap.end();++it)
{
string name=it->first;
int time=it->second;
fprintf(fout,"\t\"%s\" %li //has played as a \"%s\" for %02li:%02li:%02li\n",name.c_str(),time,name.c_str(),Util::time_t2hours(time),Util::time_t2mins(time),Util::time_t2secs(time));
}
fprintf(fout,"endclasses\n");
fprintf(fout,"playtimes\n");
list<pair<time_t,time_t> >::iterator it2=playtimes.begin();
for (it2;it2!=playtimes.end();++it2)
{
char buf[500];
time_t t1=it2->first;
time_t t2=it2->second;
bool doesOverlap;
list<pair<time_t,time_t> >::iterator overlap=timesOverlap(it2->first,it2->second,false);
doesOverlap= overlap!=playtimes.end();
fprintf(fout,"\t%lu %lu //played from %s.",it2->first,it2->second,Util::makeDurationString(it2->first,it2->second,buf," to "));
if (doesOverlap)
fprintf(fout,"Warning! overlaps with time range (%lu-%lu)",overlap->first,overlap->second);
fprintf(fout,"\n");
}
fprintf(fout,"endplaytimes\n");
fclose(fout);
}
list<pair<time_t,time_t> >::iterator CPlrPersist::timesOverlap(time_t start, time_t end,bool testself)
{
list<pair<time_t,time_t> >::iterator it;
it=playtimes.begin();
for (it;it!=playtimes.end();++it)
{
time_t itFirst=it->first;
time_t itSecond=it->second;
if (start == it->first && end == it->second)
{
if (testself)
break;
}
//if start is in current range
else if (start >= it->first && start <= it->second)
break;
//if end is in current range
else if (end >= it->first && end <= it->second)
break;
//if the start is before this range and end is after
else if (start <= it->first && end >= it->second)
break;
}
return it;
}
string CPlrPersist::faveString(map<string,int>& theMap)
{
string retstr;
time_t max=0;
map<string,int>::iterator it=theMap.begin();
for (it;it!=theMap.end();++it)
{
if (it->second > max)
{
max=it->second;
retstr=it->first;
}
}
return retstr;
}
string CPlrPersist::faveName()
{
return faveString(nickmap);
}
string CPlrPersist::faveWeap()
{
string s=faveString(weapmap);
faveweapkills=weapmap[s];
return s;
}
string CPlrPersist::faveClass()
{
return faveString(classmap);
}
double CPlrPersist::rank()
{
return ((double)((double)kills - (double)deaths) * 1000.0) / (double)timeon;
}
+91
View File
@@ -0,0 +1,91 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#pragma warning (disable:4786)
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#ifndef PLRPERSIST_H
#define PLRPERSIST_H
#ifdef WIN32
#pragma once
#endif
#include <time.h>
#include <map>
#include <string>
#include <list>
#include <utility>
#include "TimeIndexedList.h"
#include "Player.h"
#include "TextFile.h"
using namespace std;
//------------------------------------------------------------------------------------------------------
// Purpose: Represents persistent player data. This class is used to save and load
// Player data from the disk.
//------------------------------------------------------------------------------------------------------
class CPlrPersist
{
public:
unsigned long WONID;
int kills;
int deaths;
time_t timeon;
bool valid;
string faveString(map<string,int>& theMap);
map<string,int> nickmap;
string faveName();
map<string,int> weapmap;
string faveWeap();
map<string,int> classmap;
string faveClass();
list<pair<time_t,time_t> > playtimes;
time_t lastplayed;
int matches;
int suicides;
int faveweapkills;
double rank();
CPlrPersist()
{
kills=deaths=suicides=faveweapkills=matches=0;WONID=-1;
}
void read(unsigned long WONID);
void read(CTextFile& f);
void merge(CPlrPersist& cpp,bool mergeOverlaps=false);
void generate(CPlayer& cp);
void write();
list<pair<time_t,time_t> >::iterator timesOverlap(time_t start, time_t end,bool testself=true);
};
#endif // PLRPERSIST_H
+50
View File
@@ -0,0 +1,50 @@
TFStats v2.0 readme file
v2.0 New Features
* Full search custom rules. Custom rules can now search every event in the log
and match based on regular expression matching patterns.
* General Rule File. TFStats now reads TFC.RUL in addition to any map specific
rule files so you can put any server-specific rules in tfc.rul.
* Persistent Player Statistics. Player's stats are now saved (if you so specify)
on the hard-disk and every time you generate a report more are saved and/or
merged (if a player's stats had already been saved). What this does is allow
player stats to accumulate over time, across many matches. This also has support
for omitting players who have been absent for a long time from the report.
* Stats Resume for Lan Games. Stats Resume now works on Lan games by matching IP
addresses. It will match by name if it cannot match by IP for some reason.
* Windows Front End. the Win32 version of TFStats now features an easy-to-use
Windows front end that automates generating several logs at once and provides
easy to use controls to control all of the new switches that TFStats supports and
the directories it reads from and writes to.
* Shared Report Resources. TFStats can now generate several reports that share
the same set of reports to preserve hard-drive space.
v2.0 Bug Fixes
*Players with < and > in their names now work properly.
*Multiline Broadcasts are now handled correctly.
v1.5 New Features
*Team Differentiation: If a player plays on two different teams, tfstats
gathers stats for each team seperately, then when viewing that players
stats, there's a link to that player's merged stats.
*Pseudonyms for players: This is so it's not confusing if players change their
names. it uses the name they used for the most time, and also lists other
names they used.
*DisplayMM2 switch: The user (the person who runs tfstats) can now choose if
they want to display team messages or not. a lot of clans e-mailed me asking
me to take out mm2 messages from the dialogue readout.
*Stats Resume: Disconnected players resume their stats where they left off
when they reconnect. This doesn't work in lan games because there is no
WONID to work with.
*Garbage handling: TFStats is more robust when it comes to garbage input now.
v1.5 Bug Fixes
*The team kill award now works
*medics don't get double kills anymore
*the dates are now correct
*RandomPC is now handled correctly
As always you can e-mail tfstats@valvesoftware.com with questions, comments
and feature suggestions. Read the TFStats manual for full documentation
Thanks for using TFStats!
+5
View File
@@ -0,0 +1,5 @@
#ifndef CREGEX_H
#include <jm/cregex.h>
#endif
+11
View File
@@ -0,0 +1,11 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef CREGEX_H
#include <jm/cregex.h>
#endif
+13
View File
@@ -0,0 +1,13 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef __FILEITER_H
#include <jm/fileiter.h>
#endif
+309
View File
@@ -0,0 +1,309 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE cregex.h
* VERSION 2.12
*/
#ifndef CREGEX_H
#define CREGEX_H
#include <jm/jm_cfg.h>
/* include these defs only for POSIX compatablity */
typedef int regoff_t;
typedef struct
{
unsigned int re_magic;
unsigned int re_nsub; /* number of parenthesized subexpressions */
const char* re_endp; /* end pointer for REG_PEND */
void* guts; /* none of your business :-) */
unsigned int eflags; /* none of your business :-) */
} regex_tA;
#ifndef JM_NO_WCSTRING
typedef struct
{
unsigned int re_magic;
unsigned int re_nsub; /* number of parenthesized subexpressions */
const wchar_t* re_endp; /* end pointer for REG_PEND */
void* guts; /* none of your business :-) */
unsigned int eflags; /* none of your business :-) */
} regex_tW;
#endif
typedef struct
{
regoff_t rm_so; /* start of match */
regoff_t rm_eo; /* end of match */
} regmatch_t;
/* regcomp() flags */
#define REG_BASIC 0000
#define REG_EXTENDED 0001
#define REG_ICASE 0002
#define REG_NOSUB 0004
#define REG_NEWLINE 0010
#define REG_NOSPEC 0020
#define REG_PEND 0040
#define REG_DUMP 0200
#define REG_NOCOLLATE 0400
#define REG_ASSERT 15
#define REG_INVARG 16
#define REG_ATOI 255 /* convert name to number (!) */
#define REG_ITOA 0400 /* convert number to name (!) */
/* regexec() flags */
#define REG_NOTBOL 00001
#define REG_NOTEOL 00002
#define REG_STARTEND 00004
#ifdef __cplusplus
extern "C" {
#endif
JM_IX_DECL int RE_CCALL regcompA(regex_tA*, const char*, int);
JM_IX_DECL unsigned int RE_CCALL regerrorA(int, const regex_tA*, char*, unsigned int);
JM_IX_DECL int RE_CCALL regexecA(const regex_tA*, const char*, unsigned int, regmatch_t*, int);
JM_IX_DECL void RE_CCALL regfreeA(regex_tA*);
#ifndef JM_NO_WCSTRING
JM_IX_DECL int RE_CCALL regcompW(regex_tW*, const wchar_t*, int);
JM_IX_DECL unsigned int RE_CCALL regerrorW(int, const regex_tW*, wchar_t*, unsigned int);
JM_IX_DECL int RE_CCALL regexecW(const regex_tW*, const wchar_t*, unsigned int, regmatch_t*, int);
JM_IX_DECL void RE_CCALL regfreeW(regex_tW*);
#endif
#ifdef UNICODE
#define regcomp regcompW
#define regerror regerrorW
#define regexec regexecW
#define regfree regfreeW
#define regex_t regex_tW
#else
#define regcomp regcompA
#define regerror regerrorA
#define regexec regexecA
#define regfree regfreeA
#define regex_t regex_tA
#endif
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
JM_NAMESPACE(__JM)
#endif
/* regerror() flags */
typedef enum
{
REG_NOERROR = 0, /* Success. */
REG_NOMATCH = 1, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
REG_BADPAT = 2, /* Invalid pattern. */
REG_ECOLLATE = 3, /* Undefined collating element. */
REG_ECTYPE = 4, /* Invalid character class name. */
REG_EESCAPE = 5, /* Trailing backslash. */
REG_ESUBREG = 6, /* Invalid back reference. */
REG_EBRACK = 7, /* Unmatched left bracket. */
REG_EPAREN = 8, /* Parenthesis imbalance. */
REG_EBRACE = 9, /* Unmatched \{. */
REG_BADBR = 10, /* Invalid contents of \{\}. */
REG_ERANGE = 11, /* Invalid range end. */
REG_ESPACE = 12, /* Ran out of memory. */
REG_BADRPT = 13, /* No preceding re for repetition op. */
REG_EEND = 14, /* unexpected end of expression */
REG_ESIZE = 15, /* expression too big */
REG_ERPAREN = 16, /* unmatched right parenthesis */
REG_EMPTY = 17, /* empty expression */
REG_E_MEMORY = 18, /* out of memory */
REG_E_UNKNOWN = 19 /* unknown error */
} reg_errcode_t;
enum match_flags
{
match_default = 0,
match_not_bol = 1, // first is not start of line
match_not_eol = match_not_bol << 1, // last is not end of line
match_not_bob = match_not_eol << 1, // first is not start of buffer
match_not_eob = match_not_bob << 1, // last is not end of buffer
match_not_bow = match_not_eob << 1, // first is not start of word
match_not_eow = match_not_bow << 1, // last is not end of word
match_not_dot_newline = match_not_eow << 1, // \n is not matched by '.'
match_not_dot_null = match_not_dot_newline << 1, // '\0' is not matched by '.'
match_prev_avail = match_not_dot_null << 1, // *--first is a valid expression
match_init = match_prev_avail << 1, // internal use
match_any = match_init << 1, // don't care what we match
match_not_null = match_any << 1, // string can't be null
match_continuous = match_not_null << 1, // each grep match must continue from
// uninterupted from the previous one
match_stop = match_continuous << 1 // stop after first match (grep)
};
#ifdef __cplusplus
JM_END_NAMESPACE
#endif
//
// C++ high level wrapper goes here:
//
#if defined(__cplusplus) && !defined(JM_NO_STRING_H)
#include <string>
#include <vector>
JM_NAMESPACE(__JM)
class RegExData;
class RegEx;
struct pred1;
struct pred2;
struct pred3;
struct pred4;
typedef bool (*GrepCallback)(const RegEx& expression);
typedef bool (*GrepFileCallback)(const char* file, const RegEx& expression);
typedef bool (*FindFilesCallback)(const char* file);
class JM_IX_DECL RegEx
{
private:
RegExData* pdata;
public:
RegEx();
RegEx(const RegEx& o);
~RegEx();
RegEx(const char* c, bool icase = false);
RegEx(const __JM_STD::string& s, bool icase = false);
RegEx& operator=(const RegEx& o);
RegEx& operator=(const char* p);
RegEx& operator=(const __JM_STD::string& s){ return this->operator=(s.c_str()); }
unsigned int SetExpression(const char* p, bool icase = false);
unsigned int SetExpression(const __JM_STD::string& s, bool icase = false){ return SetExpression(s.c_str(), icase); }
__JM_STD::string Expression()const;
//
// now matching operators:
//
bool Match(const char* p, unsigned int flags = match_default);
bool Match(const __JM_STD::string& s, unsigned int flags = match_default) { return Match(s.c_str(), flags); }
bool Search(const char* p, unsigned int flags = match_default);
bool Search(const __JM_STD::string& s, unsigned int flags = match_default) { return Search(s.c_str(), flags); }
unsigned int Grep(GrepCallback cb, const char* p, unsigned int flags = match_default);
unsigned int Grep(GrepCallback cb, const __JM_STD::string& s, unsigned int flags = match_default) { return Grep(cb, s.c_str(), flags); }
unsigned int Grep(__JM_STD::vector<__JM_STD::string>& v, const char* p, unsigned int flags = match_default);
unsigned int Grep(__JM_STD::vector<__JM_STD::string>& v, const __JM_STD::string& s, unsigned int flags = match_default) { return Grep(v, s.c_str(), flags); }
unsigned int Grep(__JM_STD::vector<unsigned int>& v, const char* p, unsigned int flags = match_default);
unsigned int Grep(__JM_STD::vector<unsigned int>& v, const __JM_STD::string& s, unsigned int flags = match_default) { return Grep(v, s.c_str(), flags); }
unsigned int GrepFiles(GrepFileCallback cb, const char* files, bool recurse = false, unsigned int flags = match_default);
unsigned int GrepFiles(GrepFileCallback cb, const __JM_STD::string& files, bool recurse = false, unsigned int flags = match_default) { return GrepFiles(cb, files.c_str(), recurse, flags); }
unsigned int FindFiles(FindFilesCallback cb, const char* files, bool recurse = false, unsigned int flags = match_default);
unsigned int FindFiles(FindFilesCallback cb, const __JM_STD::string& files, bool recurse = false, unsigned int flags = match_default) { return FindFiles(cb, files.c_str(), recurse, flags); }
//
// now operators for returning what matched in more detail:
//
unsigned int Position(int i = 0)const;
unsigned int Length(int i = 0)const;
unsigned int Line()const;
unsigned int Marks()const;
__JM_STD::string What(int i = 0)const;
__JM_STD::string operator[](int i)const { return What(i); }
friend struct pred1;
friend struct pred2;
friend struct pred3;
friend struct pred4;
};
JM_END_NAMESPACE
#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING) && defined(__cplusplus)
using __JM::RegEx;
using __JM::GrepCallback;
using __JM::GrepFileCallback;
using __JM::FindFilesCallback;
#endif
#endif // __cplusplus
#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING) && defined(__cplusplus)
using __JM::match_flags;
using __JM::reg_errcode_t;
using __JM::REG_NOERROR;
using __JM::REG_NOMATCH;
using __JM::REG_BADPAT;
using __JM::REG_ECOLLATE;
using __JM::REG_ECTYPE;
using __JM::REG_EESCAPE;
using __JM::REG_ESUBREG;
using __JM::REG_EBRACK;
using __JM::REG_EPAREN;
using __JM::REG_EBRACE;
using __JM::REG_BADBR;
using __JM::REG_ERANGE;
using __JM::REG_ESPACE;
using __JM::REG_BADRPT;
using __JM::REG_EEND;
using __JM::REG_ESIZE;
using __JM::REG_ERPAREN;
using __JM::REG_EMPTY;
using __JM::REG_E_MEMORY;
using __JM::REG_E_UNKNOWN;
using __JM::match_default;
using __JM::match_not_bol;
using __JM::match_not_eol;
using __JM::match_not_bob;
using __JM::match_not_eob;
using __JM::match_not_bow;
using __JM::match_not_eow;
using __JM::match_not_dot_newline;
using __JM::match_not_dot_null;
using __JM::match_prev_avail;
using __JM::match_init;
using __JM::match_any;
using __JM::match_not_null;
using __JM::match_continuous;
using __JM::match_stop;
#endif
#endif
+368
View File
@@ -0,0 +1,368 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
*
* FILE fileiter.h
* VERSION 2.12
*
* this file declares various platform independent file and directory
* iterators, plus binary file input in the form of class map_file.
*
*/
#ifndef __FILEITER_H
#define __FILEITER_H
#include <jm/jm_cfg.h>
#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32)) && !defined(JM_NO_WIN32)
#define FI_W32
#include <windows.h>
JM_NAMESPACE(__JM)
typedef WIN32_FIND_DATA _fi_find_data;
typedef HANDLE _fi_find_handle;
JM_END_NAMESPACE
#define _fi_invalid_handle INVALID_HANDLE_VALUE
#define _fi_dir FILE_ATTRIBUTE_DIRECTORY
#else
#include <stdio.h>
#include <ctype.h>
#ifndef JM_NO_STL
#include <iterator>
#include <list>
#if defined(__SUNPRO_CC) && !defined(JM_NO_NAMESPACES)
using __JM_STD::list;
#endif
#endif
#include <assert.h>
#include <dirent.h>
#ifndef MAX_PATH
#define MAX_PATH 256
#endif
JM_NAMESPACE(__JM)
struct _fi_find_data
{
unsigned dwFileAttributes;
char cFileName[MAX_PATH];
};
struct _fi_priv_data;
typedef _fi_priv_data* _fi_find_handle;
#define _fi_invalid_handle NULL
#define _fi_dir 1
_fi_find_handle _fi_FindFirstFile(const char* lpFileName, _fi_find_data* lpFindFileData);
bool _fi_FindNextFile(_fi_find_handle hFindFile, _fi_find_data* lpFindFileData);
bool _fi_FindClose(_fi_find_handle hFindFile);
JM_END_NAMESPACE
#ifdef FindFirstFile
#undef FindFirstFile
#endif
#ifdef FindNextFile
#undef FindNextFile
#endif
#ifdef FindClose
#undef FindClose
#endif
#define FindFirstFile _fi_FindFirstFile
#define FindNextFile _fi_FindNextFile
#define FindClose _fi_FindClose
#endif
JM_NAMESPACE(__JM)
#ifdef FI_W32 // win32 mapfile
class JM_IX_DECL mapfile
{
HANDLE hfile;
HANDLE hmap;
const char* _first;
const char* _last;
public:
typedef const char* iterator;
mapfile(){ hfile = hmap = 0; _first = _last = 0; }
mapfile(const char* file){ hfile = hmap = 0; _first = _last = 0; open(file); }
~mapfile(){ close(); }
void open(const char* file);
void close();
const char* begin(){ return _first; }
const char* end(){ return _last; }
size_t size(){ return _last - _first; }
bool valid(){ return (hfile != 0) && (hfile != INVALID_HANDLE_VALUE); }
};
#elif !defined(JM_NO_STL) // use POSIX API to emulate the memory map:
class JM_IX_DECL mapfile_iterator;
class JM_IX_DECL mapfile
{
typedef char* pointer;
FILE* hfile;
long int _size;
pointer* _first;
pointer* _last;
mutable __JM_STD::list<pointer*> condemed;
enum sizes
{
buf_size = 4096
};
void lock(pointer* node)const;
void unlock(pointer* node)const;
public:
typedef mapfile_iterator iterator;
mapfile(){ hfile = 0; _size = 0; _first = _last = 0; }
mapfile(const char* file){ hfile = 0; _size = 0; _first = _last = 0; open(file); }
~mapfile(){ close(); }
void open(const char* file);
void close();
iterator begin()const;
iterator end()const;
unsigned long size()const{ return _size; }
bool valid()const{ return hfile != 0; }
friend class mapfile_iterator;
};
class JM_IX_DECL mapfile_iterator : public JM_RA_ITERATOR(char, long)
{
typedef mapfile::pointer pointer;
pointer* node;
const mapfile* file;
unsigned long offset;
long position()const
{
return file ? ((node - file->_first) * mapfile::buf_size + offset) : 0;
}
void position(long pos)
{
if(file)
{
node = file->_first + (pos / mapfile::buf_size);
offset = pos % mapfile::buf_size;
}
}
public:
mapfile_iterator() { node = 0; file = 0; offset = 0; }
mapfile_iterator(const mapfile* f, long position)
{
file = f;
node = f->_first + position / mapfile::buf_size;
offset = position % mapfile::buf_size;
if(file)
file->lock(node);
}
mapfile_iterator(const mapfile_iterator& i)
{
file = i.file;
node = i.node;
offset = i.offset;
if(file)
file->lock(node);
}
~mapfile_iterator()
{
if(file && node)
file->unlock(node);
}
mapfile_iterator& operator = (const mapfile_iterator& i);
char operator* ()const
{
assert(node >= file->_first);
assert(node < file->_last);
return file ? *(*node + sizeof(int) + offset) : char(0);
}
mapfile_iterator& operator++ ();
mapfile_iterator operator++ (int);
mapfile_iterator& operator-- ();
mapfile_iterator operator-- (int);
mapfile_iterator& operator += (long off)
{
position(position() + off);
return *this;
}
mapfile_iterator& operator -= (long off)
{
position(position() - off);
return *this;
}
friend inline bool operator==(const mapfile_iterator& i, const mapfile_iterator& j)
{
return (i.file == j.file) && (i.node == j.node) && (i.offset == j.offset);
}
#ifndef JM_NO_NOT_EQUAL
friend inline bool operator!=(const mapfile_iterator& i, const mapfile_iterator& j)
{
return !(i == j);
}
#endif
friend inline bool operator<(const mapfile_iterator& i, const mapfile_iterator& j)
{
return i.position() < j.position();
}
friend mapfile_iterator operator + (const mapfile_iterator& i, long off);
friend mapfile_iterator operator - (const mapfile_iterator& i, long off);
friend inline long operator - (const mapfile_iterator& i, const mapfile_iterator& j)
{
return i.position() - j.position();
}
};
#endif
// _fi_sep determines the directory separator, either '\\' or '/'
JM_IX_DECL extern const char* _fi_sep;
struct file_iterator_ref
{
_fi_find_handle hf;
_fi_find_data _data;
long count;
};
class JM_IX_DECL file_iterator : public JM_INPUT_ITERATOR(const char*, __JM_STDC::ptrdiff_t)
{
char* _root;
char* _path;
char* ptr;
file_iterator_ref* ref;
public:
file_iterator();
file_iterator(const char* wild);
~file_iterator();
file_iterator(const file_iterator&);
file_iterator& operator=(const file_iterator&);
const char* root() { return _root; }
const char* path() { return _path; }
_fi_find_data* data() { return &(ref->_data); }
void next();
file_iterator& operator++() { next(); return *this; }
file_iterator operator++(int);
const char* operator*() { return path(); }
friend inline bool operator == (const file_iterator& f1, const file_iterator& f2)
{
return ((f1.ref->hf == _fi_invalid_handle) && (f1.ref->hf == _fi_invalid_handle));
}
#ifndef JM_NO_NOT_EQUAL
friend inline bool operator != (const file_iterator& f1, const file_iterator& f2)
{
return !(f1 == f2);
}
#endif
};
inline bool operator < (const file_iterator& f1, const file_iterator& f2)
{
return false;
}
class JM_IX_DECL directory_iterator : public JM_INPUT_ITERATOR(const char*, __JM_STDC::ptrdiff_t)
{
char* _root;
char* _path;
char* ptr;
file_iterator_ref* ref;
public:
directory_iterator();
directory_iterator(const char* wild);
~directory_iterator();
directory_iterator(const directory_iterator& other);
directory_iterator& operator=(const directory_iterator& other);
const char* root() { return _root; }
const char* path() { return _path; }
_fi_find_data* data() { return &(ref->_data); }
void next();
directory_iterator& operator++() { next(); return *this; }
directory_iterator operator++(int);
const char* operator*() { return path(); }
static const char* separator() { return _fi_sep; }
friend inline bool operator == (const directory_iterator& f1, const directory_iterator& f2)
{
return ((f1.ref->hf == _fi_invalid_handle) && (f1.ref->hf == _fi_invalid_handle));
}
#ifndef JM_NO_NOT_EQUAL
friend inline bool operator != (const directory_iterator& f1, const directory_iterator& f2)
{
return !(f1 == f2);
}
#endif
};
inline bool operator < (const directory_iterator& f1, const directory_iterator& f2)
{
return false;
}
JM_END_NAMESPACE
#if !defined(JM_NO_NAMESPACES) && !defined(JM_NO_USING)
using __JM::directory_iterator;
using __JM::file_iterator;
using __JM::mapfile;
#endif
#endif // __WINITER_H
File diff suppressed because it is too large Load Diff
+414
View File
@@ -0,0 +1,414 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef JM_OPT_H
#define JM_OPT_H
/* #define JM_AUTO_CONFIGURE */
#ifdef JM_AUTO_CONFIGURE
/* Namespace Options: */
/* JM_NO_NAMESPACES Define if your compiler does not support namespaces */
/* #define JM_NO_NAMESPACES */
/* __JM Defines the namespace used for this library,
defaults to "jm", but can be changed by defining
__JM on the command line. */
/* #define __JM */
/* __JM_STD Defines the namespace used by the underlying STL
(if any), defaults to "std", can be changed by
defining __JM_STD on the command line. */
/* #define __JM_STD */
/* __JM_STDC Defines the namespace used by the C Library defs.
Defaults to "std" as recomended by the latest
draft standard, can be redefined by defining
__JM_STDC on the command line. */
/* #define __JM_STDC */
/* Compiler options: */
/* JM_NO_EXCEPTIONS Disables exception handling support. */
/* #define JM_NO_EXCEPTIONS */
/* JM_NO_MUTABLE Disables use of mutable keyword. */
/* #define JM_NO_MUTABLE */
/* JM_INT32 The type for 32-bit integers - what C calls intfast32_t */
/* #define JM_INT32 */
/* JM_NO_DEFAULT_PARAM If templates can not have default parameters. */
/* #define JM_NO_DEFAULT_PARAM */
/* JM_NO_TRICKY_DEFAULT_PARAM If templates can not have derived default parameters. */
/* #define JM_NO_TRICKY_DEFAULT_PARAM */
/* JM_NO_TEMPLATE_TYPENAME If class scope typedefs of the form:
typedef typename X<T> Y;
where T is a template parameter to this,
do not compile unless the typename is omitted. */
/* #define JM_NO_TEMPLATE_TYPENAME */
/* JM_NO_TEMPLATE_FRIEND If template friend declarations are not supported */
/* #define JM_NO_TEMPLATE_FRIEND */
/* JM_PLATFORM_WINDOWS Platform is MS Windows. */
/* #define JM_PLATFORM_WINDOWS */
/* JM_PLATFORM_DOS Platform if MSDOS. */
/* #define JM_PLATFORM_DOS */
/* JM_PLATFORM_W32 Platform is MS Win32 */
/* #define JM_PLATFORM_W32 */
/* JM_NO_WIN32 Disable Win32 support even when present */
/* #define JM_NO_WIN32 */
/* JM_NO_BOOL If bool is not a distict type. */
/* #define JM_NO_BOOL */
/* JM_NO_WCHAR_H If there is no <wchar.h> */
/* #define JM_NO_WCHAR_H */
/* JM_NO_WCTYPE_H If there is no <wctype.h> */
/* #define JM_NO_WCTYPE_H */
/* JM_NO_WCSTRING If there are no wcslen and wcsncmp functions available. */
/* #define JM_NO_WCSTRING */
/* JM_NO_SWPRINTF If there is no swprintf available. */
/* #define JM_NO_SWPRINTF */
/* JM_NO_WSPRINTF If there is no wsprintf available. */
/* #define JM_NO_WSPRINTF */
/* JM_NO_MEMBER_TEMPLATES If member function templates or nested template classes are not allowed. */
/* #define JM_NO_MEMBER_TEMPLATES */
/* JM_NO_TEMPLATE_RETURNS If template functions based on return type are not supported. */
/* #define JM_NO_TEMPLATE_RETURNS */
/* JM_NO_PARTIAL_FUNC_SPEC If partial template function specialisation is not supported */
/* #define JM_NO_PARTIAL_FUNC_SPEC */
/* JM_NO_INT64 If 64bit integers are not supported. */
/* JM_INT64t The type of a 64-bit signed integer if available. */
/* JM_IMM64(val) Declares a 64-bit immediate value by appending any
necessary suffix to val. */
/* JM_INT64_T 0 = NA
1 = short
2 = int
3 = long
4 = int64_t
5 = long long
6 = __int64 */
/* #define JM_INT64_T */
/* JM_NO_CAT Define if the compiler does not support POSIX style
message categories (catopen catgets catclose). */
/* #define JM_NO_CAT */
/* JM_THREADS Define if the compiler supports multiple threads in
the current translation mode. */
/* #define JM_THREADS */
/* JM_TEMPLATE_SPECIALISE Defaults to template<> , ie the template specialisation
prefix, can be redefined to nothing for older compilers. */
/* #define JM_TEMPLATE_SPECIALISE */
/* JM_NESTED_TEMPLATE_DECL Defaults to template, the standard prefix when accessing
nested template classes, can be redefined to nothing if
the compiler does not support this. */
/* #define JM_NESTED_TEMPLATE_DECL */
/* JM_NO_TEMPLATE_INST If explicit template instantiation with the "template class X<T>"
syntax is not supported */
/* #define JM_NO_TEMPLATE_INST */
/* JM_NO_TEMPLATE_MERGE If template in separate translation units don't merge at link time */
/* #define JM_NO_TEMPLATE_MERGE */
/* JM_NO_TEMPLATE_MERGE_A If template merging from library archives is not supported */
/* #define JM_NO_TEMPLATE_MERGE_A */
/* JM_NO_TEMPLATE_SWITCH_MERGE If merging of templates containing switch statements is not supported */
/* #define JM_NO_TEMPLATE_SWITCH_MERGE */
/* RE_CALL Optionally define a calling convention for C++ functions */
/* #define RE_CALL */
/* RE_CCALL Optionally define a calling convention for C functions */
/* #define RE_CCALL */
/* JM_SIZEOF_SHORT sizeof(short) */
/* #define JM_SIZEOF_SHORT */
/* JM_SIZEOF_INT sizeof(int) */
/* #define JM_SIZEOF_INT */
/* JM_SIZEOF_LONG sizeof(long) */
/* #define JM_SIZEOF_LONG */
/* JM_SIZEOF_WCHAR_T sizeof(wchar_t) */
/* #define JM_SIZEOF_WCHAR_T */
/* STL options: */
/* JM_NO_EXCEPTION_H Define if you do not a compliant <exception>
header file. */
/* #define JM_NO_EXCEPTION_H */
/* JM_NO_ITERATOR_H Define if you do not have a version of <iterator>. */
/* #define JM_NO_ITERATOR_H */
/* JM_NO_MEMORY_H Define if <memory> does not fully comply with the
latest standard, and is not auto-recognised,
that means nested template classes
which hardly any compilers support at present. */
/* #define JM_NO_MEMORY_H */
/* JM_NO_LOCALE_H Define if there is no verion of the standard
<locale> header available. */
/* #define JM_NO_LOCALE_H */
/* JM_NO_STL Disables the use of any supporting STL code. */
/* #define JM_NO_STL */
/* JM_NO_NOT_EQUAL Disables the generation of operator!= if this
clashes with the STL version. */
/* JM_NO_STRING_H Define if <string> not available */
/* #define JM_NO_STRING_H */
/* JM_NO_STRING_DEF_ARGS Define if std::basic_string<charT> not allowed - in
other words if the template is missing its required
default arguments. */
/* #define JM_NO_STRING_DEF_ARGS */
/* JM_NO_TYPEINFO Define if <typeinfo> is absent or non-standard */
/* #define JM_NO_TYPEINFO */
/* JM_USE_ALGO If <algo.h> not <algorithm> is present */
/* #define JM_USE_ALGO */
/* JM_OLD_IOSTREAM If the new iostreamm classes are not available */
/* #define JM_OLD_IOSTREAM */
/* JM_DISTANCE_T For std::distance:
0 = NA
1 = std::distance(i, j, n)
2 = n = std::distance(i, j) */
/* #define JM_DISTANCE_T */
/* JM_ITERATOR_T Defines generic standard iterator type if available, use this as
a shortcut to define all the other iterator types.
1 = __JM_STD::iterator<__JM_STD::tag_type, T, D, T*, T&>
2 = __JM_STD::iterator<__JM_STD::tag_type, T, D> */
/* #define JM_ITERATOR_T */
/* JM_OI_T For output iterators:
0 = NA
1 = __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D, T*, T&>
2 = __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D>
3 = __JM_STD::output_iterator */
/* #define JM_OI_T */
/* JM_II_T For input iterators:
0 = NA
1 = __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D, T*, T&>
2 = __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D>
3 = __JM_STD::input_iterator<T, D>
4 = __JM_STD::input_iterator<T> */
/* #define JM_II_T */
/* JM_FI_T For forward iterators:
0 = NA
1 = __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D, T*, T&>
2 = __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D>
3 = __JM_STD::forward_iterator<T, D> */
/* #define JM_FI_T */
/* JM_BI_T For bidirectional iterators:
0 = NA
1 = __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D, T*, T&>
2 = __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D>
3 = __JM_STD::bidirectional_iterator<T, D> */
/* #define JM_BI_T */
/* JM_RI_T For random access iterators:
0 = NA
1 = __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D, T*, T&>
2 = __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D>
3 = __JM_STD::random_access_iterator<T, D> */
/* #define JM_RI_T */
/* JM_NO_OI_ASSIGN If output iterators ostream_iterator<>, back_insert_iterator<> and
front_insert_iterator<> do not have assignment operators */
/* #define JM_NO_OI_ASSIGN */
#if JM_INT64_T == 0
#define JM_NO_INT64
#elif JM_INT64_T == 1
#define JM_INT64t short
#define JM_IMM64(val) val
#elif JM_INT64_T == 2
#define JM_INT64t int
#define JM_IMM64(val) val
#elif JM_INT64_T == 3
#define JM_INT64t long
#define JM_IMM64(val) val##L
#elif JM_INT64_T == 4
#define JM_INT64t int64_t
#define JM_IMM64(val) INT64_C(val)
#elif JM_INT64_T == 5
#define JM_INT64t long long
#define JM_IMM64(val) val##LL
#elif JM_INT64_T == 6
#define JM_INT64t __int64
#define JM_IMM64(val) val##i64
#else
syntax error: unknown value for JM_INT64_T
#endif
#if JM_DISTANCE_T == 0
# define JM_DISTANCE(i, j, n) n = j - i
#elif JM_DISTANCE_T == 1
# define JM_DISTANCE(i, j, n) n = __JM_STD::distance(i, j)
#elif JM_DISTANCE_T == 2
# define JM_DISTANCE(i, j, n) (n = 0, __JM_STD::distance(i, j, n))
#else
syntax erorr
#endif
#ifdef JM_ITERATOR_T
#ifndef JM_OI_T
#define JM_OI_T JM_ITERATOR_T
#endif
#ifndef JM_II_T
#define JM_II_T JM_ITERATOR_T
#endif
#ifndef JM_FI_T
#define JM_FI_T JM_ITERATOR_T
#endif
#ifndef JM_BI_T
#define JM_BI_T JM_ITERATOR_T
#endif
#ifndef JM_RI_T
#define JM_RI_T JM_ITERATOR_T
#endif
#endif
#if JM_OI_T == 0
# define JM_OUTPUT_ITERATOR(T, D) dummy_iterator_base<T>
#elif JM_OI_T == 1
# define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D, T*, T&>
#elif JM_OI_T == 2
# define JM_OUTPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::output_iterator_tag, T, D>
#elif JM_OI_T == 3
# define JM_OUTPUT_ITERATOR(T, D) __JM_STD::output_iterator
#else
syntax error
#endif
#if JM_II_T == 0
# define JM_INPUT_ITERATOR(T, D) dummy_iterator_base<T>
#elif JM_II_T == 1
#define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D, T*, T&>
#elif JM_II_T == 2
#define JM_INPUT_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::input_iterator_tag, T, D>
#elif JM_II_T == 3
# define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T, D>
#elif JM_II_T == 4
# define JM_INPUT_ITERATOR(T, D) __JM_STD::input_iterator<T>
#else
syntax error
#endif
#if JM_FI_T == 0
# define JM_FWD_ITERATOR(T, D) dummy_iterator_base<T>
#elif JM_FI_T == 1
# define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D, T*, T&>
#elif JM_FI_T == 2
# define JM_FWD_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::forward_iterator_tag, T, D>
#elif JM_FI_T == 3
# define JM_FWD_ITERATOR(T, D) __JM_STD::forward_iterator<T, D>
#else
syntax error
#endif
#if JM_BI_T == 0
# define JM_BIDI_ITERATOR(T, D) dummy_iterator_base<T>
#elif JM_BI_T == 1
# define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D, T*, T&>
#elif JM_BI_T == 2
# define JM_BIDI_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::bidirectional_iterator_tag, T, D>
#elif JM_BI_T == 3
# define JM_BIDI_ITERATOR(T, D) __JM_STD::bidirectional_iterator<T, D>
#else
syntax error
#endif
#if JM_RI_T == 0
# define JM_RA_ITERATOR(T, D) dummy_iterator_base<T>
#elif JM_RI_T == 1
# define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D, T*, T&>
#elif JM_RI_T == 2
# define JM_RA_ITERATOR(T, D) __JM_STD::iterator<__JM_STD::random_access_iterator_tag, T, D>
#elif JM_RI_T == 3
# define JM_RA_ITERATOR(T, D) __JM_STD::random_access_iterator<T, D>
#else
syntax error
#endif
#ifndef JM_NO_EXCEPTION_H
#include <exception>
#endif
#ifndef JM_NO_ITERATOR_H
#include <iterator>
#ifdef JM_USE_ALGO
#include <algo.h>
#else
#include <algorithm>
#endif
#endif
#ifdef JM_NO_MEMORY_H
#define JM_OLD_ALLOCATORS
#define REBIND_INSTANCE(x, y, inst) re_alloc_binder<x, y>(inst)
#define REBIND_TYPE(x, y) re_alloc_binder<x, y>
#define JM_DEF_ALLOC_PARAM(x) JM_DEFAULT_PARAM( jm_def_alloc )
#define JM_DEF_ALLOC(x) jm_def_alloc
#define JM_NEED_BINDER
#define JM_NEED_ALLOC
#else
#include <memory>
#define REBIND_INSTANCE(x, y, inst) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other(inst)
#define REBIND_TYPE(x, y) y::JM_NESTED_TEMPLATE_DECL rebind<x>::other
#define JM_DEF_ALLOC_PARAM(x) JM_TRICKY_DEFAULT_PARAM( __JM_STD::allocator<x> )
#define JM_DEF_ALLOC(x) __JM_STD::allocator<x>
#endif
#endif // JM_AUTO_CONFIGURE
#endif /* JM_OPT_H */
+209
View File
@@ -0,0 +1,209 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE jstack.h
* VERSION 2.12
*/
#ifndef __JSTACH_H
#define __JSTACK_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
JM_NAMESPACE(__JM)
//
// class jstack
// simplified stack optimised for push/peek/pop
// operations, we could use std::stack<std::vector<T>> instead...
//
template <class T, class Allocator JM_DEF_ALLOC_PARAM(T) >
class jstack
{
private:
typedef JM_MAYBE_TYPENAME REBIND_TYPE(unsigned char, Allocator) alloc_type;
typedef typename REBIND_TYPE(T, Allocator)::size_type size_type;
struct node
{
node* next;
T* start; // first item
T* end; // last item
T* last; // end of storage
};
//
// empty base member optimisation:
struct data : public alloc_type
{
unsigned char buf[sizeof(T)*16];
data(const Allocator& a) : alloc_type(a){}
};
data alloc_inst;
mutable node* stack;
mutable node* unused;
node base;
size_type block_size;
void RE_CALL pop_aux()const;
void RE_CALL push_aux();
public:
jstack(size_type n = 64, const Allocator& a = Allocator());
~jstack();
node* RE_CALL get_node()
{
node* new_stack = (node*)alloc_inst.allocate(sizeof(node) + sizeof(T) * block_size);
new_stack->last = (T*)(new_stack+1);
new_stack->start = new_stack->end = new_stack->last + block_size;
new_stack->next = 0;
return new_stack;
}
bool RE_CALL empty()
{
return (stack->start == stack->end) && (stack->next == 0);
}
bool RE_CALL good()
{
return (stack->start != stack->end) || (stack->next != 0);
}
T& RE_CALL peek()
{
if(stack->start == stack->end)
pop_aux();
return *stack->end;
}
const T& RE_CALL peek()const
{
if(stack->start == stack->end)
pop_aux();
return *stack->end;
}
void RE_CALL pop()
{
if(stack->start == stack->end)
pop_aux();
jm_destroy(stack->end);
++(stack->end);
}
void RE_CALL pop(T& t)
{
if(stack->start == stack->end)
pop_aux();
t = *stack->end;
jm_destroy(stack->end);
++(stack->end);
}
void RE_CALL push(const T& t)
{
if(stack->end == stack->last)
push_aux();
--(stack->end);
jm_construct(stack->end, t);
}
};
template <class T, class Allocator>
jstack<T, Allocator>::jstack(size_type n, const Allocator& a)
: alloc_inst(a)
{
unused = 0;
block_size = n;
stack = &base;
base.last = (T*)alloc_inst.buf;
base.end = base.start = base.last + 16;
base.next = 0;
}
template <class T, class Allocator>
void RE_CALL jstack<T, Allocator>::push_aux()
{
// make sure we have spare space on TOS:
register node* new_node;
if(unused)
{
new_node = unused;
unused = new_node->next;
new_node->next = stack;
stack = new_node;
}
else
{
new_node = get_node();
new_node->next = stack;
stack = new_node;
}
}
template <class T, class Allocator>
void RE_CALL jstack<T, Allocator>::pop_aux()const
{
// make sure that we have a valid item
// on TOS:
jm_assert(stack->next);
register node* p = stack;
stack = p->next;
p->next = unused;
unused = p;
}
template <class T, class Allocator>
jstack<T, Allocator>::~jstack()
{
node* condemned;
while(good())
pop();
while(unused)
{
condemned = unused;
unused = unused->next;
alloc_inst.deallocate((unsigned char*)condemned, sizeof(node) + sizeof(T) * block_size);
}
while(stack != &base)
{
condemned = stack;
stack = stack->next;
alloc_inst.deallocate((unsigned char*)condemned, sizeof(node) + sizeof(T) * block_size);
}
}
JM_END_NAMESPACE
#endif
+79
View File
@@ -0,0 +1,79 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_cls.h
* VERSION 2.12
* This is an internal header file, do not include directly.
* character class lookup, for regular
* expression library.
*/
#ifndef RE_CLS_H
#define RE_CLS_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#ifndef RE_STR_H
#include <jm/re_str.h>
#endif
JM_NAMESPACE(__JM)
#define re_classes_max 14
void RE_CALL re_init_classes();
void RE_CALL re_free_classes();
void RE_CALL re_update_classes();
JM_IX_DECL jm_uintfast32_t RE_CALL __re_lookup_class(const char* p);
inline jm_uintfast32_t RE_CALL re_lookup_class(const char* first, const char* last)
{
re_str<char> s(first, last);
return __re_lookup_class(s.c_str());
}
#ifndef JM_NO_WCSTRING
inline jm_uintfast32_t RE_CALL re_lookup_class(const wchar_t* first, const wchar_t* last)
{
re_str<wchar_t> s(first, last);
unsigned int len = re_strnarrow((char*)NULL, 0, s.c_str());
auto_array<char> buf(new char[len]);
re_strnarrow((char*)buf, len, s.c_str());
len = __re_lookup_class((char*)buf);
return len;
}
#endif
#ifdef RE_LOCALE_CPP
extern jm_uintfast32_t re_char_class_id[];
extern const char* re_char_class_names[];
#endif
JM_END_NAMESPACE
#endif
+61
View File
@@ -0,0 +1,61 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_coll.h
* VERSION 2.12
* This is an internal header file, do not include directly
*/
#ifndef RE_COLL_H
#define RE_COLL_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#ifndef RE_STR_H
#include <re_str.h>
#endif
JM_NAMESPACE(__JM)
JM_IX_DECL bool RE_CALL re_lookup_def_collate_name(re_str<char>& buf, const char* name);
void RE_CALL re_init_collate();
void RE_CALL re_free_collate();
void RE_CALL re_update_collate();
JM_IX_DECL bool RE_CALL __re_lookup_collate(re_str<char>& buf, const char* p);
inline bool RE_CALL re_lookup_collate(re_str<char>& buf, const char* first, const char* last)
{
re_str<char> s(first, last);
return __re_lookup_collate(buf, s.c_str());
}
#ifndef JM_NO_WCSTRING
JM_IX_DECL bool RE_CALL re_lookup_collate(re_str<wchar_t>& out, const wchar_t* first, const wchar_t* last);
#endif
JM_END_NAMESPACE
#endif
+112
View File
@@ -0,0 +1,112 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_kmp.h
* VERSION 2.12
* Knuth-Morris-Pratt search.
*/
#ifndef __RE_KMP_H
#define __RE_KMP_H
#ifdef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
JM_NAMESPACE(__JM)
template <class charT>
struct kmp_info
{
unsigned int size;
unsigned int len;
const charT* pstr;
int kmp_next[1];
};
template <class charT, class Allocator>
void kmp_free(kmp_info<charT>* pinfo, Allocator a)
{
typedef JM_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) atype;
atype(a).deallocate((char*)pinfo, pinfo->size);
}
template <class iterator, class charT, class Trans, class Allocator>
kmp_info<charT>* kmp_compile(iterator first, iterator last, charT, Trans translate, Allocator a
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
typedef JM_MAYBE_TYPENAME REBIND_TYPE(char, Allocator) atype;
int i, j, m;
i = 0;
m = 0;
JM_DISTANCE(first, last, m);
++m;
unsigned int size = sizeof(kmp_info<charT>) + sizeof(int)*m + sizeof(charT)*m;
--m;
//
// allocate struct and fill it in:
//
kmp_info<charT>* pinfo = (kmp_info<charT>*)atype(a).allocate(size);
pinfo->size = size;
pinfo->len = m;
charT* p = (charT*)((char*)pinfo + sizeof(kmp_info<charT>) + sizeof(int)*(m+1));
pinfo->pstr = p;
while(first != last)
{
*p = translate(*first MAYBE_PASS_LOCALE(l));
++first;
++p;
}
*p = 0;
//
// finally do regular kmp compile:
//
j = pinfo->kmp_next[0] = -1;
while (i < m)
{
while ((j > -1) && (pinfo->pstr[i] != pinfo->pstr[j]))
j = pinfo->kmp_next[j];
++i;
++j;
if (pinfo->pstr[i] == pinfo->pstr[j])
pinfo->kmp_next[i] = pinfo->kmp_next[j];
else
pinfo->kmp_next[i] = j;
}
return pinfo;
}
JM_END_NAMESPACE // namespace regex
#endif // __RE_KMP_H
+155
View File
@@ -0,0 +1,155 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_lib.h
* VERSION 2.12
* Automatic library file inclusion.
*/
#ifndef RE_LIB_H
#define RE_LIB_H
#if defined(_MSC_VER) && !defined(RE_BUILD_DLL)
#ifdef _DLL
#ifdef _DEBUG
#pragma comment(lib, "mre200dl.lib")
#else // DEBUG
#pragma comment(lib, "mre200l.lib")
#endif // _DEBUG
#else // _DLL
#ifdef _MT
#ifdef _DEBUG
#pragma comment(lib, "mre200dm.lib")
#else //_DEBUG
#pragma comment(lib, "mre200m.lib")
#endif //_DEBUG
#else //_MT
#ifdef _DEBUG
#pragma comment(lib, "mre200d.lib")
#else //_DEBUG
#pragma comment(lib, "mre200.lib")
#endif //_DEBUG
#endif //_MT
#endif //_DLL
#endif //_MSC_VER
#if defined(__BORLANDC__) && !defined(RE_BUILD_DLL)
#if (__BORLANDC__ > 0x520) && !defined(_NO_VCL)
#define JM_USE_VCL
#endif
#if __BORLANDC__ <= 0x520
#ifdef JM_USE_VCL
#ifdef _RTLDLL
#pragma comment(lib, "b2re200lv.lib")
#else
#pragma comment(lib, "b2re200v.lib")
#endif
#else // VCL
#ifdef _RTLDLL
#ifdef __MT__
#pragma comment(lib, "b2re200lm.lib")
#else // __MT__
#pragma comment(lib, "b2re200l.lib")
#endif // __MT__
#else //_RTLDLL
#ifdef __MT__
#pragma comment(lib, "b2re200m.lib")
#else // __MT__
#pragma comment(lib, "b2re200.lib")
#endif // __MT__
#endif // _RTLDLL
#endif // VCL
#elif __BORLANDC__ <= 0x530
#ifdef JM_USE_VCL
#ifdef _RTLDLL
#pragma comment(lib, "b3re200lv.lib")
#else
#pragma comment(lib, "b3re200v.lib")
#endif
#else // VCL
#ifdef _RTLDLL
#ifdef __MT__
#pragma comment(lib, "b3re200lm.lib")
#else // __MT__
#pragma comment(lib, "b3re200l.lib")
#endif // __MT__
#else //_RTLDLL
#ifdef __MT__
#pragma comment(lib, "b3re200m.lib")
#else // __MT__
#pragma comment(lib, "b3re200.lib")
#endif // __MT__
#endif // _RTLDLL
#endif // VCL
#else // Version: 0x540
#ifdef JM_USE_VCL
#ifdef _RTLDLL
#pragma comment(lib, "b4re200lv.lib")
#else
#pragma comment(lib, "b4re200v.lib")
#endif
#else // VCL
#ifdef _RTLDLL
#ifdef __MT__
#pragma comment(lib, "b4re200lm.lib")
#else // __MT__
#pragma comment(lib, "b4re200l.lib")
#endif // __MT__
#else //_RTLDLL
#ifdef __MT__
#pragma comment(lib, "b4re200m.lib")
#else // __MT__
#pragma comment(lib, "b4re200.lib")
#endif // __MT__
#endif // _RTLDLL
#endif // VCL
#endif
#endif //__BORLANDC__
#endif // RE_LIB_H
+184
View File
@@ -0,0 +1,184 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_lst.h
* VERSION 2.12
* This is an internal header file, do not include directly.
* re_list support class, for regular
* expression library.
*/
#ifndef RE_LST_H
#define RE_LST_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#include <new.h>
JM_NAMESPACE(__JM)
template <class T, class Allocator>
class re_list
{
public:
struct node
{
node* next;
T t;
node(const T& o) : t(o) {}
};
public:
class iterator
{
node* pos;
public:
iterator() { pos = 0; }
~iterator() {}
iterator(const iterator& i) { pos = i.pos; }
iterator(node* n) { pos = n; }
iterator& operator=(const iterator& i)
{
pos = i.pos;
return *this;
}
bool operator==(iterator& i)
{
return pos == i.pos;
}
bool operator!=(iterator& i)
{
return pos != i.pos;
}
T& operator*() { return pos->t; }
iterator& operator++()
{
pos = pos->next;
return *this;
}
iterator operator++(int)
{
iterator t(*this);
pos = pos->next;
return t;
}
const node* tell()const
{
return pos;
}
};
class const_iterator
{
const node* pos;
public:
const_iterator() { pos = 0; }
~const_iterator() {}
const_iterator(const const_iterator& i) { pos = i.pos; }
const_iterator(const iterator& i) { pos = i.tell(); }
const_iterator(const node* n) { pos = n; }
const_iterator& operator=(const iterator& i)
{
pos = i.tell();
return *this;
}
const_iterator& operator=(const const_iterator& i)
{
pos = i.pos;
return *this;
}
bool operator==(const_iterator& i)
{
return pos == i.pos;
}
bool operator!=(const_iterator& i)
{
return pos != i.pos;
}
const T& operator*() { return pos->t; }
const_iterator& operator++()
{
pos = pos->next;
return *this;
}
const_iterator operator++(int)
{
const_iterator t(*this);
pos = pos->next;
return t;
}
};
private:
typedef JM_MAYBE_TYPENAME REBIND_TYPE(node, Allocator) node_alloc;
struct data : public node_alloc
{
node* first;
data(const Allocator& a) : node_alloc(a), first(0) {}
};
data alloc_inst;
public:
re_list(const Allocator& a = Allocator()) : alloc_inst(a) {}
~re_list() { clear(); }
iterator RE_CALL begin() { return iterator(alloc_inst.first); }
iterator RE_CALL end() { return iterator(0); }
const_iterator RE_CALL begin()const { return const_iterator(alloc_inst.first); }
const_iterator RE_CALL end()const { return const_iterator(0); }
void RE_CALL add(const T& t)
{
node* temp;
temp = alloc_inst.allocate(1);
#ifndef JM_NO_EXCEPTIONS
try{
#endif
alloc_inst.construct(temp, t);
#ifndef JM_NO_EXCEPTIONS
}catch(...){ alloc_inst.deallocate(temp, 1); throw; }
#endif
temp->next = alloc_inst.first;
alloc_inst.first = temp;
}
void RE_CALL clear();
};
template <class T, class Allocator>
void RE_CALL re_list<T, Allocator>::clear()
{
node* temp;
while(alloc_inst.first)
{
temp = alloc_inst.first;
alloc_inst.first = alloc_inst.first->next;
alloc_inst.destroy(temp);
alloc_inst.deallocate(temp, 1);
}
}
JM_END_NAMESPACE
#endif
+90
View File
@@ -0,0 +1,90 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_mss.h
* VERSION 2.12
* This is an internal header file, do not include directly.
* Message helper functions, for regular
* expression library.
*/
#ifndef RE_MSS_H
#define RE_MSS_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
JM_NAMESPACE(__JM)
//
// re_get_message
// returns required buffer size if len is zero
// otherwise fills in buf.
//
JM_IX_DECL unsigned int RE_CALL re_get_default_message(char* buf, unsigned int len, unsigned int id);
JM_IX_DECL unsigned int RE_CALL __re_get_message(char* buf, unsigned int len, unsigned int id);
template <class charT>
unsigned int RE_CALL re_get_message(charT* buf, unsigned int len, unsigned int id)
{
unsigned int size = __re_get_message((char*)0, 0, id);
if(len < size)
return size;
auto_array<char> cb(new char[size]);
__re_get_message((char*)cb, size, id);
size = re_strwiden(buf, len, (char*)cb);
return size;
}
inline unsigned int RE_CALL re_get_message(char* buf, unsigned int len, unsigned int id)
{
return __re_get_message(buf, len, id);
}
//
// declare message initialisers:
//
void RE_CALL re_message_init();
void RE_CALL re_message_update();
void RE_CALL re_message_free();
#ifdef RE_LOCALE_CPP
__JM_STD::messages<char>::string_type RE_CALL re_get_def_message(unsigned int i);
__JM_STD::messages<wchar_t>::string_type RE_CALL re_get_def_message_w(unsigned int i);
extern const char *re_default_error_messages[];
#endif
JM_END_NAMESPACE
#endif
+371
View File
@@ -0,0 +1,371 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_nls.h
* VERSION 2.12
* This is an internal header file, do not include directly
*/
#ifndef RE_NLS_H
#define RE_NLS_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#ifdef RE_LOCALE_CPP
#include <jm/regfac.h>
#endif
#include <limits.h>
JM_NAMESPACE(__JM)
enum char_class_type
{
#ifdef RE_LOCALE_CPP
char_class_none = 0,
char_class_alnum = __JM_STD::ctype_base::alnum,
char_class_alpha = __JM_STD::ctype_base::alpha,
char_class_cntrl = __JM_STD::ctype_base::cntrl,
char_class_digit = __JM_STD::ctype_base::digit,
char_class_graph = __JM_STD::ctype_base::graph,
char_class_lower = __JM_STD::ctype_base::lower,
char_class_print = __JM_STD::ctype_base::print,
char_class_punct = __JM_STD::ctype_base::punct,
char_class_space = __JM_STD::ctype_base::space,
char_class_upper = __JM_STD::ctype_base::upper,
char_class_xdigit = __JM_STD::ctype_base::xdigit,
char_class_blank = 1<<12,
char_class_underscore = 1<<13,
char_class_word = __JM_STD::ctype_base::alnum | char_class_underscore,
char_class_unicode = 1<<14,
char_class_all_base = char_class_alnum | char_class_alpha | char_class_cntrl
| char_class_digit | char_class_graph | char_class_lower
| char_class_print | char_class_punct | char_class_space
| char_class_upper | char_class_xdigit
#elif defined(RE_LOCALE_W32)
char_class_none = 0,
char_class_alnum = C1_ALPHA | C1_DIGIT,
char_class_alpha = C1_ALPHA,
char_class_cntrl = C1_CNTRL,
char_class_digit = C1_DIGIT,
char_class_graph = C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_ALPHA,
char_class_lower = C1_LOWER,
char_class_print = C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_BLANK | C1_ALPHA,
char_class_punct = C1_PUNCT,
char_class_space = C1_SPACE,
char_class_upper = C1_UPPER,
char_class_xdigit = C1_XDIGIT,
char_class_blank = C1_BLANK,
char_class_underscore = 0x0200,
char_class_word = C1_ALPHA | C1_DIGIT | char_class_underscore,
char_class_unicode = 0x0400
#else
char_class_none = 0,
char_class_alpha = 1,
char_class_cntrl = char_class_alpha << 1,
char_class_digit = char_class_cntrl << 1,
char_class_lower = char_class_digit << 1,
char_class_punct = char_class_lower << 1,
char_class_space = char_class_punct << 1,
char_class_upper = char_class_space << 1,
char_class_xdigit = char_class_upper << 1,
char_class_blank = char_class_xdigit << 1,
char_class_unicode = char_class_blank << 1,
char_class_underscore = char_class_unicode << 1,
char_class_alnum = char_class_alpha | char_class_digit,
char_class_graph = char_class_alpha | char_class_digit | char_class_punct | char_class_underscore,
char_class_print = char_class_alpha | char_class_digit | char_class_punct | char_class_underscore | char_class_blank,
char_class_word = char_class_alpha | char_class_digit | char_class_underscore
#endif
};
//
// declare our initialise class and functions:
//
template <class charT>
class re_initialiser
{
public:
void update();
};
JM_IX_DECL void RE_CALL re_init();
JM_IX_DECL void RE_CALL re_update();
JM_IX_DECL void RE_CALL re_free();
JM_IX_DECL void RE_CALL re_init_w();
JM_IX_DECL void RE_CALL re_update_w();
JM_IX_DECL void RE_CALL re_free_w();
JM_TEMPLATE_SPECIALISE
class re_initialiser<char>
{
public:
re_initialiser() { re_init(); }
~re_initialiser() { re_free(); }
void RE_CALL update() { re_update(); }
};
#ifndef JM_NO_WCSTRING
JM_TEMPLATE_SPECIALISE
class re_initialiser<wchar_t>
{
public:
re_initialiser() { re_init_w(); }
~re_initialiser() { re_free_w(); }
void RE_CALL update() { re_update_w(); }
};
#endif
//
// start by declaring externals for RE_LOCALE_C
// and RE_LOCALE_W32:
//
JM_IX_DECL extern unsigned char re_syntax_map[];
JM_IX_DECL extern unsigned short re_class_map[];
JM_IX_DECL extern char re_lower_case_map[];
JM_IX_DECL extern char re_zero;
JM_IX_DECL extern char re_ten;
#ifndef JM_NO_WCSTRING
JM_IX_DECL extern unsigned short re_unicode_classes[];
JM_IX_DECL extern const wchar_t* re_lower_case_map_w;
JM_IX_DECL extern wchar_t re_zero_w;
JM_IX_DECL extern wchar_t re_ten_w;
JM_IX_DECL wchar_t RE_CALL re_wtolower(wchar_t c);
JM_IX_DECL bool RE_CALL re_iswclass(wchar_t c, jm_uintfast32_t f);
#endif
JM_IX_DECL const char* RE_CALL re_get_error_str(unsigned int id);
JM_IX_DECL unsigned int RE_CALL re_get_syntax_type(wchar_t c);
#ifdef RE_LOCALE_CPP
__JM_STD::string RE_CALL re_get_error_str(unsigned int id, const __JM_STD::locale&);
#endif
//
// add some API's for character manipulation:
//
inline char RE_CALL re_tolower(char c
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
return JM_USE_FACET(l, __JM_STD::ctype<char>).tolower(c);
#else
return re_lower_case_map[(unsigned char)c];
#endif
}
#ifndef JM_NO_WCSTRING
inline wchar_t RE_CALL re_tolower(wchar_t c
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
return JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).tolower(c);
#else
return c < 256 ? re_lower_case_map_w[c] : re_wtolower(c);
#endif
}
#endif
inline bool RE_CALL re_istype(char c, jm_uintfast32_t f
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
if(JM_USE_FACET(l, __JM_STD::ctype<char>).is((__JM_STD::ctype<char>::mask)(f & char_class_all_base), c))
return true;
if((f & char_class_underscore) && (c == '_'))
return true;
if((f & char_class_blank) && ((c == ' ') || (c == '\t')))
return true;
return false;
#else
return re_class_map[(unsigned char)c] & f;
#endif
}
#ifndef JM_NO_WCSTRING
inline bool RE_CALL re_istype(wchar_t c, jm_uintfast32_t f
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
if(JM_USE_FACET(l, __JM_STD::ctype<wchar_t>).is((__JM_STD::ctype<wchar_t>::mask)(f & char_class_all_base), c))
return true;
if((f & char_class_underscore) && (c == '_'))
return true;
if((f & char_class_blank) && ((c == ' ') || (c == '\t')))
return true;
return false;
#else
return c < 256 ? re_unicode_classes[c] & f : re_iswclass(c, f);
#endif
}
#endif
inline char RE_CALL re_get_zero(char
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
return JM_USE_FACET(l, regfacet<char>).zero();
#else
return re_zero;
#endif
}
#ifndef JM_NO_WCSTRING
inline wchar_t RE_CALL re_get_zero(wchar_t
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
return JM_USE_FACET(l, regfacet<wchar_t>).zero();
#else
return re_zero_w;
#endif
}
#endif
inline char RE_CALL re_get_ten(char
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
return JM_USE_FACET(l, regfacet<char>).ten();
#else
return re_ten;
#endif
}
#ifndef JM_NO_WCSTRING
inline wchar_t RE_CALL re_get_ten(wchar_t
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef RE_LOCALE_CPP
return JM_USE_FACET(l, regfacet<wchar_t>).ten();
#else
return re_ten_w;
#endif
}
#endif
//
// re_toi:
// convert a single character to the int it represents:
//
template <class charT>
unsigned int RE_CALL re_toi(charT c
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
if(re_istype(c, char_class_digit MAYBE_PASS_LOCALE(l)))
return c - re_get_zero(c MAYBE_PASS_LOCALE(l));
if(re_istype(c, char_class_xdigit MAYBE_PASS_LOCALE(l)))
return 10 + re_tolower(c MAYBE_PASS_LOCALE(l)) - re_tolower(re_get_ten(c MAYBE_PASS_LOCALE(l)) MAYBE_PASS_LOCALE(l));
return -1; // error!!
}
//
// re_toi:
// parse an int from the input string
// update first to point to end of int
// on exit.
//
template <class charT>
unsigned int RE_CALL re_toi(const charT*& first, const charT*const last, int radix
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
unsigned int maxval;
if(radix < 0)
{
// if radix is less than zero, then restrict
// return value to charT. NB assumes sizeof(charT) <= sizeof(int)
radix *= -1;
maxval = 1 << (sizeof(charT) * CHAR_BIT - 1);
maxval /= radix;
maxval *= 2;
maxval -= 1;
}
else
{
maxval = (unsigned int)-1;
maxval /= radix;
}
unsigned int result = 0;
unsigned int type = (radix > 10) ? char_class_xdigit : char_class_digit;
while((first != last) && re_istype(*first, type MAYBE_PASS_LOCALE(l)) && (result <= maxval))
{
result *= radix;
result += re_toi(*first MAYBE_PASS_LOCALE(l));
++first;
}
return result;
}
#ifndef JM_NO_WCSTRING
JM_IX_DECL bool RE_CALL re_is_combining(wchar_t c);
#endif
extern const char* regex_message_catalogue;
JM_IX_DECL const char* RE_CALL get_global_locale_name(int);
JM_END_NAMESPACE
#endif
+185
View File
@@ -0,0 +1,185 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_raw.h
* VERSION 2.12
*/
#ifndef RE_RAW_H
#define RE_RAW_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
JM_NAMESPACE(__JM)
union padding
{
void* p;
unsigned int i;
};
//
// class raw_storage
// basically this is a simplified vector<unsigned char>
// this is used by reg_expression for expression storage
//
template <class Allocator>
class raw_storage
{
public:
typedef Allocator alloc_type;
typedef typename REBIND_TYPE(unsigned char, alloc_type)::size_type size_type;
typedef JM_MAYBE_TYPENAME REBIND_TYPE(unsigned char, alloc_type) alloc_inst_type;
typedef typename REBIND_TYPE(unsigned char, alloc_type)::pointer pointer;
private:
//
// empty member optimisation:
struct alloc_data : public alloc_inst_type
{
pointer last;
alloc_data(const Allocator& a) : alloc_inst_type(a){}
} alloc_inst;
pointer start, end;
public:
raw_storage(const Allocator& a = Allocator());
raw_storage(size_type n, const Allocator& a = Allocator());
~raw_storage()
{
alloc_inst.deallocate(start, (alloc_inst.last - start));
}
void RE_CALL resize(size_type n);
void* RE_CALL extend(size_type n)
{
if(size_type(alloc_inst.last - end) < n)
resize(n + (end - start));
register void* result = end;
end += n;
return result;
}
void* RE_CALL insert(size_type pos, size_type n);
size_type RE_CALL size()
{
return end - start;
}
size_type RE_CALL capacity()
{
return alloc_inst.last - start;
}
void* RE_CALL data()const
{
return start;
}
size_type RE_CALL index(void* ptr)
{
return (unsigned char*)ptr - start;
}
void RE_CALL clear()
{
end = start;
}
void RE_CALL align()
{
// move end up to a boundary:
end = (unsigned char*)((long)(end + sizeof(padding) - 1) & ~((long)sizeof(padding) - 1));
}
Allocator RE_CALL allocator()const;
};
template <class Allocator>
CONSTRUCTOR_INLINE raw_storage<Allocator>::raw_storage(const Allocator& a)
: alloc_inst(a)
{
start = end = alloc_inst.allocate(1024);
alloc_inst.last = start + 1024;
}
template <class Allocator>
CONSTRUCTOR_INLINE raw_storage<Allocator>::raw_storage(size_type n, const Allocator& a)
: alloc_inst(a)
{
start = end = alloc_inst.allocate(n);
alloc_inst.last = start + n;
}
template <class Allocator>
Allocator RE_CALL raw_storage<Allocator>::allocator()const
{
return alloc_inst;
}
template <class Allocator>
void RE_CALL raw_storage<Allocator>::resize(size_type n)
{
register size_type newsize = (alloc_inst.last - start) * 2;
register size_type datasize = end - start;
if(newsize < n)
newsize = n;
// extend newsize to WORD/DWORD boundary:
newsize = (newsize + (sizeof(padding) - 1)) & ~(sizeof(padding) - 1);
// allocate and copy data:
register unsigned char* ptr = alloc_inst.allocate(newsize);
memcpy(ptr, start, datasize);
// get rid of old buffer:
alloc_inst.deallocate(start, (alloc_inst.last - start));
// and set up pointers:
start = ptr;
end = ptr + datasize;
alloc_inst.last = ptr + newsize;
}
template <class Allocator>
void* RE_CALL raw_storage<Allocator>::insert(size_type pos, size_type n)
{
jm_assert(pos <= size_type(end - start));
if(size_type(alloc_inst.last - end) < n)
resize(n + (end - start));
register void* result = start + pos;
memmove(start + pos + n, start + pos, (end - start) - pos);
end += n;
return result;
}
JM_END_NAMESPACE
#endif
+301
View File
@@ -0,0 +1,301 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_str.h
* VERSION 2.12
* This is an internal header file, do not include directly.
* String support and helper functions, for regular
* expression library.
*/
#ifndef RE_STR_H
#define RE_STR_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#include <string.h>
JM_NAMESPACE(__JM)
//
// start by defining some template function aliases for C API functions:
//
template <class charT>
size_t RE_CALL re_strlen(const charT *s)
{
size_t len = 0;
while(*s)
{
++s;
++len;
}
return len;
}
template <class charT>
int RE_CALL re_strcmp(const charT *s1, const charT *s2)
{
while(*s1 && *s2)
{
if(*s1 != *s2)
return *s1 - *s2;
++s1;
++s2;
}
return *s1 - *s2;
}
template <class charT>
charT* RE_CALL re_strcpy(charT *s1, const charT *s2)
{
charT* base = s1;
while(*s2)
{
*s1 = *s2;
++s1;
++s2;
}
*s1 = *s2;
return base;
}
template <class charT>
unsigned int RE_CALL re_strwiden(charT *s1, unsigned int len, const char *s2)
{
unsigned int result = 1 + re_strlen(s2);
if(result > len)
return result;
while(*s2)
{
*s1 = (unsigned char)*s2;
++s2;
++s1;
}
*s1 = (unsigned char)*s2;
return result;
}
template <class charT>
unsigned int RE_CALL re_strnarrow(char *s1, unsigned int len, const charT *s2)
{
unsigned int result = 1 + re_strlen(s2);
if(result > len)
return result;
while(*s2)
{
*s1 = (char)(unsigned char)*s2;
++s2;
++s1;
}
*s1 = (char)(unsigned char)*s2;
return result;
}
inline size_t RE_CALL re_strlen(const char *s)
{
return strlen(s);
}
inline int RE_CALL re_strcmp(const char *s1, const char *s2)
{
return strcmp(s1, s2);
}
inline char* RE_CALL re_strcpy(char *s1, const char *s2)
{
return strcpy(s1, s2);
}
#ifndef JM_NO_WCSTRING
inline size_t RE_CALL re_strlen(const wchar_t *s)
{
return wcslen(s);
}
inline int RE_CALL re_strcmp(const wchar_t *s1, const wchar_t *s2)
{
return wcscmp(s1, s2);
}
inline wchar_t* RE_CALL re_strcpy(wchar_t *s1, const wchar_t *s2)
{
return wcscpy(s1, s2);
}
#endif
#if !defined(JM_NO_WCSTRING) || defined(JM_PLATFORM_W32)
JM_IX_DECL unsigned int RE_CALL _re_strnarrow(char *s1, unsigned int len, const wchar_t *s2);
JM_IX_DECL unsigned int RE_CALL _re_strwiden(wchar_t *s1, unsigned int len, const char *s2);
inline unsigned int RE_CALL re_strnarrow(char *s1, unsigned int len, const wchar_t *s2)
{
return _re_strnarrow(s1, len, s2);
}
inline unsigned int RE_CALL re_strwiden(wchar_t *s1, unsigned int len, const char *s2)
{
return _re_strwiden(s1, len, s2);
}
#endif
template <class charT>
charT* RE_CALL re_strdup(const charT* p)
{
charT* buf = new charT[re_strlen(p) + 1];
re_strcpy(buf, p);
return buf;
}
template <class charT>
charT* RE_CALL re_strdup(const charT* p1, const charT* p2)
{
unsigned int len = p2 - p1 + 1;
charT* buf = new charT[len];
memcpy(buf, p1, (len - 1) * sizeof(charT));
*(buf + len - 1) = 0;
return buf;
}
template <class charT>
inline void RE_CALL re_strfree(charT* p)
{
delete[] p;
}
template <class charT>
class re_str
{
charT* buf;
public:
re_str()
{
charT c = 0;
buf = re_strdup(&c);
}
~re_str();
re_str(const re_str& other);
re_str(const charT* p1);
re_str(const charT* p1, const charT* p2);
re_str(charT c);
re_str& RE_CALL operator=(const re_str& other)
{
re_strfree(buf);
buf = re_strdup(other.buf);
return *this;
}
re_str& RE_CALL operator=(const charT* p)
{
re_strfree(buf);
buf = re_strdup(p);
return *this;
}
re_str& RE_CALL operator=(charT c)
{
re_strfree(buf);
buf = re_strdup(&c, &c+1);
return *this;
}
const charT* RE_CALL c_str()const { return buf; }
RE_CALL operator const charT*()const { return buf; }
unsigned int RE_CALL size()const { return re_strlen(buf); }
charT& RE_CALL operator[](unsigned int i) { return buf[i]; }
charT RE_CALL operator[](unsigned int i)const { return buf[i]; }
bool RE_CALL operator==(const re_str& other)const { return re_strcmp(buf, other.buf) == 0; }
bool RE_CALL operator==(const charT* p)const { return re_strcmp(buf, p) == 0; }
bool RE_CALL operator==(const charT c)const
{
if((*buf) && (*buf == c) && (*(buf+1) == 0))
return true;
return false;
}
bool RE_CALL operator!=(const re_str& other)const { return re_strcmp(buf, other.buf) != 0; }
bool RE_CALL operator!=(const charT* p)const { return re_strcmp(buf, p) != 0; }
bool RE_CALL operator!=(const charT c)const { return !(*this == c); }
bool RE_CALL operator<(const re_str& other)const { return re_strcmp(buf, other.buf) < 0; }
bool RE_CALL operator<=(const re_str& other)const { return re_strcmp(buf, other.buf) <= 0; }
bool RE_CALL operator>(const re_str& other)const { return re_strcmp(buf, other.buf) > 0; }
bool RE_CALL operator>=(const re_str& other)const { return re_strcmp(buf, other.buf) >= 0; }
bool RE_CALL operator<(const charT* p)const { return re_strcmp(buf, p) < 0; }
bool RE_CALL operator<=(const charT* p)const { return re_strcmp(buf, p) <= 0; }
bool RE_CALL operator>(const charT* p)const { return re_strcmp(buf, p) > 0; }
bool RE_CALL operator>=(const charT* p)const { return re_strcmp(buf, p) >= 0; }
};
template <class charT>
CONSTRUCTOR_INLINE re_str<charT>::~re_str() { re_strfree(buf); }
template <class charT>
CONSTRUCTOR_INLINE re_str<charT>::re_str(const re_str<charT>& other) { buf = re_strdup(other.buf); }
template <class charT>
CONSTRUCTOR_INLINE re_str<charT>::re_str(const charT* p1) { buf = re_strdup(p1); }
template <class charT>
CONSTRUCTOR_INLINE re_str<charT>::re_str(const charT* p1, const charT* p2) { buf = re_strdup(p1, p2); }
template <class charT>
CONSTRUCTOR_INLINE re_str<charT>::re_str(charT c) { buf = re_strdup(&c, &c+1); }
#ifndef JM_NO_WCSTRING
JM_IX_DECL void RE_CALL re_transform(re_str<wchar_t>& out, const re_str<wchar_t>& in);
#endif
JM_IX_DECL void RE_CALL re_transform(re_str<char>& out, const re_str<char>& in);
template <class charT>
void RE_CALL re_trunc_primary(re_str<charT>& s)
{
for(unsigned int i = 0; i < s.size(); ++i)
{
if(s[i] <= 1)
{
s[i] = 0;
break;
}
}
}
#ifdef RE_LOCALE_C
#define TRANSFORM_ERROR (size_t)-1
#else
#define TRANSFORM_ERROR 0
#endif
JM_END_NAMESPACE
#endif
+169
View File
@@ -0,0 +1,169 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE re_thrd.h
* VERSION 2.12
* Thread synch helper functions, for regular
* expression library.
*/
#ifndef RE_THRD_H
#define RE_THRD_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#if defined(JM_PLATFORM_W32) && defined(JM_THREADS)
//#include <windows.h>
#endif
#if !defined(JM_PLATFORM_W32) && defined(JM_THREADS)
#include <pthread.h>
#endif
JM_NAMESPACE(__JM)
void RE_CALL re_init_threads();
void RE_CALL re_free_threads();
#ifdef JM_THREADS
#ifndef JM_PLATFORM_W32
typedef pthread_mutex_t CRITICAL_SECTION;
inline void RE_CALL InitializeCriticalSection(CRITICAL_SECTION* ps)
{
pthread_mutex_init(ps, NULL);
}
inline void RE_CALL DeleteCriticalSection(CRITICAL_SECTION* ps)
{
pthread_mutex_destroy(ps);
}
inline void RE_CALL EnterCriticalSection(CRITICAL_SECTION* ps)
{
pthread_mutex_lock(ps);
}
inline void RE_CALL LeaveCriticalSection(CRITICAL_SECTION* ps)
{
pthread_mutex_unlock(ps);
}
#endif
template <class Lock>
class lock_guard
{
typedef Lock lock_type;
public:
lock_guard(lock_type& m, bool aq = true)
: mut(m), owned(false){ acquire(aq); }
~lock_guard()
{ acquire(false); }
void RE_CALL acquire(bool aq = true, DWORD timeout = INFINITE)
{
if(aq && !owned)
{
mut.acquire(true, timeout);
owned = true;
}
else if(!aq && owned)
{
mut.acquire(false);
owned = false;
}
}
private:
lock_type& mut;
bool owned;
};
class critical_section
{
public:
critical_section()
{ InitializeCriticalSection(&hmutex);}
critical_section(const critical_section&)
{ InitializeCriticalSection(&hmutex);}
const critical_section& RE_CALL operator=(const critical_section&)
{return *this;}
~critical_section()
{DeleteCriticalSection(&hmutex);}
private:
void RE_CALL acquire(bool aq, DWORD unused = INFINITE)
{ if(aq) EnterCriticalSection(&hmutex);
else LeaveCriticalSection(&hmutex);
}
CRITICAL_SECTION hmutex;
public:
typedef lock_guard<critical_section> ro_guard;
typedef lock_guard<critical_section> rw_guard;
friend lock_guard<critical_section>;
};
inline bool RE_CALL operator==(const critical_section&, const critical_section&)
{
return false;
}
inline bool RE_CALL operator<(const critical_section&, const critical_section&)
{
return true;
}
typedef lock_guard<critical_section> cs_guard;
JM_IX_DECL extern critical_section* p_re_lock;
JM_IX_DECL extern unsigned int re_lock_count;
#define JM_GUARD(inst) __JM::critical_section::rw_guard g(inst);
#else // JM_THREADS
#define JM_GUARD(inst)
#endif // JM_THREADS
JM_END_NAMESPACE
#endif // sentry
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+168
View File
@@ -0,0 +1,168 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE regfac.h
* VERSION 2.12
*/
#ifndef REGFAC_H
#define REGFAC_H
#ifndef JM_CFG_H
#include <jm/jm_cfg.h>
#endif
#ifdef RE_LOCALE_CPP
#include <string>
#include <jm/re_str.h>
#include <jm/re_cls.h>
#include <list>
#include <map>
//
// class regfacet
//
// provides syntax data etc, customised versions
// can be installed in an instance of std::locale and imbue'd
// into a reg_expression for per-instance localisation.
//
JM_NAMESPACE(__JM)
template <class charT>
class regfacet : public __JM_STD::locale::facet
{
public:
static __JM_STD::locale::id id;
regfacet(unsigned int i = 0);
jm_uintfast32_t RE_CALL lookup_classname(const charT* first, const charT* last)const;
bool RE_CALL lookup_collatename(re_str<charT>& s, const re_str<charT>& name)const;
unsigned int RE_CALL syntax_type(charT)const;
void RE_CALL update(const __JM_STD::locale&)const;
charT RE_CALL zero()const;
charT RE_CALL ten()const;
protected:
virtual jm_uintfast32_t RE_CALL do_lookup_classname(const charT* first, const charT* last)const = 0;
virtual bool RE_CALL do_lookup_collatename(re_str<charT>& s, const re_str<charT>& name)const = 0;
virtual unsigned int RE_CALL do_syntax_type(charT)const = 0;
virtual void RE_CALL do_update(const __JM_STD::locale&) = 0;
// required by Rogue Wave, not part of standard:
__JM_STD::locale::id& get_id()const { return id; }
~regfacet(){}
};
JM_TEMPLATE_SPECIALISE
class JM_IX_DECL regfacet<char> : public __JM_STD::locale::facet
{
public:
typedef __JM_STD::messages<char>::string_type string_type;
private:
unsigned char syntax_map[256];
string_type name;
char _zero, _ten;
__JM_STD::map<__JM_STD::string, unsigned long, __JM_STD::less<__JM_STD::string> > classes;
__JM_STD::map<re_str<char>, re_str<char>, __JM_STD::less<re_str<char> > > collating_elements;
regfacet(const regfacet&);
#ifdef RE_THREADS
critical_section cs;
#endif
public:
static __JM_STD::locale::id id;
regfacet(unsigned int i = 0);
jm_uintfast32_t RE_CALL lookup_classname(const char* first, const char* last)const { return do_lookup_classname(first, last); }
bool RE_CALL lookup_collatename(re_str<char>& s, const re_str<char>& name)const { return do_lookup_collatename(s, name); }
unsigned int RE_CALL syntax_type(char c)const { return do_syntax_type(c); }
void RE_CALL update(const __JM_STD::locale& l)const { const_cast<regfacet<char>*>(this)->do_update(l); }
char RE_CALL zero()const { return _zero; }
char RE_CALL ten()const { return _ten; }
protected:
virtual jm_uintfast32_t RE_CALL do_lookup_classname(const char* first, const char* last)const;
virtual bool RE_CALL do_lookup_collatename(re_str<char>& s, const re_str<char>& name)const;
virtual unsigned int RE_CALL do_syntax_type(char)const;
virtual void RE_CALL do_update(const __JM_STD::locale&);
// required by Rogue Wave, not part of standard:
__JM_STD::locale::id& get_id()const { return id; }
~regfacet();
};
JM_TEMPLATE_SPECIALISE
class JM_IX_DECL regfacet<wchar_t> : public __JM_STD::locale::facet
{
public:
typedef __JM_STD::messages<wchar_t>::string_type string_type;
private:
__JM_STD::messages<char>::string_type name;
struct syntax_map
{
wchar_t c;
unsigned int type;
};
__JM_STD::list<syntax_map> syntax;
wchar_t _zero, _ten;
__JM_STD::map<__JM_STD::wstring, unsigned long, __JM_STD::less<__JM_STD::wstring> > classes;
const __JM_STD::locale* ploc;
__JM_STD::map<re_str<wchar_t>, re_str<wchar_t>, __JM_STD::less<re_str<wchar_t> > > collating_elements;
regfacet(const regfacet&);
#ifdef RE_THREADS
critical_section cs;
#endif
public:
static __JM_STD::locale::id id;
regfacet(unsigned int i = 0);
jm_uintfast32_t RE_CALL lookup_classname(const wchar_t* first, const wchar_t* last)const { return do_lookup_classname(first, last); }
bool RE_CALL lookup_collatename(re_str<wchar_t>& s, const re_str<wchar_t>& name)const { return do_lookup_collatename(s, name); }
unsigned int RE_CALL syntax_type(wchar_t c)const { return do_syntax_type(c); }
void RE_CALL update(const __JM_STD::locale& l)const { const_cast<regfacet<wchar_t>*>(this)->do_update(l); }
wchar_t RE_CALL zero()const { return _zero; }
wchar_t RE_CALL ten()const { return _ten; }
protected:
virtual jm_uintfast32_t RE_CALL do_lookup_classname(const wchar_t* first, const wchar_t* last)const;
virtual bool RE_CALL do_lookup_collatename(re_str<wchar_t>& s, const re_str<wchar_t>& name)const;
virtual unsigned int RE_CALL do_syntax_type(wchar_t)const;
virtual void RE_CALL do_update(const __JM_STD::locale&);
// required by Rogue Wave, not part of standard:
__JM_STD::locale::id& get_id()const { return id; }
~regfacet();
};
JM_END_NAMESPACE
#endif
#endif
+565
View File
@@ -0,0 +1,565 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
*
* Copyright (c) 1998-9
* Dr John Maddock
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Dr John Maddock makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
*/
/*
* FILE regfmt.h
* VERSION 2.12
*
* Provides formatting output routines for search and replace
* operations. Note this is an internal header file included
* by regex.h, do not include on its own.
*/
#ifndef REGFMT_H
#define REGFMT_H
JM_NAMESPACE(__JM)
template <class O, class I>
O RE_CALL re_copy_out(O out, I first, I last)
{
while(first != last)
{
*out = *first;
++out;
++first;
}
return out;
}
template <class charT>
void RE_CALL re_skip_format(const charT*& fmt
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef JM_NO_TEMPLATE_TYPENAME
typedef char_regex_traits<charT> re_traits_type;
#else
typedef typename char_regex_traits<charT> re_traits_type;
#endif
unsigned int parens = 0;
unsigned int c;
while(*fmt)
{
c = re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l));
if((c == syntax_colon) && (parens == 0))
{
++fmt;
return;
}
else if(c == syntax_close_bracket)
{
if(parens == 0)
{
++fmt;
return;
}
--parens;
}
else if(c == syntax_open_bracket)
++parens;
else if(c == syntax_slash)
{
++fmt;
if(*fmt == 0)
return;
}
++fmt;
}
}
#ifdef JM_NO_OI_ASSIGN
//
// ugly hack for buggy output iterators
template <class T>
inline void oi_assign(T* p, T v)
{
jm_destroy(p);
jm_construct(p, v);
}
#else
template <class T>
inline void oi_assign(T* p, T v)
{
//
// if you get a compile time error in here then you either
// need to rewrite your output iterator to make it assignable
// (as is required by the standard), or define JM_NO_OI_ASSIGN
// to use the ugly hack above
*p = v;
}
#endif
#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
//
// Ugly ugly hack,
// template don't merge if they contain switch statements so declare these
// templates in unnamed namespace (ie with internal linkage), each translation
// unit then gets its own local copy, it works seemlessly but bloats the app.
namespace{
#endif
//
// algorithm reg_format:
// takes the result of a match and a format string
// and merges them to produce a new string which
// is sent to an OutputIterator,
// __reg_format_aux does the actual work:
//
template <class OutputIterator, class iterator, class Allocator, class charT>
OutputIterator RE_CALL __reg_format_aux(OutputIterator out,
const reg_match<iterator, Allocator>& m,
const charT*& fmt,
bool isif
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& l
#endif
)
{
#ifdef JM_NO_TEMPLATE_TYPENAME
typedef char_regex_traits<charT> re_traits_type;
#else
typedef typename char_regex_traits<charT> re_traits_type;
#endif
const charT* fmt_end = fmt;
while(*fmt_end) ++ fmt_end;
while(*fmt)
{
switch(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)))
{
case syntax_dollar:
++fmt;
if(*fmt == 0) // oops trailing $
{
--fmt;
*out = *fmt;
++out;
return out;
}
switch(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)))
{
case syntax_start_buffer:
oi_assign(&out, re_copy_out(out, iterator(m[-1].first), iterator(m[-1].second)));
++fmt;
continue;
case syntax_end_buffer:
oi_assign(&out, re_copy_out(out, iterator(m[-2].first), iterator(m[-2].second)));
++fmt;
continue;
case syntax_digit:
{
unsigned int index = re_traits_type::toi(fmt, fmt_end, 10 MAYBE_PASS_LOCALE(l));
oi_assign(&out, re_copy_out(out, iterator(m[index].first), iterator(m[index].second)));
continue;
}
}
// anything else:
if(*fmt == '&')
{
oi_assign(&out, re_copy_out(out, iterator(m[0].first), iterator(m[0].second)));
++fmt;
}
else
{
// probably an error, treat as a literal '$'
--fmt;
*out = *fmt;
++out;
++fmt;
}
continue;
case syntax_slash:
{
// escape sequence:
charT c;
++fmt;
if(*fmt == 0)
{
--fmt;
*out = *fmt;
++out;
++fmt;
return out;
}
switch(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)))
{
case syntax_a:
c = '\a';
++fmt;
break;
case syntax_f:
c = '\f';
++fmt;
break;
case syntax_n:
c = '\n';
++fmt;
break;
case syntax_r:
c = '\r';
++fmt;
break;
case syntax_t:
c = '\t';
++fmt;
break;
case syntax_v:
c = '\v';
++fmt;
break;
case syntax_x:
++fmt;
if(fmt == fmt_end)
{
*out = *--fmt;
++out;
return out;
}
// maybe have \x{ddd}
if(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)) == syntax_open_brace)
{
++fmt;
if(fmt == fmt_end)
{
fmt -= 2;
*out = *fmt;
++out;
++fmt;
continue;
}
if(re_traits_type::is_class(*fmt, char_class_xdigit MAYBE_PASS_LOCALE(l)) == false)
{
fmt -= 2;
*out = *fmt;
++out;
++fmt;
continue;
}
c = (charT)re_traits_type::toi(fmt, fmt_end, -16 MAYBE_PASS_LOCALE(l));
if(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)) != syntax_close_brace)
{
while(re_traits_type::syntax_type(*fmt MAYBE_PASS_LOCALE(l)) != syntax_slash)
--fmt;
++fmt;
*out = *fmt;
++out;
++fmt;
continue;
}
++fmt;
break;
}
else
{
if(re_traits_type::is_class(*fmt, char_class_xdigit MAYBE_PASS_LOCALE(l)) == false)
{
--fmt;
*out = *fmt;
++out;
++fmt;
continue;
}
c = (charT)re_traits_type::toi(fmt, fmt_end, -16 MAYBE_PASS_LOCALE(l));
}
break;
case syntax_c:
++fmt;
if(fmt == fmt_end)
{
--fmt;
*out = *fmt;
++out;
return out;
}
if(((typename re_traits_type::uchar_type)(*fmt) < (typename re_traits_type::uchar_type)'@')
|| ((typename re_traits_type::uchar_type)(*fmt) > (typename re_traits_type::uchar_type)127) )
{
--fmt;
*out = *fmt;
++out;
++fmt;
break;
}
c = (charT)((typename re_traits_type::uchar_type)(*fmt) - (typename re_traits_type::uchar_type)'@');
++fmt;
break;
case syntax_e:
c = (charT)27;
++fmt;
break;
case syntax_digit:
c = (charT)re_traits_type::toi(fmt, fmt_end, -8 MAYBE_PASS_LOCALE(l));
break;
default:
c = *fmt;
++fmt;
}
*out = c;
continue;
}
case syntax_open_bracket:
++fmt; // recurse
oi_assign(&out, __reg_format_aux(out, m, fmt, false MAYBE_PASS_LOCALE(l)));
continue;
case syntax_close_bracket:
++fmt; // return from recursion
return out;
case syntax_colon:
if(isif)
{
++fmt;
return out;
}
*out = *fmt;
++out;
++fmt;
continue;
case syntax_question:
{
++fmt;
if(*fmt == 0)
{
--fmt;
*out = *fmt;
++out;
++fmt;
return out;
}
unsigned int id = re_traits_type::toi(fmt, fmt_end, 10 MAYBE_PASS_LOCALE(l));
if(m[id].matched)
{
oi_assign(&out, __reg_format_aux(out, m, fmt, true MAYBE_PASS_LOCALE(l)));
if(re_traits_type::syntax_type(*(fmt-1) MAYBE_PASS_LOCALE(l)) == syntax_colon)
re_skip_format(fmt MAYBE_PASS_LOCALE(l));
}
else
{
re_skip_format(fmt MAYBE_PASS_LOCALE(l));
if(re_traits_type::syntax_type(*(fmt-1) MAYBE_PASS_LOCALE(l)) == syntax_colon)
oi_assign(&out, __reg_format_aux(out, m, fmt, true MAYBE_PASS_LOCALE(l)));
}
return out;
}
default:
*out = *fmt;
++out;
++fmt;
}
}
return out;
}
#if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
} // namespace
#endif
template <class OutputIterator, class iterator, class Allocator, class charT>
OutputIterator RE_CALL reg_format(OutputIterator out,
const reg_match<iterator, Allocator>& m,
const charT* fmt
#ifdef RE_LOCALE_CPP
, __JM_STD::locale locale_inst = __JM_STD::locale()
#endif
)
{
//
// start by updating the locale:
//
#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32)
static re_initialiser<charT> locale_initialiser;
locale_initialiser.update();
#else
if(JM_HAS_FACET(locale_inst, regfacet<charT>) == false)
{
#ifdef _MSC_VER
locale_inst = __JM_STD::_ADDFAC(locale_inst, new regfacet<charT>());
#else
locale_inst = __JM_STD::locale(locale_inst, new regfacet<charT>());
#endif
}
JM_USE_FACET(locale_inst, regfacet<charT>).update(locale_inst);
#endif
return __reg_format_aux(out, m, fmt, false MAYBE_PASS_LOCALE(locale_inst));
}
template <class S>
class string_out_iterator
{
S* out;
public:
string_out_iterator(S& s) : out(&s) {}
string_out_iterator& operator++() { return *this; }
string_out_iterator& operator++(int) { return *this; }
string_out_iterator& operator*() { return *this; }
string_out_iterator& operator=(typename S::value_type v)
{
out->append(1, v);
return *this;
}
};
#ifndef JM_NO_STRING_DEF_ARGS
template <class iterator, class Allocator, class charT>
__JM_STD::basic_string<charT> RE_CALL reg_format(const reg_match<iterator, Allocator>& m, const charT* fmt
#ifdef RE_LOCALE_CPP
, __JM_STD::locale locale_inst = __JM_STD::locale()
#endif
)
{
__JM_STD::basic_string<charT> result;
string_out_iterator<__JM_STD::basic_string<charT> > i(result);
reg_format(i, m, fmt MAYBE_PASS_LOCALE(locale_inst));
return result;
}
#elif !defined(JM_NO_STRING_H)
template <class iterator, class Allocator>
__JM_STD::string RE_CALL reg_format(const reg_match<iterator, Allocator>& m, const char* fmt
#ifdef RE_LOCALE_CPP
, __JM_STD::locale locale_inst = __JM_STD::locale()
#endif
)
{
__JM_STD::string result;
string_out_iterator<__JM_STD::string> i(result);
reg_format(i, m, fmt MAYBE_PASS_LOCALE(locale_inst));
return result;
}
#endif
template <class OutputIterator, class iterator, class charT, class Allocator>
class merge_out_predicate
{
OutputIterator* out;
iterator* last;
const charT* fmt;
bool copy_none;
#ifdef RE_LOCALE_CPP
const __JM_STD::locale& l;
#endif
public:
merge_out_predicate(OutputIterator& o, iterator& pi, const charT* f, bool c
#ifdef RE_LOCALE_CPP
, const __JM_STD::locale& loc
#endif
) : out(&o), last(&pi), fmt(f), copy_none(c)
#ifdef RE_LOCALE_CPP
, l(loc)
#endif
{}
~merge_out_predicate() {}
bool RE_CALL operator()(const __JM::reg_match<iterator, Allocator>& m)
{
const charT* f = fmt;
if(copy_none)
oi_assign(out, re_copy_out(*out, iterator(m[-1].first), iterator(m[-1].second)));
oi_assign(out, __reg_format_aux(*out, m, f, false MAYBE_PASS_LOCALE(l)));
*last = m[-2].first;
return true;
}
};
template <class OutputIterator, class iterator, class traits, class Allocator, class charT>
OutputIterator RE_CALL reg_merge(OutputIterator out,
iterator first,
iterator last,
const reg_expression<charT, traits, Allocator>& e,
const charT* fmt,
bool copy = true,
unsigned int flags = match_default)
{
//
// start by updating the locale:
//
#if defined(RE_LOCALE_C) || defined(RE_LOCALE_W32)
static re_initialiser<charT> locale_initialiser;
locale_initialiser.update();
#else
__JM_STD::locale locale_inst(e.locale());
if(JM_HAS_FACET(locale_inst, regfacet<charT>) == false)
{
#ifdef _MSC_VER
locale_inst = __JM_STD::_ADDFAC(locale_inst, new regfacet<charT>());
#else
locale_inst = __JM_STD::locale(locale_inst, new regfacet<charT>());
#endif
}
JM_USE_FACET(locale_inst, regfacet<charT>).update(locale_inst);
#endif
iterator l = first;
merge_out_predicate<OutputIterator, iterator, charT, Allocator> oi(out, l, fmt, copy MAYBE_PASS_LOCALE(locale_inst));
reg_grep(oi, first, last, e, flags);
return copy ? re_copy_out(out, l, last) : out;
}
#ifndef JM_NO_STRING_DEF_ARGS
template <class traits, class Allocator, class charT>
__JM_STD::basic_string<charT> RE_CALL reg_merge(const __JM_STD::basic_string<charT>& s,
const reg_expression<charT, traits, Allocator>& e,
const charT* fmt,
bool copy = true,
unsigned int flags = match_default)
{
__JM_STD::basic_string<charT> result;
string_out_iterator<__JM_STD::basic_string<charT> > i(result);
reg_merge(i, s.begin(), s.end(), e, fmt, copy, flags);
return result;
}
#elif !defined(JM_NO_STRING_H)
template <class traits, class Allocator>
__JM_STD::string RE_CALL reg_merge(const __JM_STD::string& s,
const reg_expression<char, traits, Allocator>& e,
const char* fmt,
bool copy = true,
unsigned int flags = match_default)
{
__JM_STD::string result;
string_out_iterator<__JM_STD::string> i(result);
reg_merge(i, s.begin(), s.end(), e, fmt, copy, flags);
return result;
}
#endif
JM_END_NAMESPACE
#endif
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
#ifndef __REGEX_H
#include <jm/regex.h>
#endif
+16
View File
@@ -0,0 +1,16 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef __REGEX_H
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#pragma warning(disable: 4800)
#endif
#include <jm/regex.h>
#endif
Binary file not shown.
Binary file not shown.
Binary file not shown.
+36
View File
@@ -0,0 +1,36 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implematation of CReport
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "report.h"
#include "util.h"
//------------------------------------------------------------------------------------------------------
// Function: CReport::makeHTMLPage
// Purpose: makes a whole page out of the element that it is called on
// Input: pageName - the name of the html file
// pageTitle - the title of the document
//------------------------------------------------------------------------------------------------------
void CReport::makeHTMLPage(char* pageName,char* pageTitle)
{
CHTMLFile Page(pageName,pageTitle);
report(Page);
}
//------------------------------------------------------------------------------------------------------
// Function: CReport::report
// Purpose: generates the report's output and adds it to anHTML file
// Input: html - the HTML file to add this report element to
//------------------------------------------------------------------------------------------------------
void CReport::report(CHTMLFile& html)
{
generate();
writeHTML(html);
}
+47
View File
@@ -0,0 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of CReport
//
// $Workfile: $
// $Date: $
//
//------------------------------------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef REPORT_H
#define REPORT_H
#ifdef WIN32
#pragma once
#pragma warning(disable:4786)
#endif
#include "MatchInfo.h"
#include "HTML.h"
//------------------------------------------------------------------------------------------------------
// Purpose: CReport is the base class for all elements of a report. This includes
// things like scoreboards and awards.
//------------------------------------------------------------------------------------------------------
class CReport
{
protected:
//every element must have some info about the match to go off of.
//moved into global pointer. g_pMatchInfo
//CMatchInfo* pMatchInfo;
virtual void init(){}
public:
//explicit CReport(CMatchInfo* pMInfo):pMatchInfo(pMInfo){}
explicit CReport(){}
virtual void writeHTML(CHTMLFile& html){}
virtual void generate(){}
virtual void makeHTMLPage(char* pageName,char* pageTitle);
virtual void report(CHTMLFile& html);
virtual ~CReport(){}
};
#endif // REPORT_H
+57
View File
@@ -0,0 +1,57 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
char* szHeaderFile=
"//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========\n"\
"//\n"\
"// The copyright to the contents herein is the property of Valve, L.L.C.\n"\
"// The contents may be used and/or copied only with the written permission of\n"\
"// Valve, L.L.C., or in accordance with the terms and conditions stipulated in\n"\
"// the agreement/contract under which the contents have been supplied.\n"\
"//\n"\
"// Purpose: \n"\
"//\n"\
"// $Workfile: $\n"\
"// $Date: $\n"\
"//\n"\
"//------------------------------------------------------------------------------------------------------\n"\
"// $Log: $\n"\
"//\n"\
"// $NoKeywords: $\n"\
"//=============================================================================\n"\
"#ifndef BINARYRESOURCE_H\n"\
"#define BINARYRESOURCE_H\n"\
"#ifdef WIN32\n"\
"#pragma once\n"\
"#endif\n"\
"#include <string>\n"\
"#include <stdio.h>\n"\
"\n"\
"class CBinaryResource\n"\
"{\n"\
"private:\n"\
" std::string filename;\n"\
" size_t numBytes;\n"\
" unsigned char* pData;\n"\
"public:\n"\
" CBinaryResource(char* name, size_t bytes,unsigned char* data)\n"\
" :filename(name),numBytes(bytes),pData(data)\n"\
" {}\n"\
" \n"\
" bool writeOut()\n"\
" {\n"\
" FILE* f=fopen(filename.c_str(),\"wb\");\n"\
" if (!f)\n"\
" return false;\n"\
" fwrite(pData,1,numBytes,f);\n"\
" fclose(f);\n"\
" return true;\n"\
" }\n"\
"};\n"\
"\n"\
"#endif // BINARYRESOURCE_H\n"\
"\n";
+111
View File
@@ -0,0 +1,111 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define NUM_PER_LINE 40
extern char* szHeaderFile;
void printUsage()
{
printf("res2c <res file name> <c file name> <object name>\n");
}
char* id4filename(const char* filename)
{
static char id[500];
const char* read=filename;
char *write=id;
for (read;*read;read++)
{
//if first char
if (read==filename)
{
if (isalpha(*read) || *read=='_')
*write++=*read;
}
else if (isalnum(*read))
*write++=*read;
}
*write++='s';
*write++='r';
*write++='c';
*write++='\0';
return id;
}
void main(int argc, const char* argv[])
{
if (argc < 4)
{
printUsage();
return;
}
char cppname[200];
sprintf(cppname,"%s.cpp",argv[2]);
char hname[200];
sprintf(hname,"%s.h",argv[2]);
FILE* f=fopen(argv[1],"rb");
FILE* cppout=fopen(cppname,"at");
FILE* hout=fopen(hname,"at");
FILE* brheader=fopen("BinaryResource.h","wt");
if (!brheader){printf("couldn't open %s to write\n","BinaryResource.h");exit(-1);}
if (!f){printf("couldn't read %s\n",argv[1]);exit(-1);}
if (!cppout){printf("couldn't open %s to write\n",argv[2]);exit(-1);}
if (!hout){printf("couldn't open %s to write\n",argv[2]);exit(-1);}
fprintf(brheader,szHeaderFile);
fclose(brheader);
fprintf(cppout,"\nunsigned char %s[]={\n",id4filename(argv[1]));
int numLeft4Line=NUM_PER_LINE;
unsigned char c;
int result=fread(&c,sizeof(unsigned char),1,f);
int numbytes=0;
while (result)
{
//int longc=(*c)&0x000000ff;
fprintf(cppout,"0x%02.2x,",c);
numbytes++;
if(--numLeft4Line==0)
{
numLeft4Line=NUM_PER_LINE;
fprintf(cppout,"\n");
}
result=fread(&c,sizeof(unsigned char),1,f);
}
fprintf(cppout,"\n};\n\n");
char* coloncolon=strstr(argv[3],"::");
if (coloncolon!=NULL)
{
coloncolon+=2;
fprintf(hout,"static CBinaryResource %s;\n",coloncolon);
fprintf(cppout,"CBinaryResource %s(\"%s\",%li,%s);\n\n\n",argv[3],argv[1],numbytes,id4filename(argv[1]));
}
else
{
fprintf(hout,"//extern CBinaryResource g_%s;\n",argv[3]);
fprintf(cppout,"CBinaryResource g_%s;\n",argv[3]);
}
fclose(cppout);
fclose(hout);
fclose(f);
}
+152
View File
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="res2c"
ProjectGUID="{3245AFA2-1569-4ED7-B378-3B6461B3F5BA}"
SccProjectName=""
SccLocalPath="">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="TRUE"
RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Release/res2c.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile=".\Release/res2c.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
ProgramDatabaseFile=".\Release/res2c.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/res2c.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Debug/res2c.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile=".\Debug/res2c.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\Debug/res2c.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/res2c.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath="main.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

+14
View File
@@ -0,0 +1,14 @@
res2c awards.gif binResources CTFStatsReport::gifAwards
res2c bgleft.jpg binResources CTFStatsReport::jpgBgLeft
res2c bgtop.jpg binResources CTFStatsReport::jpgBgTop
res2c boxscore.gif binResources CTFStatsReport::gifBoxScore
res2c game.dialog.off.gif binResources CTFStatsReport::gifGameDialogOff
res2c game.dialog.on.gif binResources CTFStatsReport::gifGameDialogOn
res2c match.statistics.off.gif binResources CTFStatsReport::gifMatchStatsOff
res2c match.statistics.on.gif binResources CTFStatsReport::gifMatchStatsOn
res2c scores.gif binResources CTFStatsReport::gifScores
res2c server.settings.off.gif binResources CTFStatsReport::gifServerSettingsOff
res2c server.settings.on.gif binResources CTFStatsReport::gifServerSettingsOn
res2c player.statistics.off.gif binResources CTFStatsReport::gifPlayerStatsOff
res2c player.statistics.on.gif binResources CTFStatsReport::gifPlayerStatsOn
res2c detailed.gif binResources CTFStatsReport::gifDetailedScores
Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Some files were not shown because too many files have changed in this diff Show More