From fce87802978a1029ac147bf22b16fe263d1b1345 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 9 Mar 2021 21:17:26 +0100 Subject: [PATCH] Add 64-bit integers support to wxConfig Serialize them to strings in wxFileConfig, just as we always did for long, but use wxRegKey support for storing them directly to the registry in wxRegConfig. --- include/wx/confbase.h | 23 +++++++++++++++++++++++ include/wx/fileconf.h | 6 ++++++ include/wx/msw/regconf.h | 2 ++ interface/wx/config.h | 38 ++++++++++++++++++++++++++++++++++++++ src/common/config.cpp | 7 +++++-- src/common/fileconf.cpp | 24 ++++++++++++++++++++++++ src/msw/regconf.cpp | 30 +++++++++++++++++++++++++++++- tests/config/config.cpp | 17 +++++++++++++++++ tests/config/fileconf.cpp | 13 +++++++++++++ tests/config/regconf.cpp | 7 +++++++ 10 files changed, 164 insertions(+), 3 deletions(-) diff --git a/include/wx/confbase.h b/include/wx/confbase.h index 5f5d44e8ac..88e4c641ba 100644 --- a/include/wx/confbase.h +++ b/include/wx/confbase.h @@ -186,6 +186,12 @@ public: bool Read(const wxString& key, bool* val) const; bool Read(const wxString& key, bool* val, bool defVal) const; + // read a 64-bit number when long is 32 bits +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + bool Read(const wxString& key, wxLongLong_t *pl) const; + bool Read(const wxString& key, wxLongLong_t *pl, wxLongLong_t defVal) const; +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + #if wxUSE_BASE64 // read a binary data block bool Read(const wxString& key, wxMemoryBuffer* data) const @@ -235,6 +241,9 @@ public: long ReadLong(const wxString& key, long defVal) const { long l; (void)Read(key, &l, defVal); return l; } + wxLongLong_t ReadLongLong(const wxString& key, wxLongLong_t defVal) const + { wxLongLong_t ll; (void)Read(key, &ll, defVal); return ll; } + double ReadDouble(const wxString& key, double defVal) const { double d; (void)Read(key, &d, defVal); return d; } @@ -304,6 +313,14 @@ public: bool Write(const wxString& key, unsigned long value) { return DoWriteLong(key, value); } +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + bool Write(const wxString& key, wxLongLong_t value) + { return DoWriteLongLong(key, value); } + + bool Write(const wxString& key, wxULongLong_t value) + { return DoWriteLongLong(key, value); } +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + bool Write(const wxString& key, float value) { return DoWriteDouble(key, double(value)); } @@ -374,6 +391,9 @@ protected: // do read/write the values of different types virtual bool DoReadString(const wxString& key, wxString *pStr) const = 0; virtual bool DoReadLong(const wxString& key, long *pl) const = 0; +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + virtual bool DoReadLongLong(const wxString& key, wxLongLong_t *pll) const = 0; +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG virtual bool DoReadDouble(const wxString& key, double* val) const; virtual bool DoReadBool(const wxString& key, bool* val) const; #if wxUSE_BASE64 @@ -382,6 +402,9 @@ protected: virtual bool DoWriteString(const wxString& key, const wxString& value) = 0; virtual bool DoWriteLong(const wxString& key, long value) = 0; +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + virtual bool DoWriteLongLong(const wxString& key, wxLongLong_t value) = 0; +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG virtual bool DoWriteDouble(const wxString& key, double value); virtual bool DoWriteBool(const wxString& key, bool value); #if wxUSE_BASE64 diff --git a/include/wx/fileconf.h b/include/wx/fileconf.h index fd392da194..8286b060ac 100644 --- a/include/wx/fileconf.h +++ b/include/wx/fileconf.h @@ -196,12 +196,18 @@ public: protected: virtual bool DoReadString(const wxString& key, wxString *pStr) const wxOVERRIDE; virtual bool DoReadLong(const wxString& key, long *pl) const wxOVERRIDE; +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + virtual bool DoReadLongLong(const wxString& key, wxLongLong_t *pll) const wxOVERRIDE; +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG #if wxUSE_BASE64 virtual bool DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const wxOVERRIDE; #endif // wxUSE_BASE64 virtual bool DoWriteString(const wxString& key, const wxString& szValue) wxOVERRIDE; virtual bool DoWriteLong(const wxString& key, long lValue) wxOVERRIDE; +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + virtual bool DoWriteLongLong(const wxString& key, wxLongLong_t value) wxOVERRIDE; +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG #if wxUSE_BASE64 virtual bool DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf) wxOVERRIDE; #endif // wxUSE_BASE64 diff --git a/include/wx/msw/regconf.h b/include/wx/msw/regconf.h index 705dafdfa7..6c7c0a98af 100644 --- a/include/wx/msw/regconf.h +++ b/include/wx/msw/regconf.h @@ -97,12 +97,14 @@ protected: // implement read/write methods virtual bool DoReadString(const wxString& key, wxString *pStr) const wxOVERRIDE; virtual bool DoReadLong(const wxString& key, long *plResult) const wxOVERRIDE; + virtual bool DoReadLongLong(const wxString& key, wxLongLong_t *pll) const wxOVERRIDE; #if wxUSE_BASE64 virtual bool DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const wxOVERRIDE; #endif // wxUSE_BASE64 virtual bool DoWriteString(const wxString& key, const wxString& szValue) wxOVERRIDE; virtual bool DoWriteLong(const wxString& key, long lValue) wxOVERRIDE; + virtual bool DoWriteLongLong(const wxString& key, wxLongLong_t llValue) wxOVERRIDE; #if wxUSE_BASE64 virtual bool DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf) wxOVERRIDE; #endif // wxUSE_BASE64 diff --git a/interface/wx/config.h b/interface/wx/config.h index bff8d675eb..6d579480c0 100644 --- a/interface/wx/config.h +++ b/interface/wx/config.h @@ -549,6 +549,29 @@ public: */ bool Read(const wxString& key, long* l, long defaultVal) const; + /** + Reads a 64-bit long long value, returning @true if the value was found. + If the value was not found, @a ll is not changed. + + @since 3.1.5 + + @beginWxPerlOnly + Not supported by wxPerl. + @endWxPerlOnly + */ + bool Read(const wxString& key, wxLongLong_t* ll) const; + /** + Reads a 64-bit long long value, returning @true if the value was found. + If the value was not found, @a defaultVal is used instead. + + @since 3.1.5 + + @beginWxPerlOnly + Not supported by wxPerl. + @endWxPerlOnly + */ + bool Read(const wxString& key, wxLongLong_t* ll, + wxLongLong_t defaultVal) const; /** Reads a double value, returning @true if the value was found. If the value was not found, @a d is not changed. @@ -662,6 +685,14 @@ public: */ long ReadLong(const wxString& key, long defaultVal) const; + /** + Reads a 64-bit long long value from the key and returns it. @a + defaultVal is returned if the key is not found. + + @since 3.1.5 + */ + wxLongLong_t ReadLongLong(const wxString& key, wxLongLong_t defaultVal) const; + /** Reads a value of type T (for which the function wxFromString() must be defined) from the key and returns it. @a defaultVal is returned if the @@ -678,6 +709,13 @@ public: Writes the long value to the config file and returns @true on success. */ bool Write(const wxString& key, long value); + /** + Writes the 64-bit long long value to the config file and returns @true + on success. + + @since 3.1.5 + */ + bool Write(const wxString& key, wxLongLong_t value); /** Writes the double value to the config file and returns @true on success. diff --git a/src/common/config.cpp b/src/common/config.cpp index 6cbded738d..22ff3fa5d1 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -120,7 +120,7 @@ wxConfigBase *wxConfigBase::Create() if ( !DoRead##name(key, val) ) \ return false; \ \ - *val = extra(*val); \ + *val = (extra)(*val); \ \ return true; \ } \ @@ -142,7 +142,7 @@ wxConfigBase *wxConfigBase::Create() *val = defVal; \ } \ \ - *val = extra(*val); \ + *val = (extra)(*val); \ \ return read; \ } @@ -150,6 +150,9 @@ wxConfigBase *wxConfigBase::Create() IMPLEMENT_READ_FOR_TYPE(String, wxString, const wxString&, ExpandEnvVars) IMPLEMENT_READ_FOR_TYPE(Long, long, long, long) +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG +IMPLEMENT_READ_FOR_TYPE(LongLong, wxLongLong_t, wxLongLong_t, wxLongLong_t) +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG IMPLEMENT_READ_FOR_TYPE(Double, double, double, double) IMPLEMENT_READ_FOR_TYPE(Bool, bool, bool, bool) diff --git a/src/common/fileconf.cpp b/src/common/fileconf.cpp index c13327ae67..af5d02b0d3 100644 --- a/src/common/fileconf.cpp +++ b/src/common/fileconf.cpp @@ -881,6 +881,21 @@ bool wxFileConfig::DoReadLong(const wxString& key, long *pl) const return str.ToLong(pl); } +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + +bool wxFileConfig::DoReadLongLong(const wxString& key, wxLongLong_t *pll) const +{ + wxString str; + if ( !Read(key, &str) ) + return false; + + str.Trim(); + + return str.ToLongLong(pll); +} + +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + #if wxUSE_BASE64 bool wxFileConfig::DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const @@ -962,6 +977,15 @@ bool wxFileConfig::DoWriteLong(const wxString& key, long lValue) return Write(key, wxString::Format(wxT("%ld"), lValue)); } +#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + +bool wxFileConfig::DoWriteLongLong(const wxString& key, wxLongLong_t llValue) +{ + return Write(key, wxString::Format("%" wxLongLongFmtSpec "d", llValue)); +} + +#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG + #if wxUSE_BASE64 bool wxFileConfig::DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf) diff --git a/src/msw/regconf.cpp b/src/msw/regconf.cpp index 5ea2409164..872f693a2f 100644 --- a/src/msw/regconf.cpp +++ b/src/msw/regconf.cpp @@ -49,11 +49,29 @@ bool TryGetValue(const wxRegKey& key, const wxString& str, long *plVal) return key.IsOpened() && key.HasValue(str) && key.QueryValue(str, plVal); } +bool TryGetValue(const wxRegKey& key, const wxString& str, wxLongLong_t *pll) +{ + return key.IsOpened() && key.HasValue(str) && key.QueryValue64(str, pll); +} + bool TryGetValue(const wxRegKey& key, const wxString& str, wxMemoryBuffer* pBuf) { return key.IsOpened() && key.HasValue(str) && key.QueryValue(str, *pBuf); } +// set value of the key in a homogeneous way to hide the differences between +// wxRegKey::SetValue() and SetValue64() +template +bool SetKeyValue(wxRegKey& key, const wxString& name, const T& value) +{ + return key.SetValue(name, value); +} + +bool SetKeyValue(wxRegKey& key, const wxString& name, wxLongLong_t value) +{ + return key.SetValue64(name, value); +} + // ============================================================================ // implementation // ============================================================================ @@ -595,6 +613,11 @@ bool wxRegConfig::DoReadLong(const wxString& key, long *plResult) const return DoReadValue(key, plResult); } +bool wxRegConfig::DoReadLongLong(const wxString& key, wxLongLong_t *pll) const +{ + return DoReadValue(key, pll); +} + #if wxUSE_BASE64 bool wxRegConfig::DoReadBinary(const wxString& key, wxMemoryBuffer *buf) const { @@ -612,7 +635,7 @@ bool wxRegConfig::DoWriteValue(const wxString& key, const T& value) return false; } - return LocalKey().SetValue(path.Name(), value); + return SetKeyValue(LocalKey(), path.Name(), value); } bool wxRegConfig::DoWriteString(const wxString& key, const wxString& szValue) @@ -625,6 +648,11 @@ bool wxRegConfig::DoWriteLong(const wxString& key, long lValue) return DoWriteValue(key, lValue); } +bool wxRegConfig::DoWriteLongLong(const wxString& key, wxLongLong_t llValue) +{ + return DoWriteValue(key, llValue); +} + #if wxUSE_BASE64 bool wxRegConfig::DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf) { diff --git a/tests/config/config.cpp b/tests/config/config.cpp index c7f12ba2b0..1b60d1ccdd 100644 --- a/tests/config/config.cpp +++ b/tests/config/config.cpp @@ -45,6 +45,14 @@ TEST_CASE("wxConfig::ReadWriteLocal", "[config]") config->Write(wxString("long1"), 234L); config->Write("double1", 345.67); config->Write("bool1", true); + + // See comment in regconf.cpp. + const wxLongLong_t val64 = wxLL(0x8000000000000008); + config->Write("ll", val64); + + const wxULongLong_t uval64 = wxULL(0x9000000000000009); + config->Write("ull", uval64); + #ifdef wxHAS_CONFIG_TEMPLATE_RW config->Write("color1", wxColour(11,22,33,44)); #endif // wxHAS_CONFIG_TEMPLATE_RW @@ -93,6 +101,15 @@ TEST_CASE("wxConfig::ReadWriteLocal", "[config]") CHECK( config->ReadBool("bool1", false) == bool1 ); + wxLongLong_t ll; + CHECK( config->Read("ll", &ll) ); + CHECK( ll == val64 ); + CHECK( config->ReadLongLong("ll", 0) == val64 ); + + CHECK( config->Read("ull", &ll) ); + CHECK( ll == static_cast(uval64) ); + CHECK( config->ReadLongLong("ull", 0) == static_cast(uval64) ); + #ifdef wxHAS_CONFIG_TEMPLATE_RW wxColour color1; r = config->Read("color1", &color1); diff --git a/tests/config/fileconf.cpp b/tests/config/fileconf.cpp index 0d64f3a114..5b860a911d 100644 --- a/tests/config/fileconf.cpp +++ b/tests/config/fileconf.cpp @@ -626,5 +626,18 @@ TEST_CASE("wxFileConfig::ReadFloat", "[fileconfig][config]") CHECK( f == -9876.5432f ); } +TEST_CASE("wxFileConfig::LongLong", "[fileconfig][config][longlong]") +{ + wxFileConfig fc("", "", "", "", 0); // Don't use any files. + + // See comment near val64 definition in regconf.cpp. + const wxLongLong_t val = wxLL(0x8000000000000008); + REQUIRE( fc.Write("ll", val) ); + + wxLongLong_t ll; + REQUIRE( fc.Read("ll", &ll) ); + CHECK( ll == val ); +} + #endif // wxUSE_FILECONFIG diff --git a/tests/config/regconf.cpp b/tests/config/regconf.cpp index ab012cb544..0db7f4ebd7 100644 --- a/tests/config/regconf.cpp +++ b/tests/config/regconf.cpp @@ -44,6 +44,12 @@ TEST_CASE("wxRegConfig::ReadWrite", "[regconfig][config][registry]") CHECK( config->Write("int32", 1234567) ); + // Note that type of wxLL(0x8000000000000008) literal is somehow unsigned + // long long with MinGW, not sure if it's a bug or not, but work around it + // by specifying the type explicitly. + const wxLongLong_t val64 = wxLL(0x8000000000000008); + CHECK( config->Write("int64", val64) ); + // test reading wxString str; long dummy; @@ -57,6 +63,7 @@ TEST_CASE("wxRegConfig::ReadWrite", "[regconfig][config][registry]") CHECK( config->Read("group2/entry1", "INVALID DEFAULT") == "bar" ); CHECK( config->ReadLong("group2/int32", 0) == 1234567 ); + CHECK( config->ReadLongLong("group2/int64", 0) == val64 ); config->DeleteAll(); }