1*8ccd4a63SDavid du Colombier #include <u.h> 2*8ccd4a63SDavid du Colombier #include <libc.h> 3*8ccd4a63SDavid du Colombier 4*8ccd4a63SDavid du Colombier enum 5*8ccd4a63SDavid du Colombier { 6*8ccd4a63SDavid du Colombier Bit1 = 7, 7*8ccd4a63SDavid du Colombier Bitx = 6, 8*8ccd4a63SDavid du Colombier Bit2 = 5, 9*8ccd4a63SDavid du Colombier Bit3 = 4, 10*8ccd4a63SDavid du Colombier Bit4 = 3, 11*8ccd4a63SDavid du Colombier 12*8ccd4a63SDavid du Colombier T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ 13*8ccd4a63SDavid du Colombier Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ 14*8ccd4a63SDavid du Colombier T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ 15*8ccd4a63SDavid du Colombier T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ 16*8ccd4a63SDavid du Colombier T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ 17*8ccd4a63SDavid du Colombier 18*8ccd4a63SDavid du Colombier Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ 19*8ccd4a63SDavid du Colombier Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ 20*8ccd4a63SDavid du Colombier Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ 21*8ccd4a63SDavid du Colombier 22*8ccd4a63SDavid du Colombier Maskx = (1<<Bitx)-1, /* 0011 1111 */ 23*8ccd4a63SDavid du Colombier Testx = Maskx ^ 0xFF, /* 1100 0000 */ 24*8ccd4a63SDavid du Colombier 25*8ccd4a63SDavid du Colombier Bad = Runeerror, 26*8ccd4a63SDavid du Colombier }; 27*8ccd4a63SDavid du Colombier 28*8ccd4a63SDavid du Colombier int 29*8ccd4a63SDavid du Colombier chartorune(Rune *rune, char *str) 30*8ccd4a63SDavid du Colombier { 31*8ccd4a63SDavid du Colombier int c, c1, c2; 32*8ccd4a63SDavid du Colombier long l; 33*8ccd4a63SDavid du Colombier 34*8ccd4a63SDavid du Colombier /* 35*8ccd4a63SDavid du Colombier * one character sequence 36*8ccd4a63SDavid du Colombier * 00000-0007F => T1 37*8ccd4a63SDavid du Colombier */ 38*8ccd4a63SDavid du Colombier c = *(uchar*)str; 39*8ccd4a63SDavid du Colombier if(c < Tx) { 40*8ccd4a63SDavid du Colombier *rune = c; 41*8ccd4a63SDavid du Colombier return 1; 42*8ccd4a63SDavid du Colombier } 43*8ccd4a63SDavid du Colombier 44*8ccd4a63SDavid du Colombier /* 45*8ccd4a63SDavid du Colombier * two character sequence 46*8ccd4a63SDavid du Colombier * 0080-07FF => T2 Tx 47*8ccd4a63SDavid du Colombier */ 48*8ccd4a63SDavid du Colombier c1 = *(uchar*)(str+1) ^ Tx; 49*8ccd4a63SDavid du Colombier if(c1 & Testx) 50*8ccd4a63SDavid du Colombier goto bad; 51*8ccd4a63SDavid du Colombier if(c < T3) { 52*8ccd4a63SDavid du Colombier if(c < T2) 53*8ccd4a63SDavid du Colombier goto bad; 54*8ccd4a63SDavid du Colombier l = ((c << Bitx) | c1) & Rune2; 55*8ccd4a63SDavid du Colombier if(l <= Rune1) 56*8ccd4a63SDavid du Colombier goto bad; 57*8ccd4a63SDavid du Colombier *rune = l; 58*8ccd4a63SDavid du Colombier return 2; 59*8ccd4a63SDavid du Colombier } 60*8ccd4a63SDavid du Colombier 61*8ccd4a63SDavid du Colombier /* 62*8ccd4a63SDavid du Colombier * three character sequence 63*8ccd4a63SDavid du Colombier * 0800-FFFF => T3 Tx Tx 64*8ccd4a63SDavid du Colombier */ 65*8ccd4a63SDavid du Colombier c2 = *(uchar*)(str+2) ^ Tx; 66*8ccd4a63SDavid du Colombier if(c2 & Testx) 67*8ccd4a63SDavid du Colombier goto bad; 68*8ccd4a63SDavid du Colombier if(c < T4) { 69*8ccd4a63SDavid du Colombier l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; 70*8ccd4a63SDavid du Colombier if(l <= Rune2) 71*8ccd4a63SDavid du Colombier goto bad; 72*8ccd4a63SDavid du Colombier *rune = l; 73*8ccd4a63SDavid du Colombier return 3; 74*8ccd4a63SDavid du Colombier } 75*8ccd4a63SDavid du Colombier 76*8ccd4a63SDavid du Colombier /* 77*8ccd4a63SDavid du Colombier * bad decoding 78*8ccd4a63SDavid du Colombier */ 79*8ccd4a63SDavid du Colombier bad: 80*8ccd4a63SDavid du Colombier *rune = Bad; 81*8ccd4a63SDavid du Colombier return 1; 82*8ccd4a63SDavid du Colombier } 83*8ccd4a63SDavid du Colombier 84*8ccd4a63SDavid du Colombier int 85*8ccd4a63SDavid du Colombier runetochar(char *str, Rune *rune) 86*8ccd4a63SDavid du Colombier { 87*8ccd4a63SDavid du Colombier long c; 88*8ccd4a63SDavid du Colombier 89*8ccd4a63SDavid du Colombier /* 90*8ccd4a63SDavid du Colombier * one character sequence 91*8ccd4a63SDavid du Colombier * 00000-0007F => 00-7F 92*8ccd4a63SDavid du Colombier */ 93*8ccd4a63SDavid du Colombier c = *rune; 94*8ccd4a63SDavid du Colombier if(c <= Rune1) { 95*8ccd4a63SDavid du Colombier str[0] = c; 96*8ccd4a63SDavid du Colombier return 1; 97*8ccd4a63SDavid du Colombier } 98*8ccd4a63SDavid du Colombier 99*8ccd4a63SDavid du Colombier /* 100*8ccd4a63SDavid du Colombier * two character sequence 101*8ccd4a63SDavid du Colombier * 0080-07FF => T2 Tx 102*8ccd4a63SDavid du Colombier */ 103*8ccd4a63SDavid du Colombier if(c <= Rune2) { 104*8ccd4a63SDavid du Colombier str[0] = T2 | (c >> 1*Bitx); 105*8ccd4a63SDavid du Colombier str[1] = Tx | (c & Maskx); 106*8ccd4a63SDavid du Colombier return 2; 107*8ccd4a63SDavid du Colombier } 108*8ccd4a63SDavid du Colombier 109*8ccd4a63SDavid du Colombier /* 110*8ccd4a63SDavid du Colombier * three character sequence 111*8ccd4a63SDavid du Colombier * 0800-FFFF => T3 Tx Tx 112*8ccd4a63SDavid du Colombier */ 113*8ccd4a63SDavid du Colombier str[0] = T3 | (c >> 2*Bitx); 114*8ccd4a63SDavid du Colombier str[1] = Tx | ((c >> 1*Bitx) & Maskx); 115*8ccd4a63SDavid du Colombier str[2] = Tx | (c & Maskx); 116*8ccd4a63SDavid du Colombier return 3; 117*8ccd4a63SDavid du Colombier } 118*8ccd4a63SDavid du Colombier 119*8ccd4a63SDavid du Colombier int 120*8ccd4a63SDavid du Colombier runelen(long c) 121*8ccd4a63SDavid du Colombier { 122*8ccd4a63SDavid du Colombier Rune rune; 123*8ccd4a63SDavid du Colombier char str[10]; 124*8ccd4a63SDavid du Colombier 125*8ccd4a63SDavid du Colombier rune = c; 126*8ccd4a63SDavid du Colombier return runetochar(str, &rune); 127*8ccd4a63SDavid du Colombier } 128*8ccd4a63SDavid du Colombier 129*8ccd4a63SDavid du Colombier int 130*8ccd4a63SDavid du Colombier runenlen(Rune *r, int nrune) 131*8ccd4a63SDavid du Colombier { 132*8ccd4a63SDavid du Colombier int nb, c; 133*8ccd4a63SDavid du Colombier 134*8ccd4a63SDavid du Colombier nb = 0; 135*8ccd4a63SDavid du Colombier while(nrune--) { 136*8ccd4a63SDavid du Colombier c = *r++; 137*8ccd4a63SDavid du Colombier if(c <= Rune1) 138*8ccd4a63SDavid du Colombier nb++; 139*8ccd4a63SDavid du Colombier else 140*8ccd4a63SDavid du Colombier if(c <= Rune2) 141*8ccd4a63SDavid du Colombier nb += 2; 142*8ccd4a63SDavid du Colombier else 143*8ccd4a63SDavid du Colombier nb += 3; 144*8ccd4a63SDavid du Colombier } 145*8ccd4a63SDavid du Colombier return nb; 146*8ccd4a63SDavid du Colombier } 147*8ccd4a63SDavid du Colombier 148*8ccd4a63SDavid du Colombier int 149*8ccd4a63SDavid du Colombier fullrune(char *str, int n) 150*8ccd4a63SDavid du Colombier { 151*8ccd4a63SDavid du Colombier int c; 152*8ccd4a63SDavid du Colombier 153*8ccd4a63SDavid du Colombier if(n > 0) { 154*8ccd4a63SDavid du Colombier c = *(uchar*)str; 155*8ccd4a63SDavid du Colombier if(c < Tx) 156*8ccd4a63SDavid du Colombier return 1; 157*8ccd4a63SDavid du Colombier if(n > 1) 158*8ccd4a63SDavid du Colombier if(c < T3 || n > 2) 159*8ccd4a63SDavid du Colombier return 1; 160*8ccd4a63SDavid du Colombier } 161*8ccd4a63SDavid du Colombier return 0; 162*8ccd4a63SDavid du Colombier } 163