windows-nt/Source/XPSP1/NT/base/cmd/string.c
2020-09-26 16:20:57 +08:00

242 lines
5.7 KiB
C

/*++
Copyright (c) 1988-1999 Microsoft Corporation
Module Name:
string.c
Abstract:
String processing support
--*/
#include "cmd.h"
/***
*
* This file contains routines for finding the last character and the
* penultimate (next to last) character of a string. And finally, a routine
* (prevc) to return a pointer to the previous character given a pointer
* to an entire string and a pointer to a character within the string.
*
* John Tupper, Microsoft
*/
//
// DbcsLeadCharTable contains 256 BOOL entries. Each entry signifies
// whether the character used to look-up the table is a DBCS lead byte.
// This table needs to be updated whenever Cmd's codepage is changed.
// Dbcsleadchar is accessed by the is_dbcsleadchar macro defined in Cmd.h.
//
BOOLEAN DbcsLeadCharTable[ 256 ];
//
// AnyDbcsLeadChars is an optimization. It tells us of there are any DBCS
// lead chars currently defined in DbcsLeadCharTable. If it is FALSE, then
// we don't have to use DBCS aware string functions.
//
extern CPINFO CurrentCPInfo;
extern UINT CurrentCP;
BOOLEAN AnyDbcsLeadChars = FALSE;
VOID
InitializeDbcsLeadCharTable(
)
{
UINT i, k;
if (! GetCPInfo((CurrentCP=GetConsoleOutputCP()), &CurrentCPInfo )) {
//
// GetCPInfo failed. What should we do ?
//
#ifdef FE_SB
LCID lcid = GetThreadLocale();
if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE) {
CurrentCPInfo.LeadByte[0] = 0x81;
CurrentCPInfo.LeadByte[1] = 0x9f;
CurrentCPInfo.LeadByte[2] = 0xe0;
CurrentCPInfo.LeadByte[3] = 0xfc;
CurrentCPInfo.LeadByte[4] = 0;
CurrentCPInfo.LeadByte[5] = 0;
}
else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE) {
if (SUBLANGID(LANGIDFROMLCID(lcid)) == SUBLANG_CHINESE_SIMPLIFIED)
CurrentCPInfo.LeadByte[0] = 0x81; /* 0xa1 */
else
CurrentCPInfo.LeadByte[0] = 0x81;
CurrentCPInfo.LeadByte[1] = 0xfe;
CurrentCPInfo.LeadByte[2] = 0;
CurrentCPInfo.LeadByte[3] = 0;
}
else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_KOREAN) {
CurrentCPInfo.LeadByte[0] = 0x81;
CurrentCPInfo.LeadByte[1] = 0xfe;
CurrentCPInfo.LeadByte[2] = 0;
CurrentCPInfo.LeadByte[3] = 0;
}
else {
CurrentCPInfo.LeadByte[0] = 0;
CurrentCPInfo.LeadByte[1] = 0;
}
#else
CurrentCPInfo.LeadByte[0] = 0;
CurrentCPInfo.LeadByte[1] = 0;
#endif
}
memset( DbcsLeadCharTable, 0, 256 * sizeof (BOOLEAN) );
for (k=0 ; CurrentCPInfo.LeadByte[k] && CurrentCPInfo.LeadByte[k+1]; k+=2) {
for (i=CurrentCPInfo.LeadByte[k] ; i<=CurrentCPInfo.LeadByte[k+1] ; i++)
DbcsLeadCharTable[i] = TRUE;
}
if ( CurrentCPInfo.LeadByte[0] && CurrentCPInfo.LeadByte[1] )
AnyDbcsLeadChars = TRUE;
else
AnyDbcsLeadChars = FALSE;
}
/***
* mystrchr(string, c) - search a string for a character
*
* mystrchr will search through string and return a pointer to the first
* occurance of the character c. This version of mystrchr knows about
* double byte characters. Note that c must be a single byte character.
*
*/
TCHAR *
mystrchr(TCHAR const *string, TCHAR c)
{
/* handle null seperatly to make main loop easier to code */
if (string == NULL)
return(NULL);
return _tcschr( string, c );
}
/***
* mystrrchr(string, c) - search a string for a character
*
* mystrchr will search through string and return a pointer to the last
* occurance of the character c. This version of mystrrchr knows about
* double byte characters. Note that c must be a single byte character.
*
*/
TCHAR *
mystrrchr(TCHAR const *string, TCHAR c)
{
/* handle null seperatly to make main loop easier to code */
if ((TCHAR *)string == NULL)
return(NULL);
return _tcsrchr( string, c );
}
/***
* mystrcspn (str1, str2) will find the first character of str1 that is also
* in str2.
* Return value:
* if a match is found return the position in str1 where the matching
* character was found (the first position is 0).
* If nomatch is found, return the position of the trailing null.
*/
size_t
mystrcspn(str1, str2)
TCHAR const *str1;
TCHAR const *str2;
{
TCHAR c;
int position = 0;
if ((str1 == NULL) || (str2 == NULL))
return (0);
/* Since str2 may not contain any double byte characters,
when we see a double byte character in str1, we just skip it.
Otherwise, use mystrchr to see if we have a match */
while (c = *str1++) {
if (mystrchr(str2, c))
break;
position++;
}
return(position);
}
/***
* lastc - return a pointer to the last character of the argument string
* not including the trailing null. If a pointer to a zero length string
* is passed, a pointer to the original string is returned.
*/
TCHAR *lastc(str)
TCHAR *str;
{
TCHAR *last = str;
while(*str)
last = str++;
return(last);
}
/***
*
* penulc returns a pointer to the penultimate (next to last) character
* of the argument string not including the trailing null.
* If a pointer to a zero or one length string is passed, a pointer to
* the orignial string is returned.
*/
TCHAR *penulc(str)
TCHAR *str;
{
TCHAR *last = str;
TCHAR *penul = str;
while(*str) {
penul = last;
last = str;
str++;
}
return(penul);
}
/***
*
* prevc(str1, str2) assumes that str2 points to a character within
* str1. prevc will return a pointer to the previous character (right
* before str2). If str2 points outside of str1, NULL is returned.
*/
TCHAR *prevc(str1, str2)
TCHAR *str1, *str2;
{
TCHAR *prev = str1;
while (str1 != str2) {
if (!*str1)
return(NULL);
prev = str1;
str1++;
}
return(prev);
}