You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

482 lines
19 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plConfigInfo_h_inc
#define plConfigInfo_h_inc
#include "plKeysAndValues.h"
#include "hsStlUtils.h"
#include <stdarg.h>
/////////////////////////////////////////////////
typedef std::vector<std::string> plStringList;
typedef std::vector<std::wstring> plWStringList;
/////////////////////////////////////////////////
class plConfigSource;
class plConfigInfo
{
public:
typedef plKeysAndValues::Keys
Keys;
typedef plKeysAndValues::Values
Values;
typedef std::map<xtl::istring, plKeysAndValues>
Sections;
static const std::string& GlobalSection();
private:
mutable Sections fSections;
public:
plConfigInfo();
plConfigInfo(const plConfigInfo & src);
virtual ~plConfigInfo() {}
plConfigInfo & operator =(const plConfigInfo & src);
// REMOVE
// remove all sections
void Clear();
// remove section
void RemoveSection(const std::string & section);
// remove key from section
void RemoveKey(const std::string & section, const std::string & key);
// QUERY
// does this section exist?
bool HasSection(const std::string & section) const;
// does the given section contain this key?
bool HasKey(const std::string & section, const std::string & key);
// does any section contain this key?
bool HasKeyAny(const std::string & key);
// does any of the given sections contain this key?
bool HasKeyIn(const std::string & key, const char * section1, ... /*, nil*/);
bool HasKeyIn(const std::string & key, const std::vector<std::string> & sections );
// does key in section have this value?
bool KeyHasValue(const std::string & section, const std::string & key, const std::string & value);
bool KeyHasValue(const std::string & section, const std::string & key, int value);
bool KeyHasValue(const std::string & section, const std::string & key, double value);
// ADD
// add key=value to the section
bool AddValue(const std::string & section, const std::string & key, const std::string & value, KAddValueMode mode=kAlwaysAdd);
bool AddValue(const std::string & section, const std::string & key, int value, KAddValueMode mode=kAlwaysAdd);
bool AddValue(const std::string & section, const std::string & key, double value, KAddValueMode mode=kAlwaysAdd);
bool AddValues(const std::string & section, const std::string & key, const std::vector<std::string> & values, KAddValueMode mode=kAlwaysAdd);
// GET
plKeysAndValues GetSection(const std::string & section, bool & found);
std::vector<std::string> GetSectionNames();
// get value for key from given section
std::string GetValue(const std::string & section, const std::string & key, const std::string & defval="", bool * outFound=nil) const;
int GetValue(const std::string & section, const std::string & key, int defval, bool * outFound=nil) const;
double GetValue(const std::string & section, const std::string & key, double defval, bool * outFound=nil) const;
std::vector<std::string> GetAllValues(const std::string & section, const std::string & key) const;
// get value for key from any section
std::string GetValueAny(const std::string & key, const std::string & defval="", bool * outFound=nil) const;
int GetValueAny(const std::string & key, int defval, bool * outFound=nil) const;
double GetValueAny(const std::string & key, double defval, bool * outFound=nil) const;
std::vector<std::string> GetAllValuesAny(const std::string & key) const;
// get value for key from one of the given sections
std::string GetValueIn(const std::string & key, const std::string & defval, bool * outFound, const char * section1, ... /*, nil*/) const;
std::string GetValueIn(const std::string & key, const std::string & defval, bool * outFound, const std::vector<std::string> & sections ) const;
int GetValueIn(const std::string & key, int defval, bool * outFound, const char * section1, ... /*, nil*/) const;
int GetValueIn(const std::string & key, int defval, bool * outFound, const std::vector<std::string> & sections ) const;
double GetValueIn(const std::string & key, double defval, bool * outFound, const char * section1, ... /*, nil*/) const;
double GetValueIn(const std::string & key, double defval, bool * outFound, const std::vector<std::string> & sections ) const;
std::vector<std::string> GetAllValuesIn(const std::string & key, const char * section1, ... /*, nil*/);
// ITERATORS
bool GetSectionIterators(Sections::const_iterator & iter, Sections::const_iterator & end) const;
bool GetKeyIterators(const xtl::istring & section, Keys::const_iterator & iter, Keys::const_iterator & end) const;
bool GetValueIterators(const xtl::istring & section, const xtl::istring & key, Values::const_iterator & iter, Values::const_iterator & end) const;
// CONFIG SOURCE
virtual bool ReadFrom(plConfigSource * src, KAddValueMode mode=kAlwaysAdd);
virtual bool WriteTo(plConfigSource * src);
};
class plConfigInfoLogging
{
private:
plConfigInfo fConfigInfo;
plConfigInfo fLog;
public:
plConfigInfoLogging();
~plConfigInfoLogging();
plConfigInfo* GetConfigInfo() { return &fConfigInfo; }
plConfigInfo* GetConfigInfoLog() { return &fLog; }
bool GetValue(std::string& retval, const std::string & section, const std::string & key, const std::string & desc, const std::string& defval = "");
bool GetValue(int& retval, const std::string & section, const std::string & key, const std::string & desc, int defval);
bool GetValue(bool& retval, const std::string & section, const std::string & key, const std::string & desc, bool defval);
bool GetValue(float& retval, const std::string & section, const std::string & key, const std::string & desc, float defval);
bool GetValue(double& retval, const std::string & section, const std::string & key, const std::string & desc, double defval);
bool GetAllValues(std::vector<std::string>& values, const std::string & section, const std::string & key, const std::string & desc);
#if USE_MULT_SECTIONS
// get value for key from any section
bool GetValueAny(std::string& retval, const std::string & key, const std::string & desc, const std::string & defval);
bool GetValueAny(int &retval, const std::string & key, const std::string & desc, int defval);
bool GetValueAny(bool& retval, const std::string & key, const std::string & desc, bool defval);
bool GetValueAny(float& retval, const std::string & key, const std::string & desc, float defval);
bool GetValueAny(double& retval, const std::string & key, const std::string & desc, double defval);
bool GetAllValuesAny(std::vector<std::string>& values, const std::string & key, const std::string & desc);
// get value for key from one of the given sections
bool GetValueIn(std::string& retval, const std::string & key, const std::string & desc, const std::string & defval, const char * section1, ... /*, nil*/);
bool GetValueIn(std::string& retval, const std::string & key, const std::string & desc, const std::string & defval, std::vector<std::string> & sections );
bool GetValueIn(int& retval, const std::string & key, const std::string & desc, int defval, const char * section1, ... /*, nil*/);
bool GetValueIn(int& retval, const std::string & key, const std::string & desc, int defval, std::vector<std::string> & sections );
bool GetValueIn(bool& retval, const std::string & key, const std::string & desc, bool defval, const char * section1, ... /*, nil*/);
bool GetValueIn(bool& retval, const std::string & key, const std::string & desc, bool defval, std::vector<std::string> & sections );
bool GetValueIn(float& retval, const std::string & key, const std::string & desc, double defval, const char * section1, ... /*, nil*/);
bool GetValueIn(float& retval, const std::string & key, const std::string & desc, double defval, std::vector<std::string> & sections );
bool GetValueIn(double& retval, const std::string & key, const std::string & desc, double defval, const char * section1, ... /*, nil*/);
bool GetValueIn(double& retval, const std::string & key, const std::string & desc, double defval, std::vector<std::string> & sections );
#endif
};
/////////////////////////////////////////////////
class plConfigSource
{
protected:
std::string fCurrSection; // used in parsing
std::string fEffectiveSection; // used in parsing
KAddValueMode fAddMode; // used in parsing
plConfigInfo * fConfigInfo;
void SplitAt(std::string & key, std::string & value, char splitter, std::string & in);
virtual bool ReadString(const std::string & in);
virtual bool ReadPair(std::string & key, std::string & value);
virtual bool ReadList(char ** list);
virtual bool ReadSubSource( const char * name ) { return true; }
protected:
virtual bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
virtual bool WriteOutOf(plConfigInfo & configInfo);
public:
plConfigSource() {}
virtual ~plConfigSource() {}
friend class plConfigInfo;
};
/////////////////////////////////////////////////
class plCmdLineConfigSource : public plConfigSource
{
int fArgc;
char ** fArgv;
std::string fMySection;
protected:
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
public:
plCmdLineConfigSource(int argc, char ** argv, const char * mySection="CmdLine");
};
/////////////////////////////////////////////////
class plEnvConfigSource : public plConfigSource
{
char ** fEnvp;
std::string fMySection;
protected:
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
public:
plEnvConfigSource(char ** envp, const char * mySection="Environment");
};
/////////////////////////////////////////////////
class plIniConfigSource : public plConfigSource
{
protected:
std::string fFileName;
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
bool WriteOutOf(plConfigInfo & configInfo);
public:
plIniConfigSource(const char * iniFileName);
};
/////////////////////////////////////////////////
// just like above, but works with hsStream-derived classes
class hsStream;
class plIniStreamConfigSource : public plConfigSource
{
protected:
hsStream * fStream;
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
bool WriteOutOf(plConfigInfo & configInfo);
public:
plIniStreamConfigSource(hsStream * stream);
};
/////////////////////////////////////////////////
// an ini file reader/writer that ignores section headers and puts all
// data in an unnamed section, or more accurately, in a section named "".
class plIniNoSectionsConfigSource : public plConfigSource
{
std::string fFileName;
protected:
bool ReadString(const std::string & in);
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
bool WriteOutOf(plConfigInfo & configInfo);
public:
plIniNoSectionsConfigSource(const char * iniFileName);
};
/////////////////////////////////////////////////
// an ini file reader that only reads specified sections
class plIniSectionConfigSource : public plIniConfigSource
{
typedef std::vector<xtl::istring>
Sections;
protected:
Sections fSections;
bool ReadPair(std::string & key, std::string & value);
bool ReadSubSource( const char * name );
public:
plIniSectionConfigSource(const char * iniFileName, std::vector<std::string> & sections);
};
/////////////////////////////////////////////////
// TODO: This would be a cool thing. not needed right now though.
class plDatabaseConfigSource : public plConfigSource
{
protected:
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
bool WriteOutOf(plConfigInfo & configInfo);
public:
plDatabaseConfigSource(const char * connectString);
};
/////////////////////////////////////////////////
class plDebugConfigSource : public plConfigSource
{
protected:
std::string fFileName;
bool WriteOutOf(plConfigInfo & configInfo);
public:
plDebugConfigSource(){}
};
/////////////////////////////////////////////////
class plWWWAuthenticateConfigSource : public plConfigSource
{
const std::string& fAuth;
protected:
bool ReadInto(plConfigInfo & configInfo, KAddValueMode mode=kAlwaysAdd);
public:
plWWWAuthenticateConfigSource(const std::string& auth);
};
////////////////////////////////////////////////////////////////////
// NOTE: plClass _must_ appear first in a multiple-inheritance list.
class plClass
{
public:
virtual void Unused(){}
};
////////////////////////////////////////////////////////////////////
typedef bool (plClass::*TEvaluate)();
typedef bool (plClass::*TEvaluateConst)() const;
struct plEvaluate
{
plClass * fTarget;
bool (plClass::*fEvaluate)();
bool (plClass::*fEvaluateConst)() const;
plEvaluate( plClass * target=nil, TEvaluate evaluate=nil )
: fTarget(target)
, fEvaluate(evaluate)
, fEvaluateConst(nil)
{}
plEvaluate( plClass * target, TEvaluateConst evaluate )
: fTarget(target)
, fEvaluateConst(evaluate)
, fEvaluate(nil)
{}
bool operator()()
{
if (fEvaluate)
return (fTarget)?(fTarget->*fEvaluate)():true;
else
if (fEvaluateConst)
return (fTarget)?(fTarget->*fEvaluateConst)():true;
else
return true;
}
};
////////////////////////////////////////////////////////////////////
typedef std::string (plClass::*TModify)(const std::string & value);
struct plModify
{
plClass * fTarget;
std::string (plClass::*fModify)(const std::string & value);
plModify( plClass * target=nil, TModify modify=nil )
: fTarget(target)
, fModify(modify)
{}
std::string operator()(const std::string & value) { return (fTarget)?(fTarget->*fModify)(value):value;}
std::string operator()(const std::string & value) const { return (fTarget)?(fTarget->*fModify)(value):value;}
};
////////////////////////////////////////////////////////////////////
class plConfigValueBase
{
public:
std::string fConfigName;
std::string fConfigGroup;
plEvaluate fReadEvaluate; // returns true if we want to read this value from options
plEvaluate fWriteEvaluate; // returns true if we want to write this value to options
plModify fReadModify; // may modify the value being read from options
plModify fWriteModify; // may modify the value being written to options
plModify fGetModify; // may modify the value when being assigned
plModify fSetModify; // may modify the value when being accessed
plConfigValueBase( const char * configName="", const char * configGroup="" )
: fConfigName(configName)
, fConfigGroup(configGroup)
{}
void SetConfigName(const char * name) { fConfigName=(name)?name:"";}
std::string GetConfigName() const { return fConfigName;}
void SetConfigGroup(const char * group) { fConfigGroup=group;}
std::string GetConfigGroup() const { return fConfigGroup;}
bool HasConfigName() { return fConfigName.length()>0;}
bool HasConfigGroup() { return fConfigGroup.length()>0;}
virtual void ConfigRead(plConfigInfo * opts);
virtual void ConfigWrite(plConfigInfo * opts);
void SetValue(const char * value);
std::string GetValue() const;
virtual void ISetValue(const char * value) = 0;
virtual std::string IGetValue() const = 0;
void SetReadEvaluate(plClass * targetObj, TEvaluate evalFunc);
void SetWriteEvaluate(plClass * targetObj, TEvaluate evalFunc);
void SetWriteEvaluate(plClass * targetObj, TEvaluateConst evalFunc);
void SetReadModify(plClass * targetObj, TModify modifyFunc);
void SetWriteModify(plClass * targetObj, TModify modifyFunc);
void SetGetModify(plClass * targetObj, TModify modifyFunc);
void SetSetModify(plClass * targetObj, TModify modifyFunc);
};
////////////////////////////////////////////////////////////////////
class plConfigValue : public plConfigValueBase
{
public:
plConfigValue( const char * configName="", const char * configGroup="" )
: plConfigValueBase(configName, configGroup)
{}
std::string fConfigValue;
void ISetValue(const char * value) { fConfigValue=value;}
std::string IGetValue() const { return fConfigValue;}
};
////////////////////////////////////////////////////////////////////
class plConfigAggregateValue : public plConfigValueBase
{
public:
std::vector<plConfigValueBase*> fItems;
plConfigAggregateValue(
const char * name=nil,
// A vararg here would not work because of a
// multiple inheritance issue. Classes that are
// plConfigValueBase are likely to be derived from
// plClass also. Since plClass must be first in
// the inheritance list, the vararg would not
// point to the plConfigValueBase vtable that we
// need to access.
plConfigValueBase * item1=nil,
plConfigValueBase * item2=nil,
plConfigValueBase * item3=nil,
plConfigValueBase * item4=nil,
plConfigValueBase * item5=nil,
plConfigValueBase * item6=nil,
plConfigValueBase * item7=nil);
void ISetValue(const char * value);
std::string IGetValue() const;
void AddItem(plConfigValueBase * item);
void AddItems(
plConfigValueBase * item1=nil,
plConfigValueBase * item2=nil,
plConfigValueBase * item3=nil,
plConfigValueBase * item4=nil,
plConfigValueBase * item5=nil,
plConfigValueBase * item6=nil,
plConfigValueBase * item7=nil);
};
////////////////////////////////////////////////////////////////////
class plConfigValueProxy : public plConfigValueBase
{
plConfigValueBase * fConfigurable;
public:
plConfigValueProxy(plConfigValueBase * item=nil)
: fConfigurable(item)
{}
void Set(plConfigValueBase * item) { fConfigurable=item;}
void ISetValue(const char * value) { fConfigurable->ISetValue(value);}
std::string IGetValue() const { return fConfigurable->IGetValue();}
};
////////////////////////////////////////////////////////////////////
class plConfigGroup
{
public:
plConfigInfo fOpts;
std::string fGroupName;
std::vector<plConfigValueBase*> fItems;
plConfigGroup(const char * groupName="");
bool Read(plConfigSource * src);
bool Write(plConfigSource * src);
void AddItem(plConfigValueBase * item, const char * name=nil);
};
////////////////////////////////////////////////////////////////////
#endif // plConfigInfo_h_inc