|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1998.
//
// File: string.cxx
//
// Contents: Yet another string class and support functions
//
// History: 96/Jan/3 DwightKr Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <locale.h>
//+---------------------------------------------------------------------------
//
// Member: CVirtualString::CVirtualString - public constructor
//
// Synopsis: Initializes the string by virtually allocating a buffer.
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
CVirtualString::CVirtualString( unsigned cwcBuffer ) : _wcsString(0), _wcsEnd(0), _cwcBuffer(cwcBuffer), _pwcLastCommitted(0) { _wcsString = new WCHAR[ _cwcBuffer ]; _pwcLastCommitted = _wcsString + _cwcBuffer - 1; _wcsEnd = _wcsString; *_wcsEnd = 0; } //CVirtualString
//+---------------------------------------------------------------------------
//
// Member: CVirtualString::~CVirtualString - public destructor
//
// Synopsis: Releases virtual memory assocated with this buffer
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
CVirtualString::~CVirtualString() { delete [] _wcsString; } //~CVirtualString
//+---------------------------------------------------------------------------
//
// Member: CVirtualString::GrowBuffer, private
//
// Synopsis: Commits or re-allocates the string as needed
//
// Arguments: [cwcValue] - # of WCHARs by which to grow the buffer
//
// History: 96/Mar/25 dlee Created from DwightKr's StrCat
//
//----------------------------------------------------------------------------
void CVirtualString::GrowBuffer( ULONG cwcValue ) { unsigned cwcNewString = cwcValue + 1; unsigned cwcOldString = CiPtrToUint( _wcsEnd - _wcsString ); unsigned cwcRemaining = CiPtrToUint( _cwcBuffer - cwcOldString );
Win4Assert( _cwcBuffer >= cwcOldString );
if ( cwcRemaining < cwcNewString ) { DWORD cwcOldBuffer = _cwcBuffer; DWORD cwcNewBuffer = _cwcBuffer;
do { cwcNewBuffer *= 2; cwcRemaining = cwcNewBuffer - cwcOldString; } while ( cwcRemaining < cwcNewString );
XArray<WCHAR> xTemp( cwcNewBuffer );
RtlCopyMemory( xTemp.GetPointer(), _wcsString, _cwcBuffer * sizeof WCHAR ); delete [] _wcsString;
_wcsString = xTemp.Acquire(); _cwcBuffer = cwcNewBuffer; _wcsEnd = _wcsString + cwcOldString; _pwcLastCommitted = _wcsString + _cwcBuffer - 1; } } //GrowBuffer
// if TRUE, the character doesn't need to be URL escaped
static const BYTE g_afNoEscape[128] = { FALSE, // 00 (NUL)
FALSE, // 01 (SOH)
FALSE, // 02 (STX)
FALSE, // 03 (ETX)
FALSE, // 04 (EOT)
FALSE, // 05 (ENQ)
FALSE, // 06 (ACK)
FALSE, // 07 (BEL)
FALSE, // 08 (BS)
FALSE, // 09 (HT)
FALSE, // 0A (LF)
FALSE, // 0B (VT)
FALSE, // 0C (FF)
FALSE, // 0D (CR)
FALSE, // 0E (SI)
FALSE, // 0F (SO)
FALSE, // 10 (DLE)
FALSE, // 11 (DC1)
FALSE, // 12 (DC2)
FALSE, // 13 (DC3)
FALSE, // 14 (DC4)
FALSE, // 15 (NAK)
FALSE, // 16 (SYN)
FALSE, // 17 (ETB)
FALSE, // 18 (CAN)
FALSE, // 19 (EM)
FALSE, // 1A (SUB)
FALSE, // 1B (ESC)
FALSE, // 1C (FS)
FALSE, // 1D (GS)
FALSE, // 1E (RS)
FALSE, // 1F (US)
FALSE, // 20 SPACE
FALSE, // 21 !
FALSE, // 22 "
FALSE, // 23 #
FALSE, // 24 $
FALSE, // 25 %
FALSE, // 26 &
FALSE, // 27 '
FALSE, // 28 (
FALSE, // 29 )
FALSE, // 2A *
FALSE, // 2B +
FALSE, // 2C ,
FALSE, // 2D -
TRUE, // 2E .
TRUE, // 2F /
TRUE, // 30 0
TRUE, // 31 1
TRUE, // 32 2
TRUE, // 33 3
TRUE, // 34 4
TRUE, // 35 5
TRUE, // 36 6
TRUE, // 37 7
TRUE, // 38 8
TRUE, // 39 9
TRUE, // 3A :
FALSE, // 3B ;
FALSE, // 3C <
TRUE, // 3D =
FALSE, // 3E >
FALSE, // 3F ?
FALSE, // 40 @
TRUE, // 41 A
TRUE, // 42 B
TRUE, // 43 C
TRUE, // 44 D
TRUE, // 45 E
TRUE, // 46 F
TRUE, // 47 G
TRUE, // 48 H
TRUE, // 49 I
TRUE, // 4A J
TRUE, // 4B K
TRUE, // 4C L
TRUE, // 4D M
TRUE, // 4E N
TRUE, // 4F O
TRUE, // 50 P
TRUE, // 51 Q
TRUE, // 52 R
TRUE, // 53 S
TRUE, // 54 T
TRUE, // 55 U
TRUE, // 56 V
TRUE, // 57 W
TRUE, // 58 X
TRUE, // 59 Y
TRUE, // 5A Z
FALSE, // 5B [
FALSE, // 5C \
FALSE, // 5D ]
FALSE, // 5E ^
FALSE, // 5F _
FALSE, // 60 `
TRUE, // 61 a
TRUE, // 62 b
TRUE, // 63 c
TRUE, // 64 d
TRUE, // 65 e
TRUE, // 66 f
TRUE, // 67 g
TRUE, // 68 h
TRUE, // 69 i
TRUE, // 6A j
TRUE, // 6B k
TRUE, // 6C l
TRUE, // 6D m
TRUE, // 6E n
TRUE, // 6F o
TRUE, // 70 p
TRUE, // 71 q
TRUE, // 72 r
TRUE, // 73 s
TRUE, // 74 t
TRUE, // 75 u
TRUE, // 76 v
TRUE, // 77 w
TRUE, // 78 x
TRUE, // 79 y
TRUE, // 7A z
FALSE, // 7B {
FALSE, // 7C |
FALSE, // 7D }
FALSE, // 7E ~
FALSE, // 7F (DEL)
};
static const unsigned cNoEscape = sizeof g_afNoEscape / sizeof g_afNoEscape[0];
//+---------------------------------------------------------------------------
//
// Function: IsNoUrlEscape
//
// Synopsis: Determines if a character doesn't need URL escaping.
//
// Arguments: [c] -- Character to test, T must be unsigned.
//
// Returns: TRUE if b doesn't need URL escaping.
//
// History: 98/Apr/22 dlee Created.
//
//----------------------------------------------------------------------------
template<class T> inline BOOL IsNoUrlEscape( T c ) { if ( c < cNoEscape ) return g_afNoEscape[ c ];
return FALSE; } //IsNoUrlEscape
//+---------------------------------------------------------------------------
//
// Function: URLEscapeW
//
// Synopsis: Appends an escaped version of a string to a virtual string.
//
// History: 96/Apr/03 dlee Created from DwightKr's code
// 96/May/21 DwightKr Escape spaces
// 97/Nov/19 AlanW Allow %ummmm escape codes
//
//----------------------------------------------------------------------------
void URLEscapeW( WCHAR const * wcsString, CVirtualString & StrResult, ULONG ulCodepage, BOOL fConvertSpaceToPlus ) { BOOL fTryConvertMB = TRUE;
//
// All spaces are converted to plus signs (+), percents are doubled,
// Non alphanumeric characters are represented by their
// hexadecimal ASCII equivalents.
//
Win4Assert( wcsString != 0 );
while ( *wcsString != 0 ) { //
// Spaces can be treated differently on either size of the ?.
// Spaces before the ? (the URI) needs to have spaces escaped;
// those AFTER the ? can be EITHER escaped, or changed to a +.
// Use either '+' or the % escape depending upon fConverSpaceToPlus
//
if ( IsNoUrlEscape( *wcsString ) ) { StrResult.CharCat( *wcsString ); } else if ( L' ' == *wcsString ) { if ( fConvertSpaceToPlus ) StrResult.CharCat( L'+' ); else StrResult.StrCat( L"%20", 3 ); } else if ( L'%' == *wcsString ) { StrResult.StrCat( L"%%", 2 ); } else if ( *wcsString < 0x80 ) { StrResult.CharCat( L'%' ); unsigned hiNibble = ((*wcsString) & 0xf0) >> 4; unsigned loNibble = (*wcsString) & 0x0f; StrResult.CharCat( hiNibble > 9 ? (hiNibble-10 + L'A') : (hiNibble + L'0') ); StrResult.CharCat( loNibble > 9 ? (loNibble-10 + L'A') : (loNibble + L'0') ); } else { Win4Assert( *wcsString >= 0x80 ); //
// We encountered a character outside the ASCII range.
// Try counverting the Unicode string to multi-byte. If the
// conversion succeeds, continue by converting to 8 bit characters.
// Otherwise, convert this and any other Unicode characters to the
// %ummmm escape.
//
if ( fTryConvertMB ) { ULONG cchString = wcslen(wcsString); XArray<BYTE> pszString( cchString*2 ); BOOL fUsedDefaultChar = FALSE; DWORD cbConvert; ULONG cbString = pszString.Count();
do { cbConvert = WideCharToMultiByte( ulCodepage, #if (WINVER >= 0x0500)
WC_NO_BEST_FIT_CHARS | #endif // (WINVER >= 0x0500)
WC_COMPOSITECHECK | WC_DEFAULTCHAR, wcsString, cchString, (CHAR *) pszString.Get(), cbString, 0, &fUsedDefaultChar );
if ( 0 == cbConvert ) { Win4Assert( cbString > 0 ); if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { cbString += cbString; delete pszString.Acquire(); pszString.Init(cbString); } else if ( GetLastError() == ERROR_INVALID_PARAMETER ) { // Presumably unknown code page.
fUsedDefaultChar = TRUE; break; } else { THROW( CException() ); } } } while ( 0 == cbConvert );
if ( ! fUsedDefaultChar ) { URLEscapeMToW(pszString.Get(), cbConvert, StrResult, fConvertSpaceToPlus ); return; } fTryConvertMB = FALSE; }
// Convert to an escaped Unicode character
StrResult.StrCat( L"%u", 2 ); USHORT wch = *wcsString;
unsigned iNibble = (wch & 0xf000) >> 12; StrResult.CharCat( iNibble > 9 ? (iNibble-10 + L'A') : (iNibble + L'0') ); iNibble = (wch & 0x0f00) >> 8; StrResult.CharCat( iNibble > 9 ? (iNibble-10 + L'A') : (iNibble + L'0') ); iNibble = (wch & 0x00f0) >> 4; StrResult.CharCat( iNibble > 9 ? (iNibble-10 + L'A') : (iNibble + L'0') ); iNibble = wch & 0x000f; StrResult.CharCat( iNibble > 9 ? (iNibble-10 + L'A') : (iNibble + L'0') ); }
wcsString++; } } //URLEscapeW
//+---------------------------------------------------------------------------
//
// Function: URLEscapeMToW
//
// Synopsis: Appends an escaped version of a string to a virtual string.
// The string is 'pseudo-UniCode'. A multi-byte input string
// is converted to a UniCode URL, which is implicitly ASCII.
//
// History: 96/Apr/03 dlee Created from DwightKr's code
// 96/May/21 DwightKr Escape spaces
// 96-Sep-17 KyleP Modified URLEscapeW
//
//----------------------------------------------------------------------------
void URLEscapeMToW( BYTE const * psz, unsigned cc, CVirtualString & StrResult, BOOL fConvertSpaceToPlus ) { //
// All spaces are converted to plus signs (+), percents are doubled,
// Non alphanumeric characters are represented by their
// hexadecimal ASCII equivalents.
//
Win4Assert( psz != 0 );
for( unsigned i = 0; i < cc; i++ ) { //
// Spaces can be treated differently on either size of the ?.
// Spaces before the ? (the URI) needs to have spaces escaped;
// those AFTER the ? can be EITHER escaped, or changed to a +.
// Use either '+' or the % escape depending upon fConverSpaceToPlus
//
if ( IsNoUrlEscape( psz[i] ) ) { StrResult.CharCat( (WCHAR)psz[i] ); } else if ( L' ' == psz[i] ) { if ( fConvertSpaceToPlus ) StrResult.CharCat( L'+' ); else StrResult.StrCat( L"%20", 3 ); } else if ( L'%' == psz[i] ) { StrResult.StrCat( L"%%", 2 ); } else { StrResult.CharCat( L'%' ); unsigned hiNibble = ((psz[i]) & 0xf0) >> 4; unsigned loNibble = (psz[i]) & 0x0f; StrResult.CharCat( hiNibble > 9 ? (hiNibble-10 + L'A') : (hiNibble + L'0') ); StrResult.CharCat( loNibble > 9 ? (loNibble-10 + L'A') : (loNibble + L'0') ); } } } //URLEscapeMToW
|