From 216a72f3b9ab2bf72f489aceac0093138a6e7707 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 11 Feb 2006 16:51:34 +0000 Subject: [PATCH] added support for 64 bit ints in wx stream classes (patch 1203970) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37497 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + docs/latex/wx/longlong.tex | 25 +++ include/wx/datstrm.h | 48 +++++ include/wx/defs.h | 31 ++- include/wx/longlong.h | 118 ++++++++++- src/common/datstrm.cpp | 332 ++++++++++++++++++++++++++----- src/common/longlong.cpp | 156 +++++++++++++++ tests/longlong/longlongtest.cpp | 3 + tests/streams/datastreamtest.cpp | 148 ++++++++++++++ tests/streams/textstreamtest.cpp | 73 +++++++ 10 files changed, 883 insertions(+), 52 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 53c813b206..c286f988a1 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -40,6 +40,7 @@ All: - Fixed wxODBC buffer overflow problem in Unicode builds. - Fixed wxSocketBase::InterruptWait on wxBase. - Important code cleanup (Paul Cornett) +- Added support for wxLongLong in wx stream classes (Mark Junker) All (GUI): diff --git a/docs/latex/wx/longlong.tex b/docs/latex/wx/longlong.tex index 68ed4dfa6a..e34f3672b2 100644 --- a/docs/latex/wx/longlong.tex +++ b/docs/latex/wx/longlong.tex @@ -76,6 +76,31 @@ wxLongLong. Assignment operator from native long long (only for compilers supporting it). +\membersection{wxLongLong::operator=}\label{wxlonglongoperatorassignull} + +\func{wxLongLong\& operator}{operator=}{\param{wxULongLong\_t }{ll}} + +Assignment operator from native unsigned long long (only for compilers +supporting it). + +\membersection{wxLongLong::operator=}\label{wxlonglongoperatorassignlong} + +\func{wxLongLong\& operator}{operator=}{\param{long }{l}} + +Assignment operator from long. + +\membersection{wxLongLong::operator=}\label{wxlonglongoperatorassignulong} + +\func{wxLongLong\& operator}{operator=}{\param{unsigned long }{l}} + +Assignment operator from unsigned long. + +\membersection{wxLongLong::operator=}\label{wxlonglongoperatorassignulonglong} + +\func{wxLongLong\& operator}{operator=}{\param{const wxULongLong \& }{ll}} + +Assignment operator from unsigned long long. The sign bit will be copied too. + \membersection{wxLongLong::Abs}\label{wxlonglongabs} \constfunc{wxLongLong}{Abs}{\void} diff --git a/include/wx/datstrm.h b/include/wx/datstrm.h index 7551c3c24b..f49620a6ae 100644 --- a/include/wx/datstrm.h +++ b/include/wx/datstrm.h @@ -30,14 +30,30 @@ public: bool IsOk() { return m_input->IsOk(); } +#if wxHAS_INT64 wxUint64 Read64(); +#endif +#if wxUSE_LONGLONG + wxLongLong ReadLL(); +#endif wxUint32 Read32(); wxUint16 Read16(); wxUint8 Read8(); double ReadDouble(); wxString ReadString(); +#if wxHAS_INT64 void Read64(wxUint64 *buffer, size_t size); + void Read64(wxInt64 *buffer, size_t size); +#endif +#if defined(wxLongLong_t) && wxUSE_LONGLONG + void Read64(wxULongLong *buffer, size_t size); + void Read64(wxLongLong *buffer, size_t size); +#endif +#if wxUSE_LONGLONG + void ReadLL(wxULongLong *buffer, size_t size); + void ReadLL(wxLongLong *buffer, size_t size); +#endif void Read32(wxUint32 *buffer, size_t size); void Read16(wxUint16 *buffer, size_t size); void Read8(wxUint8 *buffer, size_t size); @@ -50,7 +66,14 @@ public: wxDataInputStream& operator>>(wxUint8& c); wxDataInputStream& operator>>(wxUint16& i); wxDataInputStream& operator>>(wxUint32& i); +#if wxHAS_INT64 wxDataInputStream& operator>>(wxUint64& i); + wxDataInputStream& operator>>(wxInt64& i); +#endif +#if defined(wxLongLong_t) && wxUSE_LONGLONG + wxDataInputStream& operator>>(wxULongLong& i); + wxDataInputStream& operator>>(wxLongLong& i); +#endif wxDataInputStream& operator>>(double& i); wxDataInputStream& operator>>(float& f); @@ -78,14 +101,32 @@ public: bool IsOk() { return m_output->IsOk(); } +#if wxHAS_INT64 void Write64(wxUint64 i); + void Write64(wxInt64 i); +#endif +#if wxUSE_LONGLONG + void WriteLL(const wxLongLong &ll); + void WriteLL(const wxULongLong &ll); +#endif void Write32(wxUint32 i); void Write16(wxUint16 i); void Write8(wxUint8 i); void WriteDouble(double d); void WriteString(const wxString& string); +#if wxHAS_INT64 void Write64(const wxUint64 *buffer, size_t size); + void Write64(const wxInt64 *buffer, size_t size); +#endif +#if defined(wxLongLong_t) && wxUSE_LONGLONG + void Write64(const wxULongLong *buffer, size_t size); + void Write64(const wxLongLong *buffer, size_t size); +#endif +#if wxUSE_LONGLONG + void WriteLL(const wxULongLong *buffer, size_t size); + void WriteLL(const wxLongLong *buffer, size_t size); +#endif void Write32(const wxUint32 *buffer, size_t size); void Write16(const wxUint16 *buffer, size_t size); void Write8(const wxUint8 *buffer, size_t size); @@ -99,7 +140,14 @@ public: wxDataOutputStream& operator<<(wxUint8 c); wxDataOutputStream& operator<<(wxUint16 i); wxDataOutputStream& operator<<(wxUint32 i); +#if wxHAS_INT64 wxDataOutputStream& operator<<(wxUint64 i); + wxDataOutputStream& operator<<(wxInt64 i); +#endif +#if defined(wxLongLong_t) && wxUSE_LONGLONG + wxDataOutputStream& operator<<(const wxULongLong &i); + wxDataOutputStream& operator<<(const wxLongLong &i); +#endif wxDataOutputStream& operator<<(double f); wxDataOutputStream& operator<<(float f); diff --git a/include/wx/defs.h b/include/wx/defs.h index 0738eb4ec8..a15d8de78c 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -1013,6 +1013,23 @@ inline void *wxUIntToPtr(wxUIntPtr p) typedef wxLongLong_t wxInt64; typedef wxULongLong_t wxUint64; + + #define wxHAS_INT64 1 + +#elif wxUSE_LONGLONG + /* these macros allow to definea 64 bit constants in a portable way */ + #define wxLL(x) wxLongLong(x) + #define wxULL(x) wxULongLong(x) + + #define wxInt64 wxLongLong + #define wxUint64 wxULongLong + + #define wxHAS_INT64 1 + +#else // !wxUSE_LONGLONG + + #define wxHAS_INT64 0 + #endif @@ -1174,7 +1191,7 @@ typedef float wxFloat32; (((wxUint64) (val) & (wxUint64) wxULL(0x0000ff0000000000)) >> 24) | \ (((wxUint64) (val) & (wxUint64) wxULL(0x00ff000000000000)) >> 40) | \ (((wxUint64) (val) & (wxUint64) wxULL(0xff00000000000000)) >> 56))) -#else /* !wxLongLong_t */ +#elif wxUSE_LONGLONG /* !wxLongLong_t */ #define wxUINT64_SWAP_ALWAYS(val) \ ((wxUint64) ( \ ((wxULongLong(val) & wxULongLong(0L, 0x000000ffU)) << 56) | \ @@ -1207,8 +1224,10 @@ typedef float wxFloat32; #define wxINT32_SWAP_ON_BE(val) wxINT32_SWAP_ALWAYS(val) #define wxUINT32_SWAP_ON_LE(val) (val) #define wxINT32_SWAP_ON_LE(val) (val) - #define wxUINT64_SWAP_ON_BE(val) wxUINT64_SWAP_ALWAYS(val) - #define wxUINT64_SWAP_ON_LE(val) (val) + #if wxHAS_INT64 + #define wxUINT64_SWAP_ON_BE(val) wxUINT64_SWAP_ALWAYS(val) + #define wxUINT64_SWAP_ON_LE(val) (val) + #endif #else #define wxUINT16_SWAP_ON_LE(val) wxUINT16_SWAP_ALWAYS(val) #define wxINT16_SWAP_ON_LE(val) wxINT16_SWAP_ALWAYS(val) @@ -1218,8 +1237,10 @@ typedef float wxFloat32; #define wxINT32_SWAP_ON_LE(val) wxINT32_SWAP_ALWAYS(val) #define wxUINT32_SWAP_ON_BE(val) (val) #define wxINT32_SWAP_ON_BE(val) (val) - #define wxUINT64_SWAP_ON_LE(val) wxUINT64_SWAP_ALWAYS(val) - #define wxUINT64_SWAP_ON_BE(val) (val) + #if wxHAS_INT64 + #define wxUINT64_SWAP_ON_LE(val) wxUINT64_SWAP_ALWAYS(val) + #define wxUINT64_SWAP_ON_BE(val) (val) + #endif #endif /* ---------------------------------------------------------------------------- */ diff --git a/include/wx/longlong.h b/include/wx/longlong.h index 0fdf22973a..69b6c4ca47 100644 --- a/include/wx/longlong.h +++ b/include/wx/longlong.h @@ -14,6 +14,9 @@ #define _WX_LONGLONG_H #include "wx/defs.h" + +#if wxUSE_LONGLONG + #include "wx/string.h" #include // for LONG_MAX @@ -39,7 +42,12 @@ // unknown pragma should never be an error -- except that, actually, some // broken compilers don't like it, so we have to disable it in this case // - #if !(defined(__WATCOMC__) || defined(__VISAGECPP__)) + #ifdef __GNUC__ + #warning "Your compiler does not appear to support 64 bit "\ + "integers, using emulation class instead.\n" \ + "Please report your compiler version to " \ + "wx-dev@lists.wxwidgets.org!" + #elif !(defined(__WATCOMC__) || defined(__VISAGECPP__)) #pragma warning "Your compiler does not appear to support 64 bit "\ "integers, using emulation class instead.\n" \ "Please report your compiler version to " \ @@ -123,8 +131,16 @@ public: // from native 64 bit integer wxLongLongNative& operator=(wxLongLong_t ll) { m_ll = ll; return *this; } + wxLongLongNative& operator=(wxULongLong_t ll) + { m_ll = ll; return *this; } + wxLongLongNative& operator=(const wxULongLongNative &ll); + wxLongLongNative& operator=(long l) + { m_ll = l; return *this; } + wxLongLongNative& operator=(unsigned long l) + { m_ll = l; return *this; } #if wxUSE_LONGLONG_WX wxLongLongNative& operator=(wxLongLongWx ll); + wxLongLongNative& operator=(const class wxULongLongWx &ll); #endif @@ -307,6 +323,13 @@ public: friend WXDLLIMPEXP_BASE wxString& operator<<(wxString&, const wxLongLongNative&); +#if wxUSE_STREAMS + friend WXDLLIMPEXP_BASE + class wxTextOutputStream& operator<<(class wxTextOutputStream&, const wxLongLongNative&); + friend WXDLLIMPEXP_BASE + class wxTextInputStream& operator>>(class wxTextInputStream&, wxLongLongNative&); +#endif + private: wxLongLong_t m_ll; }; @@ -328,6 +351,10 @@ public: m_ll |= (wxULongLong_t) lo; } +#if wxUSE_LONGLONG_WX + wxULongLongNative(const class wxULongLongWx &ll); +#endif + // default copy ctor is ok // no dtor @@ -336,6 +363,18 @@ public: // from native 64 bit integer wxULongLongNative& operator=(wxULongLong_t ll) { m_ll = ll; return *this; } + wxULongLongNative& operator=(wxLongLong_t ll) + { m_ll = ll; return *this; } + wxULongLongNative& operator=(long l) + { m_ll = l; return *this; } + wxULongLongNative& operator=(unsigned long l) + { m_ll = l; return *this; } + wxULongLongNative& operator=(const wxLongLongNative &ll) + { m_ll = ll.GetValue(); return *this; } +#if wxUSE_LONGLONG_WX + wxULongLongNative& operator=(wxLongLongWx ll); + wxULongLongNative& operator=(const class wxULongLongWx &ll); +#endif // assignment operators from wxULongLongNative is ok @@ -494,10 +533,24 @@ public: friend WXDLLIMPEXP_BASE wxString& operator<<(wxString&, const wxULongLongNative&); +#if wxUSE_STREAMS + friend WXDLLIMPEXP_BASE + class wxTextOutputStream& operator<<(class wxTextOutputStream&, const wxULongLongNative&); + friend WXDLLIMPEXP_BASE + class wxTextInputStream& operator>>(class wxTextInputStream&, wxULongLongNative&); +#endif + private: wxULongLong_t m_ll; }; +inline +wxLongLongNative& wxLongLongNative::operator=(const wxULongLongNative &ll) +{ + m_ll = ll.GetValue(); + return *this; +} + #endif // wxUSE_LONGLONG_NATIVE #if wxUSE_LONGLONG_WX @@ -553,7 +606,22 @@ public: return *this; } - // from double + wxLongLongWx& operator=(unsigned long l) + { + m_lo = l; + m_hi = 0; + +#ifdef wxLONGLONG_TEST_MODE + m_ll = l; + + Check(); +#endif // wxLONGLONG_TEST_MODE + + return *this; + } + wxLongLongWx& operator=(const class wxULongLongWx &ll); + + // from double wxLongLongWx& Assign(double d); // can't have assignment operator from 2 longs @@ -693,6 +761,13 @@ public: friend WXDLLIMPEXP_BASE wxString& operator<<(wxString&, const wxLongLongWx&); +#if wxUSE_STREAMS + friend WXDLLIMPEXP_BASE + class wxTextOutputStream& operator<<(class wxTextOutputStream&, const wxLongLongWx&); + friend WXDLLIMPEXP_BASE + class wxTextInputStream& operator>>(class wxTextInputStream&, wxLongLongWx&); +#endif + private: // long is at least 32 bits, so represent our 64bit number as 2 longs @@ -769,6 +844,26 @@ public: return *this; } + wxULongLongWx& operator=(long l) + { + m_lo = l; + m_hi = (unsigned long) ((l<0) ? -1l : 0); + +#ifdef wxLONGLONG_TEST_MODE + m_ll = (wxULongLong_t) (wxLongLong_t) l; + + Check(); +#endif // wxLONGLONG_TEST_MODE + + return *this; + } + wxULongLongWx& operator=(const class wxLongLongWx &ll) { + // Should we use an assert like it was before in the constructor? + // wxASSERT(ll.GetHi() >= 0); + m_hi = (unsigned long)ll.GetHi(); + m_lo = ll.GetLo(); + return *this; + } // can't have assignment operator from 2 longs @@ -879,6 +974,13 @@ public: friend WXDLLIMPEXP_BASE wxString& operator<<(wxString&, const wxULongLongWx&); +#if wxUSE_STREAMS + friend WXDLLIMPEXP_BASE + class wxTextOutputStream& operator<<(class wxTextOutputStream&, const wxULongLongWx&); + friend WXDLLIMPEXP_BASE + class wxTextInputStream& operator>>(class wxTextInputStream&, wxULongLongWx&); +#endif + private: // long is at least 32 bits, so represent our 64bit number as 2 longs @@ -929,4 +1031,16 @@ inline wxLongLong operator-(unsigned long l, const wxULongLong& ull) return wxLongLong((long)ret.GetHi(),ret.GetLo()); } +#if wxUSE_LONGLONG_NATIVE && wxUSE_STREAMS + +WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &stream, wxULongLong_t value); +WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &stream, wxLongLong_t value); + +WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &stream, wxULongLong_t &value); +WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &stream, wxLongLong_t &value); + +#endif + +#endif // wxUSE_LONGLONG + #endif // _WX_LONGLONG_H diff --git a/src/common/datstrm.cpp b/src/common/datstrm.cpp index 0a02f17e8f..656b628b35 100644 --- a/src/common/datstrm.cpp +++ b/src/common/datstrm.cpp @@ -35,17 +35,14 @@ wxDataInputStream::wxDataInputStream(wxInputStream& s) { } +#if wxHAS_INT64 wxUint64 wxDataInputStream::Read64() { - wxUint64 i64; - - m_input->Read(&i64, 8); - - if (m_be_order) - return wxUINT64_SWAP_ON_LE(i64); - else - return wxUINT64_SWAP_ON_BE(i64); + wxUint64 tmp; + Read64(&tmp, 1); + return tmp; } +#endif // wxHAS_INT64 wxUint32 wxDataInputStream::Read32() { @@ -114,28 +111,196 @@ wxString wxDataInputStream::ReadString() return wxEmptyString; } -void wxDataInputStream::Read64(wxUint64 *buffer, size_t size) -{ - m_input->Read(buffer, size * 8); +#if wxUSE_LONGLONG - if (m_be_order) - { - for (wxUint32 i=0; i +static +void DoReadLL(T *buffer, size_t size, wxInputStream *input, bool be_order) +{ + typedef T DataType; + unsigned char *pchBuffer = new unsigned char[size * 8]; + // TODO: Check for overflow when size is of type uint and is > than 512m + input->Read(pchBuffer, size * 8); + size_t idx_base = 0; + if ( be_order ) { - wxUint64 v = wxUINT64_SWAP_ON_LE(*buffer); - *(buffer++) = v; + for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex ) + { + buffer[uiIndex] = 0l; + for ( unsigned ui = 0; ui != 8; ++ui ) + { + buffer[uiIndex] = buffer[uiIndex] * 256l + + DataType((unsigned long) pchBuffer[idx_base + ui]); + } + + idx_base += 8; + } + } + else // little endian + { + for ( size_t uiIndex=0; uiIndex!=size; ++uiIndex ) + { + buffer[uiIndex] = 0l; + for ( unsigned ui=0; ui!=8; ++ui ) + buffer[uiIndex] = buffer[uiIndex] * 256l + + DataType((unsigned long) pchBuffer[idx_base + 7 - ui]); + idx_base += 8; + } + } + delete[] pchBuffer; +} + +template +static void DoWriteLL(const T *buffer, size_t size, wxOutputStream *output, bool be_order) +{ + typedef T DataType; + unsigned char *pchBuffer = new unsigned char[size * 8]; + size_t idx_base = 0; + if ( be_order ) + { + for ( size_t uiIndex = 0; uiIndex != size; ++uiIndex ) + { + DataType i64 = buffer[uiIndex]; + for ( unsigned ui = 0; ui != 8; ++ui ) + { + pchBuffer[idx_base + 7 - ui] = + (unsigned char) (i64.GetLo() & 255l); + i64 >>= 8l; + } + + idx_base += 8; + } + } + else // little endian + { + for ( size_t uiIndex=0; uiIndex != size; ++uiIndex ) + { + DataType i64 = buffer[uiIndex]; + for (unsigned ui=0; ui!=8; ++ui) + { + pchBuffer[idx_base + ui] = + (unsigned char) (i64.GetLo() & 255l); + i64 >>= 8l; + } + + idx_base += 8; + } + } + + // TODO: Check for overflow when size is of type uint and is > than 512m + output->Write(pchBuffer, size * 8); + delete[] pchBuffer; +} + +#endif // wxUSE_LONGLONG + +#ifdef wxLongLong_t + +template +static +void DoReadI64(T *buffer, size_t size, wxInputStream *input, bool be_order) +{ + typedef T DataType; + unsigned char *pchBuffer = (unsigned char*) buffer; + // TODO: Check for overflow when size is of type uint and is > than 512m + input->Read(pchBuffer, size * 8); + if ( be_order ) + { + for ( wxUint32 i = 0; i < size; i++ ) + { + DataType v = wxUINT64_SWAP_ON_LE(*buffer); + *(buffer++) = v; + } + } + else // little endian + { + for ( wxUint32 i=0; i +static +void DoWriteI64(const T *buffer, size_t size, wxOutputStream *output, bool be_order) +{ + typedef T DataType; + if ( be_order ) + { + for ( size_t i = 0; i < size; i++ ) + { + DataType i64 = wxUINT64_SWAP_ON_LE(*buffer); + buffer++; + output->Write(&i64, 8); } } - else + else // little endian { - for (wxUint32 i=0; iWrite(&i64, 8); } } } +#endif // wxLongLong_t + + +#if wxHAS_INT64 +void wxDataInputStream::Read64(wxUint64 *buffer, size_t size) +{ +#ifndef wxLongLong_t + DoReadLL(buffer, size, m_input, m_be_order); +#else + DoReadI64(buffer, size, m_input, m_be_order); +#endif +} + +void wxDataInputStream::Read64(wxInt64 *buffer, size_t size) +{ +#ifndef wxLongLong_t + DoReadLL(buffer, size, m_input, m_be_order); +#else + DoReadI64(buffer, size, m_input, m_be_order); +#endif +} +#endif // wxHAS_INT64 + +#if defined(wxLongLong_t) && wxUSE_LONGLONG +void wxDataInputStream::Read64(wxULongLong *buffer, size_t size) +{ + DoReadLL(buffer, size, m_input, m_be_order); +} + +void wxDataInputStream::Read64(wxLongLong *buffer, size_t size) +{ + DoReadLL(buffer, size, m_input, m_be_order); +} +#endif // wxLongLong_t + +#if wxUSE_LONGLONG +void wxDataInputStream::ReadLL(wxULongLong *buffer, size_t size) +{ + DoReadLL(buffer, size, m_input, m_be_order); +} + +void wxDataInputStream::ReadLL(wxLongLong *buffer, size_t size) +{ + DoReadLL(buffer, size, m_input, m_be_order); +} + +wxLongLong wxDataInputStream::ReadLL(void) +{ + wxLongLong ll; + DoReadLL(&ll, 1, m_input, m_be_order); + return ll; +} +#endif // wxUSE_LONGLONG + void wxDataInputStream::Read32(wxUint32 *buffer, size_t size) { m_input->Read(buffer, size * 4); @@ -235,12 +400,34 @@ wxDataInputStream& wxDataInputStream::operator>>(wxUint32& i) return *this; } +#if wxHAS_INT64 wxDataInputStream& wxDataInputStream::operator>>(wxUint64& i) { i = Read64(); return *this; } +wxDataInputStream& wxDataInputStream::operator>>(wxInt64& i) +{ + i = Read64(); + return *this; +} +#endif // wxHAS_INT64 + +#if defined(wxLongLong_t) && wxUSE_LONGLONG +wxDataInputStream& wxDataInputStream::operator>>(wxULongLong& i) +{ + i = ReadLL(); + return *this; +} + +wxDataInputStream& wxDataInputStream::operator>>(wxLongLong& i) +{ + i = ReadLL(); + return *this; +} +#endif // wxLongLong_t + wxDataInputStream& wxDataInputStream::operator>>(double& i) { i = ReadDouble(); @@ -267,17 +454,18 @@ wxDataOutputStream::wxDataOutputStream(wxOutputStream& s) { } +#if wxHAS_INT64 void wxDataOutputStream::Write64(wxUint64 i) { - wxUint64 i64; - - if (m_be_order) - i64 = wxUINT64_SWAP_ON_LE(i); - else - i64 = wxUINT64_SWAP_ON_BE(i); - m_output->Write(&i64, 8); + Write64(&i, 1); } +void wxDataOutputStream::Write64(wxInt64 i) +{ + Write64(&i, 1); +} +#endif // wxHAS_INT64 + void wxDataOutputStream::Write32(wxUint32 i) { wxUint32 i32; @@ -334,28 +522,60 @@ void wxDataOutputStream::WriteDouble(double d) m_output->Write(buf, 10); } +#if wxHAS_INT64 void wxDataOutputStream::Write64(const wxUint64 *buffer, size_t size) { - if (m_be_order) - { - for (wxUint32 i=0; iWrite(&i64, 8); - } - } - else - { - for (wxUint32 i=0; iWrite(&i64, 8); - } - } +#ifndef wxLongLong_t + DoWriteLL(buffer, size, m_output, m_be_order); +#else + DoWriteI64(buffer, size, m_output, m_be_order); +#endif } +void wxDataOutputStream::Write64(const wxInt64 *buffer, size_t size) +{ +#ifndef wxLongLong_t + DoWriteLL(buffer, size, m_output, m_be_order); +#else + DoWriteI64(buffer, size, m_output, m_be_order); +#endif +} +#endif // wxHAS_INT64 + +#if defined(wxLongLong_t) && wxUSE_LONGLONG +void wxDataOutputStream::Write64(const wxULongLong *buffer, size_t size) +{ + DoWriteLL(buffer, size, m_output, m_be_order); +} + +void wxDataOutputStream::Write64(const wxLongLong *buffer, size_t size) +{ + DoWriteLL(buffer, size, m_output, m_be_order); +} +#endif // wxLongLong_t + +#if wxUSE_LONGLONG +void wxDataOutputStream::WriteLL(const wxULongLong *buffer, size_t size) +{ + DoWriteLL(buffer, size, m_output, m_be_order); +} + +void wxDataOutputStream::WriteLL(const wxLongLong *buffer, size_t size) +{ + DoWriteLL(buffer, size, m_output, m_be_order); +} + +void wxDataOutputStream::WriteLL(const wxLongLong &ll) +{ + WriteLL(&ll, 1); +} + +void wxDataOutputStream::WriteLL(const wxULongLong &ll) +{ + WriteLL(&ll, 1); +} +#endif // wxUSE_LONGLONG + void wxDataOutputStream::Write32(const wxUint32 *buffer, size_t size) { if (m_be_order) @@ -462,12 +682,34 @@ wxDataOutputStream& wxDataOutputStream::operator<<(wxUint32 i) return *this; } +#if wxHAS_INT64 wxDataOutputStream& wxDataOutputStream::operator<<(wxUint64 i) { Write64(i); return *this; } +wxDataOutputStream& wxDataOutputStream::operator<<(wxInt64 i) +{ + Write64(i); + return *this; +} +#endif // wxHAS_INT64 + +#if defined(wxLongLong_t) && wxUSE_LONGLONG +wxDataOutputStream& wxDataOutputStream::operator<<(const wxULongLong &i) +{ + WriteLL(i); + return *this; +} + +wxDataOutputStream& wxDataOutputStream::operator<<(const wxLongLong &i) +{ + WriteLL(i); + return *this; +} +#endif // wxLongLong_t + wxDataOutputStream& wxDataOutputStream::operator<<(double f) { WriteDouble(f); diff --git a/src/common/longlong.cpp b/src/common/longlong.cpp index b61b13d159..b8364d8579 100644 --- a/src/common/longlong.cpp +++ b/src/common/longlong.cpp @@ -25,6 +25,10 @@ #include "wx/longlong.h" #include "wx/math.h" // for fabs() +#if wxUSE_STREAMS +#include "wx/txtstrm.h" +#endif + #if defined(__MWERKS__) && defined(__WXMSW__) #include // for memset() #else @@ -92,6 +96,41 @@ wxLongLongNative& wxLongLongNative::operator=(wxLongLongWx ll) m_ll |= ll.GetLo(); return *this; } + +wxLongLongNative& wxLongLongNative::operator=(const class wxULongLongWx &ll) +{ + // assign first to avoid precision loss! + m_ll = ll.GetHi(); + m_ll <<= 32; + m_ll |= ll.GetLo(); + return *this; +} + +wxULongLongNative::wxULongLongNative(const class wxULongLongWx &ll) +{ + // assign first to avoid precision loss! + m_ll = ll.GetHi(); + m_ll <<= 32; + m_ll |= ((unsigned long) ll.GetLo()); +} + +wxULongLongNative& wxULongLongNative::operator=(wxLongLongWx ll) +{ + // assign first to avoid precision loss! + m_ll = ll.GetHi(); + m_ll <<= 32; + m_ll |= ((unsigned long) ll.GetLo()); + return *this; +} + +wxULongLongNative& wxULongLongNative::operator=(const class wxULongLongWx &ll) +{ + // assign first to avoid precision loss! + m_ll = ll.GetHi(); + m_ll <<= 32; + m_ll |= ((unsigned long) ll.GetLo()); + return *this; +} #endif #endif // wxUSE_LONGLONG_NATIVE @@ -102,6 +141,14 @@ wxLongLongNative& wxLongLongNative::operator=(wxLongLongWx ll) #if wxUSE_LONGLONG_WX +// Set value from unsigned wxULongLongWx +wxLongLongWx &wxLongLongWx::operator=(const class wxULongLongWx &ll) +{ + m_hi = (unsigned long) ll.GetHi(); + m_lo = ll.GetLo(); + return *this; +} + // assignment wxLongLongWx& wxLongLongWx::Assign(double d) { @@ -1191,4 +1238,113 @@ WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxULongLong& ll) return s << ll.ToString(); } +#if wxUSE_STREAMS + +WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxULongLong& ll) +{ + return o << ll.ToString(); +} + +WXDLLIMPEXP_BASE wxTextOutputStream& operator<< (wxTextOutputStream& o, const wxLongLong& ll) +{ + return o << ll.ToString(); +} + +#define READ_STRING_CHAR(s, idx, len) ((wxChar) ((idx!=len) ? s[idx++] : 0)) + +WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong &ll) +{ + wxString s = o.ReadWord(); + + ll = wxULongLong(0l, 0l); + size_t length = s.Length(); + size_t idx = 0; + + wxChar ch = READ_STRING_CHAR(s, idx, length); + + // Skip WS + while (ch==wxT(' ') || ch==wxT('\t')) + ch = READ_STRING_CHAR(s, idx, length); + + // Read number + wxULongLong multiplier(0l, 10l); + while (ch>=wxT('0') && ch<=wxT('9')) { + long lValue = (unsigned) (ch - wxT('0')); + ll = ll * multiplier + wxULongLong(0l, lValue); + ch = READ_STRING_CHAR(s, idx, length); + } + + return o; +} + +WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong &ll) +{ + wxString s = o.ReadWord(); + + ll = wxLongLong(0l, 0l); + size_t length = s.Length(); + size_t idx = 0; + + wxChar ch = READ_STRING_CHAR(s, idx, length); + + // Skip WS + while (ch==wxT(' ') || ch==wxT('\t')) + ch = READ_STRING_CHAR(s, idx, length); + + // Ask for sign + int iSign = 1; + if (ch==wxT('-') || ch==wxT('+')) { + iSign = ((ch==wxT('-')) ? -1 : 1); + ch = READ_STRING_CHAR(s, idx, length); + } + + // Read number + wxLongLong multiplier(0l, 10l); + while (ch>=wxT('0') && ch<=wxT('9')) { + long lValue = (unsigned) (ch - wxT('0')); + ll = ll * multiplier + wxLongLong(0l, lValue); + ch = READ_STRING_CHAR(s, idx, length); + } + +#if wxUSE_LONGLONG_NATIVE + ll = ll * wxLongLong((wxLongLong_t) iSign); +#else + ll = ll * wxLongLong((long) iSign); +#endif + + return o; +} + +#if wxUSE_LONGLONG_NATIVE + +WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxULongLong_t value) +{ + return o << wxULongLong(value).ToString(); +} + +WXDLLIMPEXP_BASE class wxTextOutputStream &operator<<(class wxTextOutputStream &o, wxLongLong_t value) +{ + return o << wxLongLong(value).ToString(); +} + +WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxULongLong_t &value) +{ + wxULongLong ll; + o >> ll; + value = ll.GetValue(); + return o; +} + +WXDLLIMPEXP_BASE class wxTextInputStream &operator>>(class wxTextInputStream &o, wxLongLong_t &value) +{ + wxLongLong ll; + o >> ll; + value = ll.GetValue(); + return o; +} + +#endif // wxUSE_LONGLONG_NATIVE + +#endif // wxUSE_STREAMS + #endif // wxUSE_LONGLONG diff --git a/tests/longlong/longlongtest.cpp b/tests/longlong/longlongtest.cpp index 3d4815db09..fdeb5fdd71 100644 --- a/tests/longlong/longlongtest.cpp +++ b/tests/longlong/longlongtest.cpp @@ -24,6 +24,8 @@ #include "wx/longlong.h" #include "wx/timer.h" +#if wxUSE_LONGLONG + // ---------------------------------------------------------------------------- // helpers for testing // ---------------------------------------------------------------------------- @@ -322,3 +324,4 @@ void LongLongTestCase::ToString() } +#endif // wxUSE_LONGLONG diff --git a/tests/streams/datastreamtest.cpp b/tests/streams/datastreamtest.cpp index 3777869352..efe700336c 100644 --- a/tests/streams/datastreamtest.cpp +++ b/tests/streams/datastreamtest.cpp @@ -21,6 +21,8 @@ #include "wx/wx.h" #endif // WX_PRECOMP +#include + #include "wx/datstrm.h" #include "wx/wfstream.h" #include "wx/math.h" @@ -38,11 +40,23 @@ private: CPPUNIT_TEST_SUITE( DataStreamTestCase ); CPPUNIT_TEST( FloatRW ); CPPUNIT_TEST( DoubleRW ); +#if wxUSE_LONGLONG + CPPUNIT_TEST( LongLongRW ); +#endif +#if wxHAS_INT64 + CPPUNIT_TEST( Int64RW ); +#endif CPPUNIT_TEST( NaNRW ); CPPUNIT_TEST_SUITE_END(); void FloatRW(); void DoubleRW(); +#if wxUSE_LONGLONG + void LongLongRW(); +#endif +#if wxHAS_INT64 + void Int64RW(); +#endif void NaNRW(); DECLARE_NO_COPY_CLASS(DataStreamTestCase) @@ -58,6 +72,7 @@ DataStreamTestCase::DataStreamTestCase() { } +static wxFloat64 TestFloatRW(wxFloat64 fValue) { wxFileOutputStream* pFileOutput = new wxFileOutputStream( _T("mytext.dat") ); @@ -81,6 +96,91 @@ wxFloat64 TestFloatRW(wxFloat64 fValue) return fInFloat; } +template +class TestMultiRW { +public: + typedef std::vector ValueArray; + typedef void (wxDataOutputStream::*FnWriter)(const T *buffer, size_t size); + typedef void (wxDataInputStream::*FnReader)(T *buffer, size_t size); + +private: + bool m_ok; + +private: + void ProcessData(const T *Values, + typename ValueArray::size_type Size, + FnWriter pfnWriter, + FnReader pfnReader) + { + ValueArray InValues(Size); + + { + wxFileOutputStream FileOutput( _T("mytext.dat") ); + wxDataOutputStream DataOutput( FileOutput ); + + (DataOutput.*pfnWriter)(Values, Size); + } + + { + wxFileInputStream FileInput( _T("mytext.dat") ); + wxDataInputStream DataInput( FileInput ); + + (DataInput.*pfnReader)(&*InValues.begin(), InValues.size()); + } + + m_ok = true; + for (typename ValueArray::size_type idx=0; idx!=Size; ++idx) { + if (InValues[idx]!=Values[idx]) { + m_ok = false; + break; + } + } + } + + +public: + TestMultiRW(const T *Values, + size_t Size, + FnWriter pfnWriter, + FnReader pfnReader) + { + ProcessData(Values, (typename ValueArray::size_type) Size, pfnWriter, pfnReader); + } + TestMultiRW(const ValueArray &Values, + FnWriter pfnWriter, + FnReader pfnReader) + { + ProcessData(&*Values.begin(), Values.size(), pfnWriter, pfnReader); + } + + bool Ok(void) const { + return m_ok; + } +}; + +template +static +T TestRW(const T &Value) +{ + T InValue; + + { + wxFileOutputStream FileOutput( _T("mytext.dat") ); + wxDataOutputStream DataOutput( FileOutput ); + + DataOutput << Value; + } + + { + wxFileInputStream FileInput( _T("mytext.dat") ); + wxDataInputStream DataInput( FileInput ); + + DataInput >> InValue; + } + + return InValue; +} + void DataStreamTestCase::FloatRW() { CPPUNIT_ASSERT( TestFloatRW(5.5) == 5.5 ); @@ -95,6 +195,54 @@ void DataStreamTestCase::DoubleRW() CPPUNIT_ASSERT( TestFloatRW(21321343431.1232143432) == 21321343431.1232143432 ); } +#if wxUSE_LONGLONG +void DataStreamTestCase::LongLongRW() +{ + TestMultiRW::ValueArray ValuesLL; + TestMultiRW::ValueArray ValuesULL; + + ValuesLL.push_back(wxLongLong(0l)); + ValuesLL.push_back(wxLongLong(1l)); + ValuesLL.push_back(wxLongLong(-1l)); + ValuesLL.push_back(wxLongLong(0x12345678l)); + ValuesLL.push_back(wxLongLong(0x12345678l, 0xabcdef01l)); + + ValuesULL.push_back(wxULongLong(0l)); + ValuesULL.push_back(wxULongLong(1l)); + ValuesULL.push_back(wxULongLong(0x12345678l)); + ValuesULL.push_back(wxULongLong(0x12345678l, 0xabcdef01l)); + + CPPUNIT_ASSERT( TestRW(wxLongLong(0x12345678l)) == wxLongLong(0x12345678l) ); + CPPUNIT_ASSERT( TestRW(wxLongLong(0x12345678l, 0xabcdef01l)) == wxLongLong(0x12345678l, 0xabcdef01l) ); + CPPUNIT_ASSERT( TestMultiRW(ValuesLL, &wxDataOutputStream::WriteLL, &wxDataInputStream::ReadLL).Ok() ); + CPPUNIT_ASSERT( TestMultiRW(ValuesULL, &wxDataOutputStream::WriteLL, &wxDataInputStream::ReadLL).Ok() ); +} +#endif + +#if wxHAS_INT64 +void DataStreamTestCase::Int64RW() +{ + TestMultiRW::ValueArray ValuesI64; + TestMultiRW::ValueArray ValuesUI64; + + ValuesI64.push_back(wxInt64(0l)); + ValuesI64.push_back(wxInt64(1l)); + ValuesI64.push_back(wxInt64(-1l)); + ValuesI64.push_back(wxInt64(0x12345678l)); + ValuesI64.push_back((wxInt64(0x12345678l) << 32) + wxInt64(0xabcdef01l)); + + ValuesUI64.push_back(wxUint64(0l)); + ValuesUI64.push_back(wxUint64(1l)); + ValuesUI64.push_back(wxUint64(0x12345678l)); + ValuesUI64.push_back((wxUint64(0x12345678l) << 32) + wxUint64(0xabcdef01l)); + + CPPUNIT_ASSERT( TestRW(wxUint64(0x12345678l)) == wxUint64(0x12345678l) ); + CPPUNIT_ASSERT( TestRW((wxUint64(0x12345678l) << 32) + wxUint64(0xabcdef01l)) == (wxUint64(0x12345678l) << 32) + wxUint64(0xabcdef01l) ); + CPPUNIT_ASSERT( TestMultiRW(ValuesI64, &wxDataOutputStream::Write64, &wxDataInputStream::Read64).Ok() ); + CPPUNIT_ASSERT( TestMultiRW(ValuesUI64, &wxDataOutputStream::Write64, &wxDataInputStream::Read64).Ok() ); +} +#endif + void DataStreamTestCase::NaNRW() { //TODO? diff --git a/tests/streams/textstreamtest.cpp b/tests/streams/textstreamtest.cpp index 6139092965..239b37aaa4 100644 --- a/tests/streams/textstreamtest.cpp +++ b/tests/streams/textstreamtest.cpp @@ -24,6 +24,10 @@ #include "wx/txtstrm.h" #include "wx/wfstream.h" +#if wxUSE_LONGLONG +#include "wx/longlong.h" +#endif + // ---------------------------------------------------------------------------- // test class // ---------------------------------------------------------------------------- @@ -36,9 +40,17 @@ public: private: CPPUNIT_TEST_SUITE( TextStreamTestCase ); CPPUNIT_TEST( Endline ); +#if wxUSE_LONGLONG + CPPUNIT_TEST( TestLongLong ); + CPPUNIT_TEST( TestLongLong ); +#endif CPPUNIT_TEST_SUITE_END(); void Endline(); +#if wxUSE_LONGLONG + void TestLongLong(); + void TestULongLong(); +#endif // wxUSE_LONGLONG DECLARE_NO_COPY_CLASS(TextStreamTestCase) @@ -85,3 +97,64 @@ void TextStreamTestCase::Endline() delete pInFile; } + +#if wxUSE_LONGLONG + +template +static void DoTestRoundTrip(const T *values, size_t numValues) +{ + { + wxFileOutputStream fileOut(_T("test.txt")); + wxTextOutputStream textOut(fileOut); + + for ( size_t n = 0; n < numValues; n++ ) + { + textOut << values[n] << endl; + } + } + + { + wxFileInputStream fileIn(_T("test.txt")); + wxTextInputStream textIn(fileIn); + + T value; + for ( size_t n = 0; n < numValues; n++ ) + { + textIn >> value; + + CPPUNIT_ASSERT( value == values[n] ); + } + } +} + +void TextStreamTestCase::TestLongLong() +{ + static const wxLongLong llvalues[] = + { + 0, + 1, + -1, + 0x12345678l, + -0x12345678l, + wxLL(0x123456789abcdef0), + wxLL(-0x123456789abcdef0), + }; + + DoTestRoundTrip(llvalues, WXSIZEOF(llvalues)); +} + +void TextStreamTestCase::TestULongLong() +{ + static const wxULongLong ullvalues[] = + { + 0, + 1, + 0x12345678l, + wxULL(0x123456789abcdef0), + }; + + DoTestRoundTrip(ullvalues, WXSIZEOF(ullvalues)); +} + +#endif // wxUSE_LONGLONG +