//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: filesize.cpp // //-------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "filesize.h" #include "util.h" #include //----------------------------------------------------------------------------- // class FileSize //----------------------------------------------------------------------------- // // Static array of file size "order" string IDs. // These IDs identify the "%1 KB", "%1 MB", "%1 GB" resource strings. // int FileSize::m_rgiOrders[IDS_ORDER_EB - IDS_ORDER_BYTES + 1]; FileSize::FileSize( ULONGLONG ullSize ) : m_ullSize(ullSize) { TraceAssert(IDS_ORDER_BYTES != 0); if (0 == m_rgiOrders[0]) { // // Initialize the static array of file size "order" string IDs. // for (int i = IDS_ORDER_BYTES; i <= IDS_ORDER_EB; i++) { m_rgiOrders[i - IDS_ORDER_BYTES] = i; } } } // // FileSize assignment. // FileSize& FileSize::operator = ( const FileSize& rhs ) { if (this != &rhs) { m_ullSize = rhs.m_ullSize; } return *this; } // // The following code for converting a file size value to a text // string (i.e. "10.5 MB") was taken from shell32.dll so that file size // values would match those displayed in shell views. The code isn't // my normal style but I left it "as is" so I wouldn't break it. [brianau] // const int MAX_INT64_SIZE = 30; const int MAX_COMMA_NUMBER_SIZE = MAX_INT64_SIZE + 10; // // Convert a ULONGLONG file size value to a text string. // void FileSize::CvtSizeToText( ULONGLONG n, LPTSTR pszBuffer ) const { TCHAR szTemp[MAX_INT64_SIZE]; ULONGLONG iChr; iChr = 0; do { szTemp[iChr++] = (TCHAR)(TEXT('0') + (TCHAR)(n % 10)); n = n / 10; } while (n != 0); do { iChr--; *pszBuffer++ = szTemp[iChr]; } while (iChr != 0); *pszBuffer++ = '\0'; } // // Convert a string to an integer (taken from shlwapi.dll). // int FileSize::StrToInt( LPCTSTR lpSrc ) const { int n = 0; BOOL bNeg = FALSE; if (*lpSrc == TEXT('-')) { bNeg = TRUE; lpSrc++; } while (IsDigit(*lpSrc)) { n *= 10; n += *lpSrc - TEXT('0'); lpSrc++; } return bNeg ? -n : n; } // // Add commas where necessary to a number with more than 3 digits. // LPTSTR FileSize::AddCommas( ULONGLONG n, LPTSTR pszResult, int cchResult ) const { TCHAR szTemp[MAX_COMMA_NUMBER_SIZE]; TCHAR szSep[5]; NUMBERFMT nfmt; nfmt.NumDigits=0; nfmt.LeadingZero=0; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep)); nfmt.Grouping = StrToInt(szSep); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep)); nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep; nfmt.NegativeOrder= 0; CvtSizeToText(n, szTemp); if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, cchResult) == 0) StringCchCopy(pszResult, cchResult, szTemp); return pszResult; } // // Format a file size value as a text string suitable for viewing. // void FileSize::Format( ULONGLONG ullSize, LPTSTR pszFS, UINT cchFS ) const { TraceAssert(NULL != pszFS); TraceAssert(0 < cchFS); int i; ULONGLONG wInt; ULONGLONG dw64 = ullSize; UINT wLen, wDec; TCHAR szTemp[MAX_COMMA_NUMBER_SIZE], szFormat[5]; if (dw64 < 1000) { wnsprintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), (DWORD)(dw64)); i = 0; } else { int cOrders = ARRAYSIZE(m_rgiOrders); for (i = 1; i < cOrders - 1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++); /* do nothing */ wInt = dw64 >> 10; AddCommas(wInt, szTemp, ARRAYSIZE(szTemp)); wLen = lstrlen(szTemp); if (wLen < 3) { wDec = ((DWORD)(dw64 - wInt * 1024L)) * 1000 / 1024; // At this point, wDec should be between 0 and 1000 // we want get the top one (or two) digits. wDec /= 10; if (wLen == 2) wDec /= 10; // Note that we need to set the format before getting the // intl char. StringCchCopy(szFormat, ARRAYSIZE(szFormat), TEXT("%02d")); szFormat[2] = (TCHAR)(TEXT('0') + 3 - wLen); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szTemp+wLen, ARRAYSIZE(szTemp)-wLen); wLen = lstrlen(szTemp); wLen += wnsprintf(szTemp+wLen, ARRAYSIZE(szTemp)-wLen, szFormat, wDec); } } *pszFS = TEXT('\0'); LPTSTR pszText; if (0 < FormatStringID(&pszText, g_hInstance, m_rgiOrders[i], szTemp)) { StringCchCopy(pszFS, cchFS, pszText); LocalFree(pszText); } }