13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier 43e12c5d1SDavid du Colombier enum 53e12c5d1SDavid du Colombier { 63e12c5d1SDavid du Colombier Bit1 = 7, 73e12c5d1SDavid du Colombier Bitx = 6, 83e12c5d1SDavid du Colombier Bit2 = 5, 93e12c5d1SDavid du Colombier Bit3 = 4, 103e12c5d1SDavid du Colombier Bit4 = 3, 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ 133e12c5d1SDavid du Colombier Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ 143e12c5d1SDavid du Colombier T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ 153e12c5d1SDavid du Colombier T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ 163e12c5d1SDavid du Colombier T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ 193e12c5d1SDavid du Colombier Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ 203e12c5d1SDavid du Colombier Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier Maskx = (1<<Bitx)-1, /* 0011 1111 */ 233e12c5d1SDavid du Colombier Testx = Maskx ^ 0xFF, /* 1100 0000 */ 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier Bad = Runeerror, 263e12c5d1SDavid du Colombier }; 273e12c5d1SDavid du Colombier 283e12c5d1SDavid du Colombier int 293e12c5d1SDavid du Colombier chartorune(Rune *rune, char *str) 303e12c5d1SDavid du Colombier { 313e12c5d1SDavid du Colombier int c, c1, c2; 323e12c5d1SDavid du Colombier long l; 333e12c5d1SDavid du Colombier 343e12c5d1SDavid du Colombier /* 353e12c5d1SDavid du Colombier * one character sequence 363e12c5d1SDavid du Colombier * 00000-0007F => T1 373e12c5d1SDavid du Colombier */ 383e12c5d1SDavid du Colombier c = *(uchar*)str; 393e12c5d1SDavid du Colombier if(c < Tx) { 403e12c5d1SDavid du Colombier *rune = c; 413e12c5d1SDavid du Colombier return 1; 423e12c5d1SDavid du Colombier } 433e12c5d1SDavid du Colombier 443e12c5d1SDavid du Colombier /* 453e12c5d1SDavid du Colombier * two character sequence 463e12c5d1SDavid du Colombier * 0080-07FF => T2 Tx 473e12c5d1SDavid du Colombier */ 483e12c5d1SDavid du Colombier c1 = *(uchar*)(str+1) ^ Tx; 493e12c5d1SDavid du Colombier if(c1 & Testx) 503e12c5d1SDavid du Colombier goto bad; 513e12c5d1SDavid du Colombier if(c < T3) { 523e12c5d1SDavid du Colombier if(c < T2) 533e12c5d1SDavid du Colombier goto bad; 543e12c5d1SDavid du Colombier l = ((c << Bitx) | c1) & Rune2; 553e12c5d1SDavid du Colombier if(l <= Rune1) 563e12c5d1SDavid du Colombier goto bad; 573e12c5d1SDavid du Colombier *rune = l; 583e12c5d1SDavid du Colombier return 2; 593e12c5d1SDavid du Colombier } 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier /* 623e12c5d1SDavid du Colombier * three character sequence 633e12c5d1SDavid du Colombier * 0800-FFFF => T3 Tx Tx 643e12c5d1SDavid du Colombier */ 653e12c5d1SDavid du Colombier c2 = *(uchar*)(str+2) ^ Tx; 663e12c5d1SDavid du Colombier if(c2 & Testx) 673e12c5d1SDavid du Colombier goto bad; 683e12c5d1SDavid du Colombier if(c < T4) { 693e12c5d1SDavid du Colombier l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; 703e12c5d1SDavid du Colombier if(l <= Rune2) 713e12c5d1SDavid du Colombier goto bad; 723e12c5d1SDavid du Colombier *rune = l; 733e12c5d1SDavid du Colombier return 3; 743e12c5d1SDavid du Colombier } 753e12c5d1SDavid du Colombier 763e12c5d1SDavid du Colombier /* 773e12c5d1SDavid du Colombier * bad decoding 783e12c5d1SDavid du Colombier */ 793e12c5d1SDavid du Colombier bad: 803e12c5d1SDavid du Colombier *rune = Bad; 813e12c5d1SDavid du Colombier return 1; 823e12c5d1SDavid du Colombier } 833e12c5d1SDavid du Colombier 843e12c5d1SDavid du Colombier int 853e12c5d1SDavid du Colombier runetochar(char *str, Rune *rune) 863e12c5d1SDavid du Colombier { 873e12c5d1SDavid du Colombier long c; 883e12c5d1SDavid du Colombier 893e12c5d1SDavid du Colombier /* 903e12c5d1SDavid du Colombier * one character sequence 913e12c5d1SDavid du Colombier * 00000-0007F => 00-7F 923e12c5d1SDavid du Colombier */ 933e12c5d1SDavid du Colombier c = *rune; 943e12c5d1SDavid du Colombier if(c <= Rune1) { 953e12c5d1SDavid du Colombier str[0] = c; 963e12c5d1SDavid du Colombier return 1; 973e12c5d1SDavid du Colombier } 983e12c5d1SDavid du Colombier 993e12c5d1SDavid du Colombier /* 1003e12c5d1SDavid du Colombier * two character sequence 1013e12c5d1SDavid du Colombier * 0080-07FF => T2 Tx 1023e12c5d1SDavid du Colombier */ 1033e12c5d1SDavid du Colombier if(c <= Rune2) { 1043e12c5d1SDavid du Colombier str[0] = T2 | (c >> 1*Bitx); 1053e12c5d1SDavid du Colombier str[1] = Tx | (c & Maskx); 1063e12c5d1SDavid du Colombier return 2; 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier /* 1103e12c5d1SDavid du Colombier * three character sequence 1113e12c5d1SDavid du Colombier * 0800-FFFF => T3 Tx Tx 1123e12c5d1SDavid du Colombier */ 1133e12c5d1SDavid du Colombier str[0] = T3 | (c >> 2*Bitx); 1143e12c5d1SDavid du Colombier str[1] = Tx | ((c >> 1*Bitx) & Maskx); 1153e12c5d1SDavid du Colombier str[2] = Tx | (c & Maskx); 1163e12c5d1SDavid du Colombier return 3; 1173e12c5d1SDavid du Colombier } 1183e12c5d1SDavid du Colombier 1193e12c5d1SDavid du Colombier int 1203e12c5d1SDavid du Colombier runelen(long c) 1213e12c5d1SDavid du Colombier { 1223e12c5d1SDavid du Colombier Rune rune; 1233e12c5d1SDavid du Colombier char str[10]; 1243e12c5d1SDavid du Colombier 1253e12c5d1SDavid du Colombier rune = c; 1263e12c5d1SDavid du Colombier return runetochar(str, &rune); 1273e12c5d1SDavid du Colombier } 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier int 130*7dd7cddfSDavid du Colombier runenlen(Rune *r, int nrune) 131*7dd7cddfSDavid du Colombier { 132*7dd7cddfSDavid du Colombier int nb, c; 133*7dd7cddfSDavid du Colombier 134*7dd7cddfSDavid du Colombier nb = 0; 135*7dd7cddfSDavid du Colombier while(nrune--) { 136*7dd7cddfSDavid du Colombier c = *r++; 137*7dd7cddfSDavid du Colombier if(c <= Rune1) 138*7dd7cddfSDavid du Colombier nb++; 139*7dd7cddfSDavid du Colombier else 140*7dd7cddfSDavid du Colombier if(c <= Rune2) 141*7dd7cddfSDavid du Colombier nb += 2; 142*7dd7cddfSDavid du Colombier else 143*7dd7cddfSDavid du Colombier nb += 3; 144*7dd7cddfSDavid du Colombier } 145*7dd7cddfSDavid du Colombier return nb; 146*7dd7cddfSDavid du Colombier } 147*7dd7cddfSDavid du Colombier 148*7dd7cddfSDavid du Colombier int 1493e12c5d1SDavid du Colombier fullrune(char *str, int n) 1503e12c5d1SDavid du Colombier { 1513e12c5d1SDavid du Colombier int c; 1523e12c5d1SDavid du Colombier 1533e12c5d1SDavid du Colombier if(n > 0) { 1543e12c5d1SDavid du Colombier c = *(uchar*)str; 1553e12c5d1SDavid du Colombier if(c < Tx) 1563e12c5d1SDavid du Colombier return 1; 1573e12c5d1SDavid du Colombier if(n > 1) 1583e12c5d1SDavid du Colombier if(c < T3 || n > 2) 1593e12c5d1SDavid du Colombier return 1; 1603e12c5d1SDavid du Colombier } 1613e12c5d1SDavid du Colombier return 0; 1623e12c5d1SDavid du Colombier } 163