Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * The authors of this software are Rob Pike and Ken Thompson.
  3.  *              Copyright (c) 2002 by Lucent Technologies.
  4.  * Permission to use, copy, modify, and distribute this software for any
  5.  * purpose without fee is hereby granted, provided that this entire notice
  6.  * is included in all copies of any software which is or includes a copy
  7.  * or modification of this software and in all copies of the supporting
  8.  * documentation for such software.
  9.  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
  10.  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
  11.  * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
  12.  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
  13.  */
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #include "utf.h"
  18.  
  19. typedef unsigned char uchar;
  20.  
  21. enum
  22. {
  23.         Bit1    = 7,
  24.         Bitx    = 6,
  25.         Bit2    = 5,
  26.         Bit3    = 4,
  27.         Bit4    = 3,
  28.         Bit5    = 2,
  29.  
  30.         T1      = ((1<<(Bit1+1))-1) ^ 0xFF,     /* 0000 0000 */
  31.         Tx      = ((1<<(Bitx+1))-1) ^ 0xFF,     /* 1000 0000 */
  32.         T2      = ((1<<(Bit2+1))-1) ^ 0xFF,     /* 1100 0000 */
  33.         T3      = ((1<<(Bit3+1))-1) ^ 0xFF,     /* 1110 0000 */
  34.         T4      = ((1<<(Bit4+1))-1) ^ 0xFF,     /* 1111 0000 */
  35.         T5      = ((1<<(Bit5+1))-1) ^ 0xFF,     /* 1111 1000 */
  36.  
  37.         Rune1   = (1<<(Bit1+0*Bitx))-1,         /* 0000 0000 0000 0000 0111 1111 */
  38.         Rune2   = (1<<(Bit2+1*Bitx))-1,         /* 0000 0000 0000 0111 1111 1111 */
  39.         Rune3   = (1<<(Bit3+2*Bitx))-1,         /* 0000 0000 1111 1111 1111 1111 */
  40.         Rune4   = (1<<(Bit4+3*Bitx))-1,         /* 0001 1111 1111 1111 1111 1111 */
  41.  
  42.         Maskx   = (1<<Bitx)-1,                  /* 0011 1111 */
  43.         Testx   = Maskx ^ 0xFF,                 /* 1100 0000 */
  44.  
  45.         Bad     = Runeerror
  46. };
  47.  
  48. int
  49. chartorune(Rune *rune, const char *str)
  50. {
  51.         int c, c1, c2, c3;
  52.         int l;
  53.  
  54.         /* overlong null character */
  55.         if((uchar)str[0] == 0xc0 && (uchar)str[1] == 0x80) {
  56.                 *rune = 0;
  57.                 return 2;
  58.         }
  59.  
  60.         /*
  61.          * one character sequence
  62.          *      00000-0007F => T1
  63.          */
  64.         c = *(uchar*)str;
  65.         if(c < Tx) {
  66.                 *rune = c;
  67.                 return 1;
  68.         }
  69.  
  70.         /*
  71.          * two character sequence
  72.          *      0080-07FF => T2 Tx
  73.          */
  74.         c1 = *(uchar*)(str+1) ^ Tx;
  75.         if(c1 & Testx)
  76.                 goto bad;
  77.         if(c < T3) {
  78.                 if(c < T2)
  79.                         goto bad;
  80.                 l = ((c << Bitx) | c1) & Rune2;
  81.                 if(l <= Rune1)
  82.                         goto bad;
  83.                 *rune = l;
  84.                 return 2;
  85.         }
  86.  
  87.         /*
  88.          * three character sequence
  89.          *      0800-FFFF => T3 Tx Tx
  90.          */
  91.         c2 = *(uchar*)(str+2) ^ Tx;
  92.         if(c2 & Testx)
  93.                 goto bad;
  94.         if(c < T4) {
  95.                 l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
  96.                 if(l <= Rune2)
  97.                         goto bad;
  98.                 *rune = l;
  99.                 return 3;
  100.         }
  101.  
  102.         /*
  103.          * four character sequence
  104.          *      10000-10FFFF => T4 Tx Tx Tx
  105.          */
  106.         if(UTFmax >= 4) {
  107.                 c3 = *(uchar*)(str+3) ^ Tx;
  108.                 if(c3 & Testx)
  109.                         goto bad;
  110.                 if(c < T5) {
  111.                         l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
  112.                         if(l <= Rune3)
  113.                                 goto bad;
  114.                         if(l > Runemax)
  115.                                 goto bad;
  116.                         *rune = l;
  117.                         return 4;
  118.                 }
  119.         }
  120.  
  121.         /*
  122.          * bad decoding
  123.          */
  124. bad:
  125.         *rune = Bad;
  126.         return 1;
  127. }
  128.  
  129. int
  130. runetochar(char *str, const Rune *rune)
  131. {
  132.         int c = *rune;
  133.  
  134.         /* overlong null character */
  135.         if (c == 0) {
  136.                 str[0] = (char)0xc0;
  137.                 str[1] = (char)0x80;
  138.                 return 2;
  139.         }
  140.  
  141.         /*
  142.          * one character sequence
  143.          *      00000-0007F => 00-7F
  144.          */
  145.         if(c <= Rune1) {
  146.                 str[0] = c;
  147.                 return 1;
  148.         }
  149.  
  150.         /*
  151.          * two character sequence
  152.          *      00080-007FF => T2 Tx
  153.          */
  154.         if(c <= Rune2) {
  155.                 str[0] = T2 | (c >> 1*Bitx);
  156.                 str[1] = Tx | (c & Maskx);
  157.                 return 2;
  158.         }
  159.  
  160.         /*
  161.          * three character sequence
  162.          *      00800-0FFFF => T3 Tx Tx
  163.          */
  164.         if(c > Runemax)
  165.                 c = Runeerror;
  166.         if(c <= Rune3) {
  167.                 str[0] = T3 |  (c >> 2*Bitx);
  168.                 str[1] = Tx | ((c >> 1*Bitx) & Maskx);
  169.                 str[2] = Tx |  (c & Maskx);
  170.                 return 3;
  171.         }
  172.  
  173.         /*
  174.          * four character sequence
  175.          *      010000-1FFFFF => T4 Tx Tx Tx
  176.          */
  177.         str[0] = T4 |  (c >> 3*Bitx);
  178.         str[1] = Tx | ((c >> 2*Bitx) & Maskx);
  179.         str[2] = Tx | ((c >> 1*Bitx) & Maskx);
  180.         str[3] = Tx |  (c & Maskx);
  181.         return 4;
  182. }
  183.  
  184. int
  185. runelen(int c)
  186. {
  187.         Rune rune;
  188.         char str[10];
  189.  
  190.         rune = c;
  191.         return runetochar(str, &rune);
  192. }
  193.  
  194. int
  195. utflen(const char *s)
  196. {
  197.         int c;
  198.         int n;
  199.         Rune rune;
  200.  
  201.         n = 0;
  202.         for(;;) {
  203.                 c = *(uchar*)s;
  204.                 if(c < Runeself) {
  205.                         if(c == 0)
  206.                                 return n;
  207.                         s++;
  208.                 } else
  209.                         s += chartorune(&rune, s);
  210.                 n++;
  211.         }
  212. }
  213.