- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
int _Mbtowcx(wchar_t *pwc, const char *s, size_t nin, mbstate_t *pst, _Statab *pmbstate)
char state = (char)pst->_State;
unsigned char *su = (unsigned char *)s;
wchar_t wc = (wchar_t)pst->_Wchar;
static const mbstate_t initial = {0};
if (pmbstate->_Tab[0] == 0) { /* no table, convert from UTF8 */
if (s == 0)
{ /* set initial state */
*pst = initial;
return (0);
}
for (; ; ++su, --nin) { /* consume an input byte */
if (nin == 0) { /* report incomplete conversion */
pst->_Wchar = wc;
pst->_State = state;
return (-2);
}
else if (0 < state) { /* fold in a successor byte */
if ((*su & 0xc0) != 0x80) { /* report invalid sequence */
errno = EILSEQ;
return (-1);
}
wc = (wchar_t)((wc << 6) | (*su & 0x3f));
--state;
}
else if ((*su & 0x80) == 0)
wc = *su; /* consume a single byte */
else if ((*su & 0xe0) == 0xc0) { /* consume first of two bytes */
wc = (wchar_t)(*su & 0x1f);
state = 1;
}
else if ((*su & 0xf0) == 0xe0) { /* consume first of three bytes */
wc = (wchar_t)(*su & 0x0f);
state = 2;
}
else{ /* report invalid sequence */
errno = EILSEQ;
return (-1);
}
if (state == 0) { /* produce an output wchar */
if (pwc != 0)
*pwc = wc;
pst->_State = 0;
return (wc == 0 ? 0 : (const char *)++su - s);
}
}
}
else
{ /* run finite state machine */
int limit = 0;
if (s == 0) { /* set initial state */
*pst = initial;
return (pmbstate->_Tab[0][0] & _ST_STATE);
}
for (; ; ) { /* perform a state transformation */
unsigned short code;
const unsigned short *stab;
if (nin == 0)
{ /* report incomplete conversion */
pst->_Wchar = wc;
pst->_State = state;
return (-2);
}
else if (_NSTATE <= state
|| (stab = pmbstate->_Tab[state]) == 0
|| (_NSTATE*UCHAR_MAX) <= ++limit
|| (code = stab[*su]) == 0)
{ /* report invalid sequence */
errno = EILSEQ;
return (-1);
}
state = (char)((code & _ST_STATE) >> _ST_STOFF);
if (code & _ST_FOLD)
wc = (wchar_t)(wc & ~UCHAR_MAX | code & _ST_CH);
if (code & _ST_ROTATE)
wc = (wchar_t)(wc << CHAR_BIT | UCHAR_MAX
& wc >> CHAR_BIT * (sizeof (wchar_t) - 1));
if (code & _ST_INPUT && *su != '\0')
++su, --nin, limit = 0;
if (code & _ST_OUTPUT)
{ /* produce an output wchar */
int nused = (const char *)su - s;
if (pwc)
*pwc = wc;
pst->_Wchar = wc;
pst->_State = state;
return (wc == 0 ? 0 : nused == 0 ? -3 : nused);
}
}
}
}
Lure Of Chaos 06.04.2011 22:28 # 0
absolut 06.04.2011 22:39 # 0
Lure Of Chaos 06.04.2011 22:41 # 0
sanchousf 06.04.2011 23:41 # 0
Аналогичная функция с MS Visual Studio делает примерно так
bugmenot 06.04.2011 23:53 # +1
absolut 07.04.2011 07:44 # 0
Lure Of Chaos 07.04.2011 12:09 # 0
gegMOPO4 07.04.2011 20:33 # 0
absolut 07.04.2011 21:32 # 0
sanchousf 07.04.2011 22:09 # −1
Во вторых: Реализация. Вот список кодовых таблиц поддерживаемых Виндой
http://msdn.microsoft.com/en-us/library/dd317756(v=VS.85).aspx
А в данная функция, вроде бы, поддерживает UTF8 и OEM.
Зачем придумывать такой алгоритм если надежней воспользоваться функцией MultiByteToWideChar?
gegMOPO4 07.04.2011 22:52 # 0
Эта функция как раз и реализует перекодировку из многобайтной кодировки в wchar. Для этого используется конечный автомат, управляемый таблицами (а кроме 8-битных кодировок существуют и многобайтные азиатские кодировки). В частном случае UTF-8 автомат закодирован явно (таблицы были бы слишком большими). Загляните в код iconv (или MultiByteToWideChar) — там увидите ещё сложнее.
Почему не используется MultiByteToWideChar? Ну, возможно, когда писался этот код, её ещё не было. Или она поддерживала очень ограниченный набор кодировок. Или медленнее. Или часть рантайма MS VС, а не системная.
sanchousf 07.04.2011 23:49 # 0
gegMOPO4 08.04.2011 10:34 # 0
sanchousf 08.04.2011 13:01 # 0
P. S. Код mbtowc и _Mbtowc приведен полностью
gegMOPO4 08.04.2011 13:51 # 0
Для работы этой перекодировщику нужны ещё таблицы, на которые ссылается pmbstate (они могут занимать сотни килобайт и даже мегабайты). Полюбопытствуйте, разберитесь, как оно работает.
sanchousf 07.04.2011 23:53 # −1
lexa 24.08.2021 01:03 # 0