diff --git a/uppsrc/Core/Core.upp b/uppsrc/Core/Core.upp index eb9889c23..6f04ff573 100644 --- a/uppsrc/Core/Core.upp +++ b/uppsrc/Core/Core.upp @@ -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, diff --git a/uppsrc/Core/Ini.cpp b/uppsrc/Core/Ini.cpp new file mode 100644 index 000000000..a29389683 --- /dev/null +++ b/uppsrc/Core/Ini.cpp @@ -0,0 +1,316 @@ +#include "Core.h" + +namespace Upp { + +VectorMap LoadIniStream(Stream &sin) { + Stream *in = &sin; + FileIn fin; + VectorMap 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 LoadIniFile(const char *filename) { + FileIn in(filename); + if(!in) return VectorMap(); + 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 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 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(*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(*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(*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(*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(*this)); +} + + +Array& sIniInfo() +{ + static Array 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 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; +} + +}; \ No newline at end of file diff --git a/uppsrc/Core/Util.cpp b/uppsrc/Core/Util.cpp index f3868f197..f11884d16 100644 --- a/uppsrc/Core/Util.cpp +++ b/uppsrc/Core/Util.cpp @@ -342,263 +342,6 @@ WString Join(const Vector& im, const WString& delim) { } return r; } -// --------------------------- - -VectorMap LoadIniStream(Stream &sin) { - Stream *in = &sin; - FileIn fin; - VectorMap 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 LoadIniFile(const char *filename) { - FileIn in(filename); - if(!in) return VectorMap(); - 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 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 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(*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(*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(*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(*this)); -} - - -Array& sIniInfo() -{ - static Array 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 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); diff --git a/uppsrc/Core/Util.h b/uppsrc/Core/Util.h index a1eee8c55..5bf594633 100644 --- a/uppsrc/Core/Util.h +++ b/uppsrc/Core/Util.h @@ -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 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 LoadIniStream(Stream &in); VectorMap LoadIniFile(const char *filename);