Core: INI_INT64, INI_INT and INI_INT64 now understand hex and K, M, G, T suffixes

git-svn-id: svn://ultimatepp.org/upp/trunk@5183 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2012-07-13 10:17:23 +00:00
parent b445e09358
commit cf0ee3a247
4 changed files with 356 additions and 262 deletions

View file

@ -30,8 +30,8 @@ options(XGNU) -ffunction-sections;
link(SOLARIS) "-Wl,-R -Wl,/usr/local/lib";
file
config.h,
Core.h,
config.h,
Defs.h,
Cpu.cpp optimize_speed,
Mt.h,
@ -68,6 +68,7 @@ file
Log.cpp,
Debug.cpp,
Util.h,
Ini.cpp,
Util.cpp optimize_speed,
mathutil.cpp optimize_speed,
Random.cpp,

316
uppsrc/Core/Ini.cpp Normal file
View file

@ -0,0 +1,316 @@
#include "Core.h"
namespace Upp {
VectorMap<String, String> LoadIniStream(Stream &sin) {
Stream *in = &sin;
FileIn fin;
VectorMap<String, String> key;
int c;
if((c = in->Get()) < 0) return key;
for(;;) {
String k, v;
for(;;) {
if(IsAlNum(c) || c == '_')
k.Cat(c);
else
break;
if((c = in->Get()) < 0) return key;
}
for(;;) {
if(c != '=' && c != ' ') break;
if((c = in->Get()) < 0) return key;
}
for(;;) {
if(c < ' ') break;
v.Cat(c);
if((c = in->Get()) < 0) break;
}
if(!k.IsEmpty())
key.Add(k, v);
if(k == "LINK") {
if(in == &fin)
fin.Close();
if(!fin.Open(v) || (c = in->Get()) < 0) return key;
in = &fin;
}
else
for(;;) {
if(IsAlNum(c) || c == '_') break;
if((c = in->Get()) < 0) return key;
}
}
}
VectorMap<String, String> LoadIniFile(const char *filename) {
FileIn in(filename);
if(!in) return VectorMap<String, String>();
return LoadIniStream(in);
}
static StaticMutex sMtx;
static char sIniFile[256];
static bool s_ini_loaded;
void ReloadIniFile()
{
s_ini_loaded = false;
}
void SetIniFile(const char *name) {
Mutex::Lock __(sMtx);
strcpy(sIniFile, name);
ReloadIniFile();
}
String GetIniKey(const char *id, const String& def) {
Mutex::Lock __(sMtx);
static VectorMap<String, String> key;
if(!s_ini_loaded) {
s_ini_loaded = true;
key = LoadIniFile(*sIniFile ? sIniFile : ~ConfigFile("q.ini"));
#ifdef PLATFORM_WIN32
if(key.GetCount() == 0)
key = LoadIniFile(~GetExeDirFile("q.ini"));
if(key.GetCount() == 0)
key = LoadIniFile("c:\\q.ini");
#endif
#ifdef PLATFORM_POSIX
if(key.GetCount() == 0)
key = LoadIniFile(GetHomeDirFile("q.ini"));
#endif
}
return key.Get(id, def);
}
String GetIniKey(const char *id)
{
return GetIniKey(id, String());
}
IniString::operator String()
{
ONCELOCK_(loaded) {
static Array<String> ss;
String& x = ss.Add();
x = TrimBoth(GetIniKey(id));
if(IsNull(x))
x = (*def)();
value = &x;
}
return *value;
}
String IniString::operator=(const String& s)
{
operator String();
*value = s;
return s;
}
String IniString::ToString() const
{
return (String)const_cast<IniString&>(*this);
}
int64 ReadIniInt(const char *id)
{
String s = GetIniKey(id);
CParser p(s);
int64 num;
int sgn = 1;
if(p.Char('-'))
sgn = -1;
else
p.Char('+');
if(p.Char2('0', 'x') || p.Char2('0', 'X'))
num = p.ReadNumber64(16);
else
if(p.IsNumber())
num = p.ReadNumber();
else
return Null;
num = sgn * num;
if(p.Char('K'))
num <<= 10;
else
if(p.Char('M'))
num <<= 20;
else
if(p.Char('G'))
num <<= 30;
else
if(p.Char('T'))
num <<= 40;
return num;
}
IniInt::operator int() {
ONCELOCK_(loaded) {
value = (int)ReadIniInt(id);
if(IsNull(value))
value = (*def)();
}
return value;
}
int IniInt::operator=(int b) {
ONCELOCK_(loaded) {}
return value = b;
}
String IniInt::ToString() const
{
return AsString((int)const_cast<IniInt&>(*this));
}
IniInt64::operator int64()
{
ONCELOCK_(loaded) {
value = ReadIniInt(id);
if(IsNull(value))
value = (*def)();
}
return value;
}
int64 IniInt64::operator=(int64 b)
{
ONCELOCK_(loaded) {}
return value = b;
}
String IniInt64::ToString() const
{
return AsString((int64)const_cast<IniInt64&>(*this));
}
IniDouble::operator double()
{
ONCELOCK_(loaded) {
value = ScanDouble(TrimBoth(ToLower(GetIniKey(id))));
if(IsNull(value))
value = (*def)();
}
return value;
}
double IniDouble::operator=(double b)
{
ONCELOCK_(loaded) {}
return value = b;
}
String IniDouble::ToString() const
{
return AsString((double)const_cast<IniDouble&>(*this));
}
IniBool::operator bool() {
ONCELOCK_(loaded) {
String h = TrimBoth(ToLower(GetIniKey(id)));
if(h.GetCount())
value = h == "1" || h == "yes" || h == "true" || h == "y";
else
value = (*def)();
}
return value;
}
bool IniBool::operator=(bool b) {
ONCELOCK_(loaded) {}
return value = b;
}
String IniBool::ToString() const
{
return AsString((bool)const_cast<IniBool&>(*this));
}
Array<IniInfo>& sIniInfo()
{
static Array<IniInfo> s;
return s;
}
void AddIniInfo(const char *id, String (*current)(), String (*def)(), const char *info)
{
IniInfo& f = sIniInfo().Add();
f.id = id;
f.current = current;
f.def = def;
f.info = info;
}
const Array<IniInfo> GetIniInfo()
{
return sIniInfo();
}
String GetIniInfoFormatted()
{
String r;
for(int i = 0; i < sIniInfo().GetCount(); i++) {
IniInfo& f = sIniInfo()[i];
r << f.id << " = " << (*f.current)() << " [default: " << (*f.def)() << "]\r\n"
<< " " << f.info << "\r\n";
}
return r;
}
void TextSettings::Load(const char *filename)
{
FileIn in(filename);
int themei = 0;
settings.Add("");
while(!in.IsEof()) {
String ln = in.GetLine();
const char *s = ln;
if(*s == '[') {
s++;
String theme;
while(*s && *s != ']')
theme.Cat(*s++);
themei = settings.FindAdd(theme);
}
else {
if(themei >= 0) {
String key;
while(*s && *s != '=') {
key.Cat(*s++);
}
if(*s == '=') s++;
String value;
while(*s) {
value.Cat(*s++);
}
if(!IsEmpty(key))
settings[themei].GetAdd(TrimBoth(key)) = TrimBoth(value);
}
}
}
}
String TextSettings::Get(const char *group, const char *key) const
{
int itemi = settings.Find(group);
return itemi < 0 ? Null : settings.Get(group).Get(key, Null);
}
String TextSettings::Get(int groupIndex, const char *key) const
{
return groupIndex >= 0 && groupIndex < settings.GetCount() ?
settings[groupIndex].Get(key, Null) : Null;
}
String TextSettings::Get(int groupIndex, int keyIndex) const
{
if (groupIndex >= 0 && groupIndex < settings.GetCount())
return keyIndex >= 0 && keyIndex < settings[groupIndex].GetCount() ?
settings[groupIndex][keyIndex] : Null;
else
return Null;
}
};

View file

@ -342,263 +342,6 @@ WString Join(const Vector<WString>& im, const WString& delim) {
}
return r;
}
// ---------------------------
VectorMap<String, String> LoadIniStream(Stream &sin) {
Stream *in = &sin;
FileIn fin;
VectorMap<String, String> key;
int c;
if((c = in->Get()) < 0) return key;
for(;;) {
String k, v;
for(;;) {
if(IsAlNum(c) || c == '_')
k.Cat(c);
else
break;
if((c = in->Get()) < 0) return key;
}
for(;;) {
if(c != '=' && c != ' ') break;
if((c = in->Get()) < 0) return key;
}
for(;;) {
if(c < ' ') break;
v.Cat(c);
if((c = in->Get()) < 0) break;
}
if(!k.IsEmpty())
key.Add(k, v);
if(k == "LINK") {
if(in == &fin)
fin.Close();
if(!fin.Open(v) || (c = in->Get()) < 0) return key;
in = &fin;
}
else
for(;;) {
if(IsAlNum(c) || c == '_') break;
if((c = in->Get()) < 0) return key;
}
}
}
VectorMap<String, String> LoadIniFile(const char *filename) {
FileIn in(filename);
if(!in) return VectorMap<String, String>();
return LoadIniStream(in);
}
static StaticMutex sMtx;
static char sIniFile[256];
static bool s_ini_loaded;
void ReloadIniFile()
{
s_ini_loaded = false;
}
void SetIniFile(const char *name) {
Mutex::Lock __(sMtx);
strcpy(sIniFile, name);
ReloadIniFile();
}
String GetIniKey(const char *id, const String& def) {
Mutex::Lock __(sMtx);
static VectorMap<String, String> key;
if(!s_ini_loaded) {
s_ini_loaded = true;
key = LoadIniFile(*sIniFile ? sIniFile : ~ConfigFile("q.ini"));
#ifdef PLATFORM_WIN32
if(key.GetCount() == 0)
key = LoadIniFile(~GetExeDirFile("q.ini"));
if(key.GetCount() == 0)
key = LoadIniFile("c:\\q.ini");
#endif
#ifdef PLATFORM_POSIX
if(key.GetCount() == 0)
key = LoadIniFile(GetHomeDirFile("q.ini"));
#endif
}
return key.Get(id, def);
}
String GetIniKey(const char *id)
{
return GetIniKey(id, String());
}
IniString::operator String()
{
ONCELOCK_(loaded) {
static Array<String> ss;
String& x = ss.Add();
x = Nvl(TrimBoth(GetIniKey(id)), (*def)());
value = &x;
}
return *value;
}
String IniString::operator=(const String& s)
{
operator String();
*value = s;
return s;
}
String IniString::ToString() const
{
return (String)const_cast<IniString&>(*this);
}
IniInt::operator int() {
ONCELOCK_(loaded) {
value = ScanInt(TrimBoth(ToLower(GetIniKey(id))));
if(IsNull(value))
value = (*def)();
}
return value;
}
int IniInt::operator=(int b) {
ONCELOCK_(loaded) {}
return value = b;
}
String IniInt::ToString() const
{
return AsString((int)const_cast<IniInt&>(*this));
}
IniDouble::operator double()
{
ONCELOCK_(loaded) {
value = ScanDouble(TrimBoth(ToLower(GetIniKey(id))));
if(IsNull(value))
value = (*def)();
}
return value;
}
double IniDouble::operator=(double b)
{
ONCELOCK_(loaded) {}
return value = b;
}
String IniDouble::ToString() const
{
return AsString((double)const_cast<IniDouble&>(*this));
}
IniBool::operator bool() {
ONCELOCK_(loaded) {
String h = TrimBoth(ToLower(GetIniKey(id)));
value = h.GetCount() ? h == "1" || h == "yes" || h == "true" || h == "y" : (*def)();
}
return value;
}
bool IniBool::operator=(bool b) {
ONCELOCK_(loaded) {}
return value = b;
}
String IniBool::ToString() const
{
return AsString((bool)const_cast<IniBool&>(*this));
}
Array<IniInfo>& sIniInfo()
{
static Array<IniInfo> s;
return s;
}
void AddIniInfo(const char *id, String (*current)(), String (*def)(), const char *info)
{
IniInfo& f = sIniInfo().Add();
f.id = id;
f.current = current;
f.def = def;
f.info = info;
}
const Array<IniInfo> GetIniInfo()
{
return sIniInfo();
}
String GetIniInfoFormatted()
{
String r;
for(int i = 0; i < sIniInfo().GetCount(); i++) {
IniInfo& f = sIniInfo()[i];
r << f.id << " = " << (*f.current)() << " [default: " << (*f.def)() << "]\r\n"
<< " " << f.info << "\r\n";
}
return r;
}
void TextSettings::Load(const char *filename)
{
FileIn in(filename);
int themei = 0;
settings.Add("");
while(!in.IsEof()) {
String ln = in.GetLine();
const char *s = ln;
if(*s == '[') {
s++;
String theme;
while(*s && *s != ']')
theme.Cat(*s++);
themei = settings.FindAdd(theme);
}
else {
if(themei >= 0) {
String key;
while(*s && *s != '=') {
key.Cat(*s++);
}
if(*s == '=') s++;
String value;
while(*s) {
value.Cat(*s++);
}
if(!IsEmpty(key))
settings[themei].GetAdd(TrimBoth(key)) = TrimBoth(value);
}
}
}
}
String TextSettings::Get(const char *group, const char *key) const
{
int itemi = settings.Find(group);
return itemi < 0 ? Null : settings.Get(group).Get(key, Null);
}
String TextSettings::Get(int groupIndex, const char *key) const
{
return groupIndex >= 0 && groupIndex < settings.GetCount() ?
settings[groupIndex].Get(key, Null) : Null;
}
String TextSettings::Get(int groupIndex, int keyIndex) const
{
if (groupIndex >= 0 && groupIndex < settings.GetCount())
return keyIndex >= 0 && keyIndex < settings[groupIndex].GetCount() ?
settings[groupIndex][keyIndex] : Null;
else
return Null;
}
// --------------------------------------------------------------
String timeFormat(double s) {
if(s < 0.000001) return Sprintf("%5.2f ns", s * 1.0e9);

View file

@ -35,7 +35,7 @@ struct IniString {
String (*def)();
bool loaded;
String *value;
// "public:"
operator String();
String operator=(const String& s);
String ToString() const;
@ -47,19 +47,31 @@ struct IniInt {
int (*def)();
bool loaded;
int value;
// "public:"
operator int();
int operator=(int b);
String ToString() const;
};
struct IniInt64 {
// "private":
const char *id;
int64 (*def)();
bool loaded;
int64 value;
// "public:"
operator int64();
int64 operator=(int64 b);
String ToString() const;
};
struct IniDouble {
// "private":
const char *id;
double (*def)();
bool loaded;
double value;
// "public:"
operator double();
double operator=(double b);
String ToString() const;
@ -71,7 +83,7 @@ struct IniBool {
bool (*def)();
bool loaded;
bool value;
// "public:"
operator bool();
bool operator=(bool b);
String ToString() const;
@ -89,6 +101,20 @@ struct IniInfo {
const Array<IniInfo> GetIniInfo();
String GetIniInfoFormatted();
#define INI_TYPE(var, def, info, type, decl)\
type DefIni_##var() { return def; }\
decl var = { #var, DefIni_##var };\
String AsStringIniCurrent_##var() { return AsString(var); } \
String AsStringIniDefault_##var() { return AsString(DefIni_##var()); } \
INITBLOCK { AddIniInfo(#var, AsStringIniCurrent_##var, AsStringIniDefault_##var, info); }
#define INI_BOOL(var, def, info) INI_TYPE(var, def, info, bool, IniBool);
#define INI_STRING(var, def, info) INI_TYPE(var, def, info, String, IniString);
#define INI_INT(var, def, info) INI_TYPE(var, def, info, int, IniInt);
#define INI_INT64(var, def, info) INI_TYPE(var, def, info, int64, IniInt64);
#define INI_DOUBLE(var, def, info) INI_TYPE(var, def, info, double, IniDouble);
/*
#define INI_BOOL(var, def, info)\
bool DefIni_##var() { return def; }\
IniBool var = { #var, DefIni_##var };\
@ -110,12 +136,20 @@ String AsStringIniCurrent_##var() { return AsString(var); } \
String AsStringIniDefault_##var() { return AsString(DefIni_##var()); } \
INITBLOCK { AddIniInfo(#var, AsStringIniCurrent_##var, AsStringIniDefault_##var, info); }
#define INI_INT64(var, def, info)\
int64 DefIni_##var() { return def; }\
Ini64Int var = { #var, DefIni_##var };\
String AsStringIniCurrent_##var() { return AsString(var); } \
String AsStringIniDefault_##var() { return AsString(DefIni_##var()); } \
INITBLOCK { AddIniInfo(#var, AsStringIniCurrent_##var, AsStringIniDefault_##var, info); }
#define INI_DOUBLE(var, def, info)\
double DefIni_##var() { return def; }\
IniDouble var = { #var, DefIni_##var };\
String AsStringIniCurrent_##var() { return AsString(var); } \
String AsStringIniDefault_##var() { return AsString(DefIni_##var()); } \
INITBLOCK { AddIniInfo(#var, AsStringIniCurrent_##var, AsStringIniDefault_##var, info); }
*/
VectorMap<String, String> LoadIniStream(Stream &in);
VectorMap<String, String> LoadIniFile(const char *filename);