📄 mbctype.c
字号:
/***
*setSBCS() - Set MB code page to SBCS.
*
*Purpose:
* Set MB code page to SBCS.
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
static void setSBCS (pthreadmbcinfo ptmbci)
{
int i;
/* set for single-byte code page */
for (i = 0; i < NUM_CHARS; i++)
ptmbci->mbctype[i] = 0;
/* code page has changed, set global flag */
ptmbci->mbcodepage = 0;
/* clear flag to indicate single-byte code */
ptmbci->ismbcodepage = 0;
ptmbci->mblcid = 0;
for (i = 0; i < NUM_ULINFO; i++)
ptmbci->mbulinfo[i] = 0;
for ( i = 0 ; i < 257 ; i++ )
ptmbci->mbctype[i] = __initialmbcinfo.mbctype[i];
for ( i = 0 ; i < 256 ; i++ )
ptmbci->mbcasemap[i] = __initialmbcinfo.mbcasemap[i];
}
/***
*setSBUpLow() - Set single byte upper/lower mappings
*
*Purpose:
* Set single byte mapping for tolower/toupper.
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
static void setSBUpLow (pthreadmbcinfo ptmbci)
{
BYTE * pbPair;
UINT ich;
CPINFO cpinfo;
UCHAR sbVector[256];
UCHAR upVector[256];
UCHAR lowVector[256];
USHORT wVector[256];
// test if codepage exists
if (GetCPInfo(ptmbci->mbcodepage, &cpinfo) != 0)
{
// if so, create vector 0-255
for (ich = 0; ich < 256; ich++)
sbVector[ich] = (UCHAR) ich;
// set byte 0 and any leading byte value to non-alpha char ' '
sbVector[0] = (UCHAR)' ';
for (pbPair = &cpinfo.LeadByte[0]; *pbPair; pbPair += 2)
for (ich = *pbPair; ich <= *(pbPair + 1); ich++)
sbVector[ich] = (UCHAR)' ';
// get char type for character vector
__crtGetStringTypeA(NULL, CT_CTYPE1, (LPCSTR)sbVector, 256, wVector,
ptmbci->mbcodepage, ptmbci->mblcid, FALSE);
// get lower case mappings for character vector
__crtLCMapStringA(NULL, ptmbci->mblcid, LCMAP_LOWERCASE, (LPCSTR)sbVector, 256,
(LPSTR)lowVector, 256, ptmbci->mbcodepage, FALSE);
// get upper case mappings for character vector
__crtLCMapStringA(NULL, ptmbci->mblcid, LCMAP_UPPERCASE, (LPCSTR)sbVector, 256,
(LPSTR)upVector, 256, ptmbci->mbcodepage, FALSE);
// set _SBUP, _SBLOW in ptmbci->mbctype if type is upper. lower
// set mapping array with lower or upper mapping value
for (ich = 0; ich < 256; ich++)
if (wVector[ich] & _UPPER)
{
ptmbci->mbctype[ich + 1] |= _SBUP;
ptmbci->mbcasemap[ich] = lowVector[ich];
}
else if (wVector[ich] & _LOWER)
{
ptmbci->mbctype[ich + 1] |= _SBLOW;
ptmbci->mbcasemap[ich] = upVector[ich];
}
else
ptmbci->mbcasemap[ich] = 0;
}
else
{
// if no codepage, set 'A'-'Z' as upper, 'a'-'z' as lower
for (ich = 0; ich < 256; ich++)
if (ich >= (UINT)'A' && ich <= (UINT)'Z')
{
ptmbci->mbctype[ich + 1] |= _SBUP;
ptmbci->mbcasemap[ich] = ich + ('a' - 'A');
}
else if (ich >= (UINT)'a' && ich <= (UINT)'z')
{
ptmbci->mbctype[ich + 1] |= _SBLOW;
ptmbci->mbcasemap[ich] = ich - ('a' - 'A');
}
else
ptmbci->mbcasemap[ich] = 0;
}
}
/***
*__updatetmbcinfo() - refresh the thread's mbc info
*
*Purpose:
* Update the current thread's reference to the multibyte character
* information to match the current global mbc info. Decrement the
* reference on the old mbc information struct and if this count is now
* zero (so that no threads are using it), free it.
*
*Entry:
*
*Exit:
* _getptd()->ptmbcinfo == __ptmbcinfo
*
*Exceptions:
*
*******************************************************************************/
extern "C" pthreadmbcinfo __cdecl __updatetmbcinfo(void)
{
pthreadmbcinfo ptmbci;
_ptiddata ptd = _getptd();
if (!(ptd->_ownlocale & __globallocalestatus)|| !ptd->ptlocinfo) {
_mlock(_MB_CP_LOCK);
__try
{
if ( (ptmbci = ptd->ptmbcinfo) != __ptmbcinfo )
{
/*
* Decrement the reference count in the old mbc info structure
* and free it, if necessary
*/
if ( (ptmbci != NULL) && (InterlockedDecrement((volatile LONG *)&(ptmbci->refcount)) == 0) && ptmbci != &__initialmbcinfo )
{
/*
* Free it
*/
_free_crt(ptmbci);
}
/*
* Point to the current mbc info structure and increment its
* reference count.
*/
ptmbci = ptd->ptmbcinfo = __ptmbcinfo;
InterlockedIncrement((volatile LONG *)&(ptmbci->refcount));
}
}
__finally
{
_munlock(_MB_CP_LOCK);
}
} else {
ptmbci = ptd->ptmbcinfo;
}
if(!ptmbci)
{
_amsg_exit(_RT_LOCALE);
}
return ptmbci;
}
/***
*_setmbcp() - Set MBC data based on code page
*
*Purpose:
* Init MBC character type tables based on code page number. If
* given code page is supported, load that code page info into
* mbctype table. If not, query OS to find the information,
* otherwise set up table with single byte info.
*
* Multithread Notes: First, allocate an mbc information struct. Set the
* mbc info in the static vars and arrays as does the single-thread
* version. Then, copy this info into the new allocated struct and set
* the current mbc info pointer (__ptmbcinfo) to point to it.
*
*Entry:
* codepage - code page to initialize MBC table
* _MB_CP_OEM = use system OEM code page
* _MB_CP_ANSI = use system ANSI code page
* _MB_CP_SBCS = set to single byte 'code page'
*
*Exit:
* 0 = Success
* -1 = Error, code page not changed.
*
*Exceptions:
*
*******************************************************************************/
extern "C" int __cdecl _setmbcp (int codepage)
{
int retcode = -1; /* initialize to failure */
pthreadmbcinfo ptmbci;
int i;
_ptiddata ptd = _getptd();
__updatetmbcinfo();
ptmbci = ptd->ptmbcinfo;
codepage = getSystemCP(codepage);
if ( codepage != ptmbci->mbcodepage )
{
/*
* Always allocate space so that we don't have to take lock
* for any update.
*/
ptmbci = (pthreadmbcinfo)_malloc_crt( sizeof(threadmbcinfo) );
if (ptmbci != NULL)
{
*ptmbci = *(ptd->ptmbcinfo);
/*
* Note that refcount for this structure is just one so
* update the refcount.
*/
/*
* Note that the refcount is set to zero because we don't count this
* refcount as we won't be calling InterlockedDecrement for this when
* the variable goes out of scope.
*/
ptmbci->refcount = 0;
/*
* Install the codepage and copy the info into the struct
*/
if ( (retcode = _setmbcp_nolock(codepage, ptmbci)) == 0)
{
if (InterlockedDecrement((volatile LONG *)&ptd->ptmbcinfo->refcount) == 0 && ptd->ptmbcinfo != &__initialmbcinfo)
_free_crt(ptd->ptmbcinfo);
/*
* Assign and increment the refcount of this structure.
*/
ptd->ptmbcinfo = ptmbci;
InterlockedIncrement((volatile LONG *)&(ptd->ptmbcinfo->refcount));
if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT) &&
!(__globallocalestatus & _GLOBAL_LOCALE_BIT)) {
_mlock(_MB_CP_LOCK);
__try
{
/*
* Fill in the mbc info struct
*/
__mbcodepage = ptmbci->mbcodepage;
__ismbcodepage = ptmbci->ismbcodepage;
__mblcid = ptmbci->mblcid;
for ( i = 0 ; i < 5 ; i++ )
__mbulinfo[i] = ptmbci->mbulinfo[i];
for ( i = 0 ; i < 257 ; i++ )
_mbctype[i] = ptmbci->mbctype[i];
for ( i = 0 ; i < 256 ; i++ )
_mbcasemap[i] = ptmbci->mbcasemap[i];
if (InterlockedDecrement((volatile LONG *)&__ptmbcinfo->refcount) == 0 && __ptmbcinfo != &__initialmbcinfo)
_free_crt(__ptmbcinfo);
/*
* Update __ptmbcinfo
*/
__ptmbcinfo = ptmbci;
InterlockedIncrement((volatile LONG *)&ptmbci->refcount);
}
__finally
{
_munlock(_MB_CP_LOCK);
}
}
}
else if (retcode == -1)
{
/*
* Free up the newly malloc-ed struct (note: a free of
* NULL is legal)
*/
if (ptmbci != &__initialmbcinfo)
_free_crt(ptmbci);
errno = EINVAL;
/* note that if malloc fails, it sets errno to ENOMEM already */
}
}
}
else
/*
* Not a new codepage after all. Nothing to do but return
* success.
*/
retcode = 0;
#pragma warning(disable:4390)
if ( (retcode == -1) && (__ptmbcinfo == NULL) )
/*
* Fatal error!
*/
;
return retcode;
}
extern "C" int __cdecl _setmbcp_nolock(int codepage, pthreadmbcinfo ptmbci)
{
unsigned int icp;
unsigned int irg;
unsigned int ich;
unsigned char *rgptr;
CPINFO cpinfo;
codepage = getSystemCP(codepage);
/* user wants 'single-byte' MB code page */
if (codepage == _MB_CP_SBCS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -