-
Notifications
You must be signed in to change notification settings - Fork 4
/
k_iconv.c
99 lines (86 loc) · 2.74 KB
/
k_iconv.c
1
2
3
4
5
6
7
8
9
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
#include "k_mem.h"
#include "k_iconv.h"
#include <stdlib.h>
DWORD ic_get_cp866(BYTE** p)
{
DWORD ch = *(*p)++; if(ch<0x80) return ch;
if(ch<0xB0) return ch+0x410-0x80;
if(ch<0xE0) return '?';
if(ch<0xF0) return ch+0x440-0xE0;
if(ch==0xF0) return 0x401;
if(ch==0xF1) return 0x451;
return '?';
}
DWORD ic_put_cp866(BYTE* p, DWORD ch)
{
if(ch<0x80) *p = ch; else
if(ch==0x401) *p = 0xF0; else
if(ch<0x410) *p = '?'; else
if(ch<0x440) *p = ch-0x410+0x80; else
if(ch<0x450) *p = ch-0x440+0xE0; else
if(ch==0x451) *p = 0xF1; else
*p='?';
return 1;
}
DWORD ic_get_utf8(BYTE** p)
{
DWORD ch = *(*p)++,x=ch; if(ch<0x80) return ch;
if(ch<0xC0||ch>=0xF8) return '?'; else ch &= 0x1F;
for(;x&0x40;x<<=1) ch = (ch<<6)|((*(*p)++)&0x3F);
return ch;
}
DWORD ic_put_utf8(BYTE* p, DWORD ch)
{
if(ch<0x80) { *p = ch; return 1; }
if(ch<0x800) { *p++ = (ch>>6)|0xC0; *p = (ch&0x3F)|0x80; return 2; }
if(ch<0x10000) { *p++ = (ch>>12)|0xC0; *p++ = ((ch>>6)&0x3F)|0x80; *p = (ch&0x3F)|0x80; return 3; }
*p++ = (ch>>18)|0xC0; *p++ = ((ch>>12)&0x3F)|0x80; *p++ = ((ch>>6)&0x3F)|0x80; *p = (ch&0x3F)|0x80;
return 4;
}
DWORD ic_get_utf16le(BYTE** p)
{
DWORD ch = *(WORD*)*p; *p += 2;
return ch;
}
DWORD ic_put_utf16le(BYTE* p, DWORD ch)
{
*(WORD*)p = ch;
return 2;
}
static DWORD (*ic_get[])(BYTE**) = {ic_get_cp866, ic_get_cp866, ic_get_utf16le, ic_get_utf8};
static DWORD (*ic_put[])(BYTE*,DWORD) = {ic_put_cp866, ic_put_cp866, ic_put_utf16le, ic_put_utf8};
DWORD k_strlen(BYTE* src, int src_cp)
{
DWORD len; if(src_cp<0) src_cp = *src==0||*src>3 ? 0 : *src++;
DWORD (*get)(BYTE**) = ic_get[src_cp&3];
for(len=0; get(&src); ++len);
return len;
}
DWORD k_strsize(BYTE* src, int src_cp, int dst_cp)
{
DWORD ch,size=0; if(src_cp<0) src_cp = *src==0||*src>3 ? 0 : *src++;
DWORD (*get)(BYTE**) = ic_get[src_cp&3];
DWORD (*put)(BYTE*,DWORD) = ic_put[(dst_cp<0?src_cp:dst_cp)&3];
BYTE tmp[8]; for(ch=1;ch;) size += put(tmp, ch=get(&src));
if(dst_cp<0 && src_cp>0) ++size;
return size;
}
BYTE* k_strncpy(BYTE* dst, int dst_cp, BYTE* src, int src_cp, DWORD maxlen)
{
DWORD ch; if(src_cp<0) src_cp = *src==0||*src>3 ? 0 : *src++;
DWORD (*get)(BYTE**) = ic_get[src_cp&3];
DWORD (*put)(BYTE*,DWORD) = ic_put[(dst_cp<0?src_cp:dst_cp)&3];
if(dst_cp<0 && src_cp>0) *dst++ = src_cp;
for(;maxlen>0 && (ch=get(&src))!=0;--maxlen) dst += put(dst, ch); put(dst, 0);
return dst;
}
BYTE* k_strcpy(BYTE* dst, int dst_cp, BYTE* src, int src_cp)
{
return k_strncpy(dst,dst_cp,src,src_cp,-1);
}
BYTE* k_strdup(BYTE* src, int src_cp, int dst_cp)
{
BYTE* dst = malloc(k_strsize(src,src_cp,dst_cp));
k_strncpy(dst,dst_cp,src,src_cp,-1);
return dst;
}