X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/842215bbb7b87bd3800f95f3d633da0690e18b76..f239a20092359e3c914adb79bd39f3f5d2b2e06f:/src/common/longlong.cpp?ds=inline diff --git a/src/common/longlong.cpp b/src/common/longlong.cpp index f0dad06d38..1ceefe0123 100644 --- a/src/common/longlong.cpp +++ b/src/common/longlong.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: wx/longlong.cpp +// Name: src/common/longlong.cpp // Purpose: implementation of wxLongLongNative // Author: Jeffrey C. Ollie , Vadim Zeitlin // Remarks: this class is not public in wxWidgets 2.0! It is intentionally @@ -15,10 +15,6 @@ // headers // ============================================================================ -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "longlong.h" -#endif - #include "wx/wxprec.h" #ifdef __BORLANDC__ @@ -26,15 +22,20 @@ #endif #if wxUSE_LONGLONG + #include "wx/longlong.h" -#if defined(__MWERKS__) && defined(__WXMSW__) -#include // for memset() -#else -#include // for memset() +#ifndef WX_PRECOMP + #include "wx/math.h" // for fabs() #endif -#include // for fabs() +#if wxUSE_STREAMS + #include "wx/txtstrm.h" +#endif + +#include // for memset() + +#include "wx/ioswrap.h" // ============================================================================ // implementation @@ -50,14 +51,14 @@ void *wxLongLongNative::asArray() const { static unsigned char temp[8]; - temp[0] = (unsigned char)((m_ll >> 56) & 0xFF); - temp[1] = (unsigned char)((m_ll >> 48) & 0xFF); - temp[2] = (unsigned char)((m_ll >> 40) & 0xFF); - temp[3] = (unsigned char)((m_ll >> 32) & 0xFF); - temp[4] = (unsigned char)((m_ll >> 24) & 0xFF); - temp[5] = (unsigned char)((m_ll >> 16) & 0xFF); - temp[6] = (unsigned char)((m_ll >> 8) & 0xFF); - temp[7] = (unsigned char)((m_ll >> 0) & 0xFF); + temp[0] = wx_truncate_cast(unsigned char, ((m_ll >> 56) & 0xFF)); + temp[1] = wx_truncate_cast(unsigned char, ((m_ll >> 48) & 0xFF)); + temp[2] = wx_truncate_cast(unsigned char, ((m_ll >> 40) & 0xFF)); + temp[3] = wx_truncate_cast(unsigned char, ((m_ll >> 32) & 0xFF)); + temp[4] = wx_truncate_cast(unsigned char, ((m_ll >> 24) & 0xFF)); + temp[5] = wx_truncate_cast(unsigned char, ((m_ll >> 16) & 0xFF)); + temp[6] = wx_truncate_cast(unsigned char, ((m_ll >> 8) & 0xFF)); + temp[7] = wx_truncate_cast(unsigned char, ((m_ll >> 0) & 0xFF)); return temp; } @@ -66,14 +67,14 @@ void *wxULongLongNative::asArray() const { static unsigned char temp[8]; - temp[0] = (unsigned char)((m_ll >> 56) & 0xFF); - temp[1] = (unsigned char)((m_ll >> 48) & 0xFF); - temp[2] = (unsigned char)((m_ll >> 40) & 0xFF); - temp[3] = (unsigned char)((m_ll >> 32) & 0xFF); - temp[4] = (unsigned char)((m_ll >> 24) & 0xFF); - temp[5] = (unsigned char)((m_ll >> 16) & 0xFF); - temp[6] = (unsigned char)((m_ll >> 8) & 0xFF); - temp[7] = (unsigned char)((m_ll >> 0) & 0xFF); + temp[0] = wx_truncate_cast(unsigned char, ((m_ll >> 56) & 0xFF)); + temp[1] = wx_truncate_cast(unsigned char, ((m_ll >> 48) & 0xFF)); + temp[2] = wx_truncate_cast(unsigned char, ((m_ll >> 40) & 0xFF)); + temp[3] = wx_truncate_cast(unsigned char, ((m_ll >> 32) & 0xFF)); + temp[4] = wx_truncate_cast(unsigned char, ((m_ll >> 24) & 0xFF)); + temp[5] = wx_truncate_cast(unsigned char, ((m_ll >> 16) & 0xFF)); + temp[6] = wx_truncate_cast(unsigned char, ((m_ll >> 8) & 0xFF)); + temp[7] = wx_truncate_cast(unsigned char, ((m_ll >> 0) & 0xFF)); return temp; } @@ -95,8 +96,59 @@ 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 +#ifdef __VISUALC6__ +double wxULongLongNative::ToDouble() const +{ + // Work around the problem of casting unsigned __int64 to double in VC6 + // (which for unknown reasons only manifests itself in DLL builds, i.e. + // when using /MD). + static const __int64 int64_t_max = 9223372036854775807i64; + if ( m_ll <= int64_t_max ) + return wx_truncate_cast(double, (wxLongLong_t)m_ll); + + double d = wx_truncate_cast(double, int64_t_max); + d += (__int64)(m_ll - int64_t_max - 1); // The cast is safe because of -1 + return d + 1; +} +#endif // __VISUALC6__ + #endif // wxUSE_LONGLONG_NATIVE // ============================================================================ @@ -105,6 +157,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) { @@ -133,6 +193,32 @@ wxLongLongWx& wxLongLongWx::Assign(double d) return *this; } +double wxLongLongWx::ToDouble() const +{ + double d = m_hi; + d *= 1.0 + (double)ULONG_MAX; + d += m_lo; + +#ifdef wxLONGLONG_TEST_MODE + wxASSERT( d == m_ll ); +#endif // wxLONGLONG_TEST_MODE + + return d; +} + +double wxULongLongWx::ToDouble() const +{ + unsigned double d = m_hi; + d *= 1.0 + (double)ULONG_MAX; + d += m_lo; + +#ifdef wxLONGLONG_TEST_MODE + wxASSERT( d == m_ll ); +#endif // wxLONGLONG_TEST_MODE + + return d; +} + wxLongLongWx wxLongLongWx::operator<<(int shift) const { wxLongLongWx ll(*this); @@ -752,7 +838,7 @@ wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll) m_hi = m_lo = 0; #ifdef wxLONGLONG_TEST_MODE - unsigned wxLongLong_t llOld = m_ll; + wxULongLong_t llOld = m_ll; m_ll = 0; #endif // wxLONGLONG_TEST_MODE @@ -778,9 +864,11 @@ wxULongLongWx& wxULongLongWx::operator*=(const wxULongLongWx& ll) // division +#define IS_MSB_SET(ll) ((ll.GetHi()) & (1 << (8*sizeof(long) - 1))) + void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, wxLongLongWx& quotient, - wxLongLongWx& remainder) const + wxLongLongWx& remainderIO) const { if ((divisorIn.m_lo == 0) && (divisorIn.m_hi == 0)) { @@ -804,8 +892,7 @@ void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, // all responsibility for using this code. // init everything - wxLongLongWx dividend = *this, - divisor = divisorIn; + wxULongLongWx dividend, divisor, remainder; quotient = 0l; remainder = 0l; @@ -818,17 +905,21 @@ void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, // dividend = quotient*divisor + remainder // // with 0 <= abs(remainder) < abs(divisor) - bool negRemainder = dividend.m_hi < 0; + bool negRemainder = GetHi() < 0; bool negQuotient = false; // assume positive - if ( dividend.m_hi < 0 ) + if ( GetHi() < 0 ) { negQuotient = !negQuotient; - dividend = -dividend; + dividend = -*this; + } else { + dividend = *this; } - if ( divisor.m_hi < 0 ) + if ( divisorIn.GetHi() < 0 ) { negQuotient = !negQuotient; - divisor = -divisor; + divisor = -divisorIn; + } else { + divisor = divisorIn; } // check for some particular cases @@ -846,8 +937,6 @@ void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, size_t nBits = 64u; wxLongLongWx d; - #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1))) - while ( remainder < divisor ) { remainder <<= 1; @@ -887,10 +976,12 @@ void wxLongLongWx::Divide(const wxLongLongWx& divisorIn, } } + remainderIO = remainder; + // adjust signs if ( negRemainder ) { - remainder = -remainder; + remainderIO = -remainderIO; } if ( negQuotient ) @@ -946,8 +1037,6 @@ void wxULongLongWx::Divide(const wxULongLongWx& divisorIn, size_t nBits = 64u; wxULongLongWx d; - #define IS_MSB_SET(ll) ((ll.m_hi) & (1 << (8*sizeof(long) - 1))) - while ( remainder < divisor ) { remainder <<= 1; @@ -1093,27 +1182,30 @@ void *wxULongLongWx::asArray(void) const \ name ll = *this; \ \ - bool neg; \ - if ( ll < 0 ) \ + bool neg = ll < 0; \ + if ( neg ) \ { \ - ll.Negate(); \ - neg = true; \ + while ( ll != 0 ) \ + { \ + long digit = (ll % 10).ToLong(); \ + result.Prepend((wxChar)(wxT('0') - digit)); \ + ll /= 10; \ + } \ } \ else \ { \ - neg = false; \ - } \ - \ - while ( ll != 0 ) \ - { \ - result.Prepend((wxChar)(_T('0') + (ll % 10).ToLong())); \ - ll /= 10; \ + while ( ll != 0 ) \ + { \ + long digit = (ll % 10).ToLong(); \ + result.Prepend((wxChar)(wxT('0') + digit)); \ + ll /= 10; \ + } \ } \ \ if ( result.empty() ) \ - result = _T('0'); \ + result = wxT('0'); \ else if ( neg ) \ - result.Prepend(_T('-')); \ + result.Prepend(wxT('-')); \ \ return result; \ } @@ -1128,12 +1220,12 @@ void *wxULongLongWx::asArray(void) const \ while ( ll != 0 ) \ { \ - result.Prepend((wxChar)(_T('0') + (ll % 10).ToULong())); \ + result.Prepend((wxChar)(wxT('0') + (ll % 10).ToULong())); \ ll /= 10; \ } \ \ if ( result.empty() ) \ - result = _T('0'); \ + result = wxT('0'); \ \ return result; \ } @@ -1151,11 +1243,13 @@ void *wxULongLongWx::asArray(void) const #if wxUSE_STD_IOSTREAM // input/output +WXDLLIMPEXP_BASE wxSTD ostream& operator<< (wxSTD ostream& o, const wxLongLong& ll) { return o << ll.ToString(); } +WXDLLIMPEXP_BASE wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll) { return o << ll.ToString(); @@ -1163,4 +1257,123 @@ wxSTD ostream& operator<< (wxSTD ostream& o, const wxULongLong& ll) #endif // wxUSE_STD_IOSTREAM +WXDLLIMPEXP_BASE wxString& operator<< (wxString& s, const wxLongLong& ll) +{ + return s << ll.ToString(); +} + +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) ((idx!=len) ? (wxChar)s[idx++] : wxT('\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