|
|
|
/*==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/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
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==*/
|
|
|
|
#include "plConfigInfo.h"
|
|
|
|
|
|
|
|
#include "hsTypes.h"
|
|
|
|
#include "hsStlUtils.h"
|
|
|
|
#include <fstream>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
const std::string& plConfigInfo::GlobalSection()
|
|
|
|
{
|
|
|
|
static std::string section("global");
|
|
|
|
return section;
|
|
|
|
}
|
|
|
|
|
|
|
|
plConfigInfo::plConfigInfo()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
plConfigInfo::plConfigInfo(const plConfigInfo & src)
|
|
|
|
: fSections(src.fSections)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
plConfigInfo & plConfigInfo::operator =(const plConfigInfo & src)
|
|
|
|
{
|
|
|
|
fSections = src.fSections;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigInfo::Clear()
|
|
|
|
{
|
|
|
|
fSections.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigInfo::RemoveSection(const std::string & section)
|
|
|
|
{
|
|
|
|
fSections.erase(section.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigInfo::RemoveKey(const std::string & section, const std::string & key)
|
|
|
|
{
|
|
|
|
Sections::iterator si = fSections.find(section.c_str());
|
|
|
|
if (si != fSections.end())
|
|
|
|
fSections[section.c_str()].RemoveKey(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::HasSection(const std::string & section) const
|
|
|
|
{
|
|
|
|
return fSections.find(section.c_str())!=fSections.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::HasKey(const std::string & section, const std::string & key)
|
|
|
|
{
|
|
|
|
Sections::iterator si = fSections.find(section.c_str());
|
|
|
|
if (si == fSections.end())
|
|
|
|
return false;
|
|
|
|
return (si->second.HasKey(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::HasKeyAny(const std::string & key)
|
|
|
|
{
|
|
|
|
for (Sections::iterator si=fSections.begin(); si!=fSections.end(); ++si)
|
|
|
|
{
|
|
|
|
if (si->second.HasKey(key))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::HasKeyIn(const std::string & key, const char * section1, ...)
|
|
|
|
{
|
|
|
|
const char * section = section1;
|
|
|
|
va_list va;
|
|
|
|
va_start(va,section1);
|
|
|
|
std::vector<std::string> sections;
|
|
|
|
while (section)
|
|
|
|
{
|
|
|
|
sections.push_back( section );
|
|
|
|
section = va_arg(va,const char *);
|
|
|
|
}
|
|
|
|
va_end(va);
|
|
|
|
return HasKeyIn( key, sections );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::HasKeyIn(const std::string & key, const std::vector<std::string> & sections )
|
|
|
|
{
|
|
|
|
for ( int i=0; i<sections.size(); i++ )
|
|
|
|
{
|
|
|
|
const char * section = sections[i].c_str();
|
|
|
|
if (HasSection(section))
|
|
|
|
{
|
|
|
|
if (fSections[section].HasKey(key))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::KeyHasValue(const std::string & section, const std::string & key, const std::string & value)
|
|
|
|
{
|
|
|
|
Sections::iterator si = fSections.find(section.c_str());
|
|
|
|
if (si == fSections.end())
|
|
|
|
return false;
|
|
|
|
return si->second.KeyHasValue(key,value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::KeyHasValue(const std::string & section, const std::string & key, int value)
|
|
|
|
{
|
|
|
|
Sections::iterator si = fSections.find(section.c_str());
|
|
|
|
if (si == fSections.end())
|
|
|
|
return false;
|
|
|
|
return si->second.KeyHasValue(key,value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::KeyHasValue(const std::string & section, const std::string & key, double value)
|
|
|
|
{
|
|
|
|
Sections::iterator si = fSections.find(section.c_str());
|
|
|
|
if (si == fSections.end())
|
|
|
|
return false;
|
|
|
|
return si->second.KeyHasValue(key,value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::AddValue(const std::string & section, const std::string & key, const std::string & value, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
fSections[section.c_str()].AddValue(key,value,mode);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::AddValue(const std::string & section, const std::string & key, int value, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
char buf[20];
|
|
|
|
sprintf(buf, "%d", value);
|
|
|
|
std::string v(buf);
|
|
|
|
return AddValue(section,key,v,mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::AddValue(const std::string & section, const std::string & key, double value, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
char buf[30];
|
|
|
|
sprintf(buf, "%f", value);
|
|
|
|
std::string v(buf);
|
|
|
|
return AddValue(section,key,v,mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::AddValues(const std::string & section, const std::string & key, const std::vector<std::string> & values, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
return fSections[section.c_str()].AddValues(key,values);
|
|
|
|
}
|
|
|
|
|
|
|
|
plKeysAndValues plConfigInfo::GetSection(const std::string & section, bool & found)
|
|
|
|
{
|
|
|
|
found = HasSection(section);
|
|
|
|
if (found)
|
|
|
|
return fSections[section.c_str()];
|
|
|
|
else
|
|
|
|
return plKeysAndValues(); // empty
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> plConfigInfo::GetSectionNames()
|
|
|
|
{
|
|
|
|
std::vector<std::string> results;
|
|
|
|
for (Sections::const_iterator ii=fSections.begin(); ii!=fSections.end(); ++ii)
|
|
|
|
results.push_back(ii->first.c_str());
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string plConfigInfo::GetValue(const std::string & section, const std::string & key, const std::string & defval, bool * outFound) const
|
|
|
|
{
|
|
|
|
return fSections[section.c_str()].GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
|
|
|
|
int plConfigInfo::GetValue(const std::string & section, const std::string & key, int defval, bool * outFound) const
|
|
|
|
{
|
|
|
|
return fSections[section.c_str()].GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
|
|
|
|
double plConfigInfo::GetValue(const std::string & section, const std::string & key, double defval, bool * outFound) const
|
|
|
|
{
|
|
|
|
return fSections[section.c_str()].GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> plConfigInfo::GetAllValues(const std::string & section, const std::string & key) const
|
|
|
|
{
|
|
|
|
Sections::iterator si = fSections.find(section.c_str());
|
|
|
|
if (si != fSections.end())
|
|
|
|
return si->second.GetAllValues(key);
|
|
|
|
std::vector<std::string> empty;
|
|
|
|
return empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string plConfigInfo::GetValueAny(const std::string & key, const std::string & defval, bool * outFound) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
for (Sections::iterator si=fSections.begin(); si!=fSections.end(); ++si)
|
|
|
|
if (si->second.HasKey(key))
|
|
|
|
return si->second.GetValue(key,defval,outFound);
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int plConfigInfo::GetValueAny(const std::string & key, int defval, bool * outFound) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
for (Sections::iterator si=fSections.begin(); si!=fSections.end(); ++si)
|
|
|
|
if (si->second.HasKey(key))
|
|
|
|
return si->second.GetValue(key,defval,outFound);
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
double plConfigInfo::GetValueAny(const std::string & key, double defval, bool * outFound) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
for (Sections::iterator si=fSections.begin(); si!=fSections.end(); ++si)
|
|
|
|
if (si->second.HasKey(key))
|
|
|
|
return si->second.GetValue(key,defval,outFound);
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> plConfigInfo::GetAllValuesAny(const std::string & key) const
|
|
|
|
{
|
|
|
|
for (Sections::iterator si=fSections.begin(); si!=fSections.end(); ++si)
|
|
|
|
if (si->second.HasKey(key))
|
|
|
|
return si->second.GetAllValues(key);
|
|
|
|
std::vector<std::string> empty;
|
|
|
|
return empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string plConfigInfo::GetValueIn(const std::string & key, const std::string & defval, bool * outFound, const char * section1, ...) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
const char * section = section1;
|
|
|
|
va_list sections;
|
|
|
|
va_start(sections,section1);
|
|
|
|
while (section)
|
|
|
|
{
|
|
|
|
if (HasSection(section))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[section];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
return kv.GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
section = va_arg(sections,const char *);
|
|
|
|
}
|
|
|
|
va_end(sections);
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string plConfigInfo::GetValueIn(const std::string & key, const std::string & defval, bool * outFound, const std::vector<std::string> & sections ) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
for ( int i=0; i<sections.size(); i++ )
|
|
|
|
{
|
|
|
|
if (HasSection(sections[i]))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[sections[i].c_str()];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
return kv.GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int plConfigInfo::GetValueIn(const std::string & key, int defval, bool * outFound, const char * section1, ...) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
const char * section = section1;
|
|
|
|
va_list sections;
|
|
|
|
va_start(sections,section1);
|
|
|
|
while (section)
|
|
|
|
{
|
|
|
|
if (HasSection(section))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[section];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
return kv.GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
section = va_arg(sections,const char *);
|
|
|
|
}
|
|
|
|
va_end(sections);
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int plConfigInfo::GetValueIn(const std::string & key, int defval, bool * outFound, const std::vector<std::string> & sections ) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
for ( int i=0; i<sections.size(); i++ )
|
|
|
|
{
|
|
|
|
if (HasSection(sections[i]))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[sections[i].c_str()];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
return kv.GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
double plConfigInfo::GetValueIn(const std::string & key, double defval, bool * outFound, const char * section1, ...) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
const char * section = section1;
|
|
|
|
va_list sections;
|
|
|
|
va_start(sections,section1);
|
|
|
|
while (section)
|
|
|
|
{
|
|
|
|
if (HasSection(section))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[section];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
return kv.GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
section = va_arg(sections,const char *);
|
|
|
|
}
|
|
|
|
va_end(sections);
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
double plConfigInfo::GetValueIn(const std::string & key, double defval, bool * outFound, const std::vector<std::string> & sections ) const
|
|
|
|
{
|
|
|
|
if (outFound) *outFound=false;
|
|
|
|
for ( int i=0; i<sections.size(); i++ )
|
|
|
|
{
|
|
|
|
if (HasSection(sections[i]))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[sections[i].c_str()];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
return kv.GetValue(key,defval,outFound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> plConfigInfo::GetAllValuesIn(const std::string & key, const char * section1, ...)
|
|
|
|
{
|
|
|
|
const char * section = section1;
|
|
|
|
va_list sections;
|
|
|
|
va_start(sections,section1);
|
|
|
|
std::vector<std::string> result;
|
|
|
|
while (section)
|
|
|
|
{
|
|
|
|
if (HasSection(section))
|
|
|
|
{
|
|
|
|
plKeysAndValues & kv = fSections[section];
|
|
|
|
if (kv.HasKey(key))
|
|
|
|
{
|
|
|
|
std::vector<std::string> values = kv.GetAllValues(key);
|
|
|
|
result.insert(result.end(),values.begin(),values.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
section = va_arg(sections,const char *);
|
|
|
|
}
|
|
|
|
va_end(sections);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::GetSectionIterators(Sections::const_iterator & iter, Sections::const_iterator & end) const
|
|
|
|
{
|
|
|
|
iter = fSections.begin();
|
|
|
|
end = fSections.end();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::GetKeyIterators(const xtl::istring & section, Keys::const_iterator & iter, Keys::const_iterator & end) const
|
|
|
|
{
|
|
|
|
Sections::const_iterator si = fSections.find(section);
|
|
|
|
if (si==fSections.end())
|
|
|
|
return false;
|
|
|
|
return fSections[section].GetKeyIterators(iter, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::GetValueIterators(const xtl::istring & section, const xtl::istring & key, Values::const_iterator & iter, Values::const_iterator & end) const
|
|
|
|
{
|
|
|
|
Sections::const_iterator si = fSections.find(section);
|
|
|
|
if (si==fSections.end())
|
|
|
|
return false;
|
|
|
|
return fSections[section].GetValueIterators(key, iter, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::ReadFrom(plConfigSource * src, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
return src->ReadInto(*this,mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigInfo::WriteTo(plConfigSource * src)
|
|
|
|
{
|
|
|
|
return src->WriteOutOf(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void plConfigSource::SplitAt(std::string & key, std::string & value, char splitter, std::string & in)
|
|
|
|
{
|
|
|
|
if(in.length() == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int t = in.find(splitter);
|
|
|
|
if(t == std::string::npos)
|
|
|
|
{
|
|
|
|
key = in;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
key.assign(in.substr(0,t));
|
|
|
|
value.assign(in.substr(t+1,in.size()-t-1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plConfigSource::ReadString(const std::string & in)
|
|
|
|
{
|
|
|
|
std::string work = in;
|
|
|
|
xtl::trim(work);
|
|
|
|
|
|
|
|
// comment
|
|
|
|
if (work[0] == '#')
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// comment
|
|
|
|
if (work[0] == ';')
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// section
|
|
|
|
if (work[0] == '[')
|
|
|
|
{
|
|
|
|
int close = work.find_first_of("]");
|
|
|
|
if(close == std::string::npos)
|
|
|
|
return false;
|
|
|
|
fCurrSection = work.substr(1,close-1);
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// key=value
|
|
|
|
std::string key, value;
|
|
|
|
SplitAt(key, value, '=', work);
|
|
|
|
|
|
|
|
// dot notation makes section change for this key=value only.
|
|
|
|
int t = key.find('.');
|
|
|
|
if (t>0 && t<key.size()-1)
|
|
|
|
{
|
|
|
|
fEffectiveSection.assign(key.substr(0,t));
|
|
|
|
key.assign(key.substr(t+1));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ret=ReadPair(key, value);
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
|
|
|
|
if(ret && strcmp("LoadIni",key.c_str()) == 0)
|
|
|
|
{
|
|
|
|
ret = ReadSubSource( value.c_str() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigSource::ReadPair(std::string & key, std::string & value)
|
|
|
|
{
|
|
|
|
hsAssert(fConfigInfo, "plConfigSource::ProcessPair: fConfigInfo not set.");
|
|
|
|
|
|
|
|
xtl::trim(key);
|
|
|
|
xtl::trim(value);
|
|
|
|
xtl::trim(value,"\"'");
|
|
|
|
|
|
|
|
if (key.size() == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return fConfigInfo->AddValue(fEffectiveSection, key, value, fAddMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plConfigSource::ReadList(char ** l)
|
|
|
|
{
|
|
|
|
while(*l != NULL)
|
|
|
|
{
|
|
|
|
ReadString(*l);
|
|
|
|
l++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
fConfigInfo = &configInfo;
|
|
|
|
fAddMode = mode;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plConfigSource::WriteOutOf(plConfigInfo & configInfo)
|
|
|
|
{
|
|
|
|
fConfigInfo = &configInfo;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plCmdLineConfigSource::plCmdLineConfigSource(int argc, char ** argv, const char * mySection)
|
|
|
|
: fArgc(argc)
|
|
|
|
, fArgv(argv)
|
|
|
|
, fMySection(mySection?mySection:"")
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
bool plCmdLineConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
int argc = fArgc;
|
|
|
|
char ** argv = fArgv;
|
|
|
|
|
|
|
|
if (!plConfigSource::ReadInto(configInfo, mode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
fCurrSection = fMySection;
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
|
|
|
|
if(argc < 1)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
fConfigInfo->AddValue(fEffectiveSection.c_str(), "ARGV0", *argv, fAddMode);
|
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
|
|
|
|
while(argc > 0)
|
|
|
|
{
|
|
|
|
if(ReadString(*argv) != true)
|
|
|
|
{
|
|
|
|
// TODO: log error here
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
argv++;
|
|
|
|
argc--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plEnvConfigSource::plEnvConfigSource(char ** envp, const char * mySection)
|
|
|
|
: fEnvp(envp)
|
|
|
|
, fMySection(mySection?mySection:"")
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
bool plEnvConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::ReadInto(configInfo, mode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (fEnvp != NULL)
|
|
|
|
{
|
|
|
|
fCurrSection = fMySection;
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
return ReadList(fEnvp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plIniConfigSource::plIniConfigSource(const char * iniFileName)
|
|
|
|
: fFileName(iniFileName)
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
bool plIniConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::ReadInto(configInfo, mode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
fCurrSection = plConfigInfo::GlobalSection();
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
|
|
|
|
if(fFileName.size() < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
std::ifstream file;
|
|
|
|
file.open(fFileName.c_str());
|
|
|
|
|
|
|
|
if(!file.is_open())
|
|
|
|
{
|
|
|
|
// TODO log error here
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char buf[4096];
|
|
|
|
|
|
|
|
while (!file.eof())
|
|
|
|
{
|
|
|
|
file.getline(buf, 4096);
|
|
|
|
|
|
|
|
if(!ReadString(buf))
|
|
|
|
{
|
|
|
|
// TODO log warning here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plIniConfigSource::WriteOutOf(plConfigInfo & configInfo)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::WriteOutOf(configInfo))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::ofstream file;
|
|
|
|
file.open(fFileName.c_str());
|
|
|
|
|
|
|
|
if(!file.is_open())
|
|
|
|
{
|
|
|
|
// TODO log error here
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
file
|
|
|
|
<< "# This is an auto-generated file." << std::endl
|
|
|
|
<< std::endl
|
|
|
|
;
|
|
|
|
|
|
|
|
plConfigInfo::Sections::const_iterator si, se;
|
|
|
|
plConfigInfo::Keys::const_iterator ki, ke;
|
|
|
|
plConfigInfo::Values::const_iterator vi, ve;
|
|
|
|
|
|
|
|
fConfigInfo->GetSectionIterators(si,se);
|
|
|
|
for (; si!=se; ++si)
|
|
|
|
{
|
|
|
|
file << std::endl << "[" << si->first.c_str() << "]"<< std::endl;
|
|
|
|
if (fConfigInfo->GetKeyIterators(si->first, ki, ke))
|
|
|
|
for (; ki!=ke; ++ki)
|
|
|
|
{
|
|
|
|
if (fConfigInfo->GetValueIterators(si->first, ki->first, vi, ve))
|
|
|
|
for (; vi!=ve; ++vi)
|
|
|
|
{
|
|
|
|
file << ki->first.c_str() << "=" << vi->c_str() << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plIniStreamConfigSource::plIniStreamConfigSource(hsStream * stream)
|
|
|
|
: fStream(stream)
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
bool plIniStreamConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::ReadInto(configInfo, mode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
fCurrSection = "global";
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
|
|
|
|
if ( !fStream )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
char buf[4096];
|
|
|
|
|
|
|
|
while (!fStream->AtEnd())
|
|
|
|
{
|
|
|
|
fStream->ReadLn( buf, sizeof(buf) );
|
|
|
|
|
|
|
|
if(!ReadString(buf))
|
|
|
|
{
|
|
|
|
// TODO log warning here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plIniStreamConfigSource::WriteOutOf(plConfigInfo & configInfo)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::WriteOutOf(configInfo))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( !fStream )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
|
|
|
plConfigInfo::Sections::const_iterator si, se;
|
|
|
|
plConfigInfo::Keys::const_iterator ki, ke;
|
|
|
|
plConfigInfo::Values::const_iterator vi, ve;
|
|
|
|
|
|
|
|
fConfigInfo->GetSectionIterators(si,se);
|
|
|
|
for (; si!=se; ++si)
|
|
|
|
{
|
|
|
|
ss << std::endl << "[" << si->first.c_str() << "]"<< std::endl;
|
|
|
|
if (fConfigInfo->GetKeyIterators(si->first, ki, ke))
|
|
|
|
for (; ki!=ke; ++ki)
|
|
|
|
{
|
|
|
|
if (fConfigInfo->GetValueIterators(si->first, ki->first, vi, ve))
|
|
|
|
for (; vi!=ve; ++vi)
|
|
|
|
{
|
|
|
|
ss << ki->first.c_str() << "=" << vi->c_str() << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fStream->WriteString( ss.str().c_str() );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plIniSectionConfigSource::plIniSectionConfigSource(const char * iniFileName, std::vector<std::string> & sections)
|
|
|
|
: plIniConfigSource(iniFileName)
|
|
|
|
{
|
|
|
|
for (int i=0; i<sections.size(); i++)
|
|
|
|
fSections.push_back(sections[i].c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plIniSectionConfigSource::ReadPair(std::string & key, std::string & value)
|
|
|
|
{
|
|
|
|
hsAssert(fConfigInfo, "plConfigSource::ProcessPair: fConfigInfo not set.");
|
|
|
|
|
|
|
|
// the current section must be in list of sections.
|
|
|
|
std::vector<xtl::istring>::iterator ii = std::find(fSections.begin(), fSections.end(), fCurrSection.c_str());
|
|
|
|
|
|
|
|
if (ii==fSections.end())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
xtl::trim(key);
|
|
|
|
xtl::trim(value);
|
|
|
|
xtl::trim(value,"\"'");
|
|
|
|
|
|
|
|
if (key.size() == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (key == "section")
|
|
|
|
fSections.push_back(value.c_str());
|
|
|
|
|
|
|
|
return fConfigInfo->AddValue(fEffectiveSection, key, value, fAddMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plIniSectionConfigSource::ReadSubSource( const char * name )
|
|
|
|
{
|
|
|
|
std::vector<std::string> sections;
|
|
|
|
for ( int i=0; i<fSections.size(); i++ )
|
|
|
|
sections.push_back( fSections[i].c_str() );
|
|
|
|
plIniSectionConfigSource src(name, sections);
|
|
|
|
return fConfigInfo->ReadFrom(&src);
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plIniNoSectionsConfigSource::plIniNoSectionsConfigSource(const char * filename)
|
|
|
|
: fFileName(filename)
|
|
|
|
{
|
|
|
|
fEffectiveSection = fCurrSection = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plIniNoSectionsConfigSource::ReadString(const std::string & in)
|
|
|
|
{
|
|
|
|
std::string work = in;
|
|
|
|
xtl::trim(work);
|
|
|
|
|
|
|
|
// ignore comments
|
|
|
|
if (work[0]=='#' || work[0]==';')
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// ignore sections
|
|
|
|
if (work[0] == '[')
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// parse key value
|
|
|
|
std::string key, value;
|
|
|
|
SplitAt(key, value, '=', work);
|
|
|
|
|
|
|
|
return ReadPair(key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plIniNoSectionsConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::ReadInto(configInfo, mode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(fFileName.size() < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::ifstream file;
|
|
|
|
file.open(fFileName.c_str());
|
|
|
|
|
|
|
|
if(!file.is_open())
|
|
|
|
{
|
|
|
|
// TODO log error here
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char buf[4096];
|
|
|
|
|
|
|
|
while (!file.eof())
|
|
|
|
{
|
|
|
|
file.getline(buf, 4096);
|
|
|
|
|
|
|
|
if(!ReadString(buf))
|
|
|
|
{
|
|
|
|
// TODO log warning here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool plIniNoSectionsConfigSource::WriteOutOf(plConfigInfo & configInfo)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::WriteOutOf(configInfo))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::ofstream file;
|
|
|
|
file.open(fFileName.c_str());
|
|
|
|
|
|
|
|
if(!file.is_open())
|
|
|
|
{
|
|
|
|
// TODO log error here
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
file
|
|
|
|
<< "# This is an auto-generated file." << std::endl
|
|
|
|
<< std::endl
|
|
|
|
;
|
|
|
|
|
|
|
|
plConfigInfo::Sections::const_iterator si, se;
|
|
|
|
plConfigInfo::Keys::const_iterator ki, ke;
|
|
|
|
plConfigInfo::Values::const_iterator vi, ve;
|
|
|
|
|
|
|
|
fConfigInfo->GetSectionIterators(si,se);
|
|
|
|
for (; si!=se; ++si)
|
|
|
|
{
|
|
|
|
if (fConfigInfo->GetKeyIterators(si->first, ki, ke))
|
|
|
|
for (; ki!=ke; ++ki)
|
|
|
|
{
|
|
|
|
if (fConfigInfo->GetValueIterators(si->first, ki->first, vi, ve))
|
|
|
|
for (; vi!=ve; ++vi)
|
|
|
|
{
|
|
|
|
file << ki->first.c_str() << "=" << vi->c_str() << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
|
|
|
|
bool plDebugConfigSource::WriteOutOf(plConfigInfo & configInfo)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::WriteOutOf(configInfo))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
plConfigInfo::Sections::const_iterator si, se;
|
|
|
|
plConfigInfo::Keys::const_iterator ki, ke;
|
|
|
|
plConfigInfo::Values::const_iterator vi, ve;
|
|
|
|
|
|
|
|
char buf[1024];
|
|
|
|
fConfigInfo->GetSectionIterators(si,se);
|
|
|
|
for (; si!=se; ++si)
|
|
|
|
{
|
|
|
|
sprintf(buf,"\n[%s]\n",si->first.c_str());
|
|
|
|
hsStatusMessage(buf);
|
|
|
|
if (fConfigInfo->GetKeyIterators(si->first, ki, ke))
|
|
|
|
for (; ki!=ke; ++ki)
|
|
|
|
{
|
|
|
|
if (fConfigInfo->GetValueIterators(si->first, ki->first, vi, ve))
|
|
|
|
for (; vi!=ve; ++vi)
|
|
|
|
{
|
|
|
|
sprintf(buf,"%s=%s\n",ki->first.c_str(),vi->c_str());
|
|
|
|
hsStatusMessage(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void plConfigValueBase::ConfigRead(plConfigInfo * opts)
|
|
|
|
{
|
|
|
|
if (fReadEvaluate())
|
|
|
|
{
|
|
|
|
std::string value;
|
|
|
|
bool found;
|
|
|
|
value = opts->GetValue(GetConfigGroup(),GetConfigName(),"",&found);
|
|
|
|
if (found)
|
|
|
|
SetValue(fReadModify(value).c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::ConfigWrite(plConfigInfo * opts)
|
|
|
|
{
|
|
|
|
if (fWriteEvaluate())
|
|
|
|
{
|
|
|
|
opts->AddValue(GetConfigGroup(),GetConfigName(),fWriteModify(GetValue()),kAlwaysAdd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetValue(const char * value)
|
|
|
|
{
|
|
|
|
ISetValue(fSetModify(value).c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string plConfigValueBase::GetValue() const
|
|
|
|
{
|
|
|
|
return fGetModify(IGetValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetReadEvaluate(plClass * targetObj, TEvaluate evalFunc)
|
|
|
|
{
|
|
|
|
fReadEvaluate = plEvaluate(targetObj,evalFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetWriteEvaluate(plClass * targetObj, TEvaluate evalFunc)
|
|
|
|
{
|
|
|
|
fWriteEvaluate = plEvaluate(targetObj,evalFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetWriteEvaluate(plClass * targetObj, TEvaluateConst evalFunc)
|
|
|
|
{
|
|
|
|
fWriteEvaluate = plEvaluate(targetObj,evalFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetReadModify(plClass * targetObj, TModify modifyFunc)
|
|
|
|
{
|
|
|
|
fReadModify = plModify(targetObj,modifyFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetWriteModify(plClass * targetObj, TModify modifyFunc)
|
|
|
|
{
|
|
|
|
fWriteModify = plModify(targetObj,modifyFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetGetModify(plClass * targetObj, TModify modifyFunc)
|
|
|
|
{
|
|
|
|
fGetModify = plModify(targetObj,modifyFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigValueBase::SetSetModify(plClass * targetObj, TModify modifyFunc)
|
|
|
|
{
|
|
|
|
fSetModify = plModify(targetObj,modifyFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plConfigGroup::plConfigGroup(const char * groupName)
|
|
|
|
: fGroupName(groupName)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool plConfigGroup::Read(plConfigSource * src)
|
|
|
|
{
|
|
|
|
if (!fOpts.ReadFrom(src))
|
|
|
|
return false;
|
|
|
|
for (int i=0; i<fItems.size(); i++)
|
|
|
|
fItems[i]->ConfigRead(&fOpts);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plConfigGroup::Write(plConfigSource * src)
|
|
|
|
{
|
|
|
|
for (int i=0; i<fItems.size(); i++)
|
|
|
|
fItems[i]->ConfigWrite(&fOpts);
|
|
|
|
return fOpts.WriteTo(src);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigGroup::AddItem(plConfigValueBase * item, const char * name)
|
|
|
|
{
|
|
|
|
item->SetConfigGroup(fGroupName.c_str());
|
|
|
|
if (name)
|
|
|
|
item->SetConfigName(name);
|
|
|
|
fItems.push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plConfigAggregateValue::plConfigAggregateValue(
|
|
|
|
const char * name,
|
|
|
|
plConfigValueBase * item1,
|
|
|
|
plConfigValueBase * item2,
|
|
|
|
plConfigValueBase * item3,
|
|
|
|
plConfigValueBase * item4,
|
|
|
|
plConfigValueBase * item5,
|
|
|
|
plConfigValueBase * item6,
|
|
|
|
plConfigValueBase * item7)
|
|
|
|
{
|
|
|
|
SetConfigName(name);
|
|
|
|
AddItems(item1,item2,item3,item4,item5,item6,item7);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigAggregateValue::AddItems(
|
|
|
|
plConfigValueBase * item1,
|
|
|
|
plConfigValueBase * item2,
|
|
|
|
plConfigValueBase * item3,
|
|
|
|
plConfigValueBase * item4,
|
|
|
|
plConfigValueBase * item5,
|
|
|
|
plConfigValueBase * item6,
|
|
|
|
plConfigValueBase * item7)
|
|
|
|
{
|
|
|
|
fItems.clear();
|
|
|
|
if (item1) AddItem(item1);
|
|
|
|
if (item2) AddItem(item2);
|
|
|
|
if (item3) AddItem(item3);
|
|
|
|
if (item4) AddItem(item4);
|
|
|
|
if (item5) AddItem(item5);
|
|
|
|
if (item6) AddItem(item6);
|
|
|
|
if (item7) AddItem(item7);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigAggregateValue::ISetValue(const char * value)
|
|
|
|
{
|
|
|
|
std::string work = value;
|
|
|
|
int p=0,i=0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
xtl::trim(work);
|
|
|
|
p = work.find(" ");
|
|
|
|
fItems[i]->SetValue(work.substr(0,p).c_str());
|
|
|
|
work.erase(0,p);
|
|
|
|
i++;
|
|
|
|
} while (i<fItems.size() && p!=std::string::npos);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string plConfigAggregateValue::IGetValue() const
|
|
|
|
{
|
|
|
|
std::string value;
|
|
|
|
for (int i=0; i<fItems.size(); i++)
|
|
|
|
{
|
|
|
|
value.append(fItems[i]->GetValue());
|
|
|
|
value.append(" ");
|
|
|
|
}
|
|
|
|
return xtl::trim(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plConfigAggregateValue::AddItem(plConfigValueBase * item)
|
|
|
|
{
|
|
|
|
fItems.push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plWWWAuthenticateConfigSource::plWWWAuthenticateConfigSource(const std::string& auth)
|
|
|
|
: fAuth(auth)
|
|
|
|
{
|
|
|
|
fEffectiveSection = fCurrSection = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plWWWAuthenticateConfigSource::ReadInto(plConfigInfo & configInfo, KAddValueMode mode)
|
|
|
|
{
|
|
|
|
if (!plConfigSource::ReadInto(configInfo, mode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
fCurrSection = "global";
|
|
|
|
fEffectiveSection = fCurrSection;
|
|
|
|
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
|
|
|
while (i < fAuth.size())
|
|
|
|
{
|
|
|
|
bool inQuote = false;
|
|
|
|
unsigned int begin = i,end;
|
|
|
|
while (i < fAuth.size()
|
|
|
|
&& ((fAuth[i] != ',' && !inQuote) || inQuote))
|
|
|
|
{
|
|
|
|
if (fAuth[i] == '"')
|
|
|
|
inQuote = ! inQuote;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
end = i;
|
|
|
|
|
|
|
|
std::string buf;
|
|
|
|
buf.assign(fAuth,begin,end-begin);
|
|
|
|
if(!ReadString(buf.c_str()))
|
|
|
|
{
|
|
|
|
// TODO log warning here
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|