iso2022_cn.h

Upload User: yingmei828
Upload Date: 2007-01-01
Package Size: 1646k
Code Size: 7k
Development Platform: Unix_Linux
  1. /*
  2.  * ISO-2022-CN
  3.  */
  4. /* Specification: RFC 1922 */
  5. #define ESC 0x1b
  6. #define SO  0x0e
  7. #define SI  0x0f
  8. /*
  9.  * The state is composed of one of the following values
  10.  */
  11. #define STATE_ASCII          0
  12. #define STATE_TWOBYTE        1
  13. /*
  14.  * and one of the following values, << 8
  15.  */
  16. #define STATE2_NONE                   0
  17. #define STATE2_DESIGNATED_GB2312      1
  18. #define STATE2_DESIGNATED_CNS11643_1  2
  19. /*
  20.  * and one of the following values, << 16
  21.  */
  22. #define STATE3_NONE                   0
  23. #define STATE3_DESIGNATED_CNS11643_2  1
  24. #define SPLIT_STATE 
  25.   unsigned int state1 = state & 0xff, state2 = (state >> 8) & 0xff, state3 = state >> 16
  26. #define COMBINE_STATE 
  27.   state = (state3 << 16) | (state2 << 8) | state1
  28. static int
  29. iso2022_cn_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  30. {
  31.   state_t state = conv->istate;
  32.   SPLIT_STATE;
  33.   int count = 0;
  34.   unsigned char c;
  35.   for (;;) {
  36.     c = *s;
  37.     if (c == ESC) {
  38.       if (n < count+4)
  39.         goto none;
  40.       if (s[1] == '$') {
  41.         if (s[2] == ')') {
  42.           if (s[3] == 'A') {
  43.             state2 = STATE2_DESIGNATED_GB2312;
  44.             s += 4; count += 4;
  45.             if (n < count+1)
  46.               goto none;
  47.             continue;
  48.           }
  49.           if (s[3] == 'G') {
  50.             state2 = STATE2_DESIGNATED_CNS11643_1;
  51.             s += 4; count += 4;
  52.             if (n < count+1)
  53.               goto none;
  54.             continue;
  55.           }
  56.         }
  57.         if (s[2] == '*') {
  58.           if (s[3] == 'H') {
  59.             state3 = STATE3_DESIGNATED_CNS11643_2;
  60.             s += 4; count += 4;
  61.             if (n < count+1)
  62.               goto none;
  63.             continue;
  64.           }
  65.         }
  66.       }
  67.       if (s[1] == 'N') {
  68.         switch (state3) {
  69.           case STATE3_NONE:
  70.             return RET_ILSEQ;
  71.           case STATE3_DESIGNATED_CNS11643_2:
  72.             if (s[2] < 0x80 && s[3] < 0x80) {
  73.               int ret = cns11643_2_mbtowc(conv,pwc,s+2,2);
  74.               if (ret == RET_ILSEQ)
  75.                 return RET_ILSEQ;
  76.               if (ret != 2) abort();
  77.               COMBINE_STATE;
  78.               conv->istate = state;
  79.               return count+4;
  80.             } else
  81.               return RET_ILSEQ;
  82.           default: abort();
  83.         }
  84.       }
  85.       return RET_ILSEQ;
  86.     }
  87.     if (c == SO) {
  88.       if (state2 != STATE2_DESIGNATED_GB2312 && state2 != STATE2_DESIGNATED_CNS11643_1)
  89.         return RET_ILSEQ;
  90.       state1 = STATE_TWOBYTE;
  91.       s++; count++;
  92.       if (n < count+1)
  93.         goto none;
  94.       continue;
  95.     }
  96.     if (c == SI) {
  97.       state1 = STATE_ASCII;
  98.       s++; count++;
  99.       if (n < count+1)
  100.         goto none;
  101.       continue;
  102.     }
  103.     break;
  104.   }
  105.   switch (state1) {
  106.     case STATE_ASCII:
  107.       if (c < 0x80) {
  108.         int ret = ascii_mbtowc(conv,pwc,s,1);
  109.         if (ret == RET_ILSEQ)
  110.           return RET_ILSEQ;
  111.         if (ret != 1) abort();
  112.         if (*pwc == 0x000a || *pwc == 0x000d) {
  113.           state2 = STATE2_NONE; state3 = STATE3_NONE;
  114.         }
  115.         COMBINE_STATE;
  116.         conv->istate = state;
  117.         return count+1;
  118.       } else
  119.         return RET_ILSEQ;
  120.     case STATE_TWOBYTE:
  121.       if (n < count+2)
  122.         goto none;
  123.       if (s[0] < 0x80 && s[1] < 0x80) {
  124.         int ret;
  125.         switch (state2) {
  126.           case STATE2_NONE:
  127.             return RET_ILSEQ;
  128.           case STATE2_DESIGNATED_GB2312:
  129.             ret = gb2312_mbtowc(conv,pwc,s,2); break;
  130.           case STATE2_DESIGNATED_CNS11643_1:
  131.             ret = cns11643_1_mbtowc(conv,pwc,s,2); break;
  132.           default: abort();
  133.         }
  134.         if (ret == RET_ILSEQ)
  135.           return RET_ILSEQ;
  136.         if (ret != 2) abort();
  137.         COMBINE_STATE;
  138.         conv->istate = state;
  139.         return count+2;
  140.       } else
  141.         return RET_ILSEQ;
  142.     default: abort();
  143.   }
  144. none:
  145.   COMBINE_STATE;
  146.   conv->istate = state;
  147.   return RET_TOOFEW(count);
  148. }
  149. static int
  150. iso2022_cn_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)
  151. {
  152.   state_t state = conv->ostate;
  153.   SPLIT_STATE;
  154.   unsigned char buf[3];
  155.   int ret;
  156.   /* Try ASCII. */
  157.   ret = ascii_wctomb(conv,buf,wc,1);
  158.   if (ret != RET_ILSEQ) {
  159.     if (ret != 1) abort();
  160.     if (buf[0] < 0x80) {
  161.       int count = (state1 == STATE_ASCII ? 1 : 2);
  162.       if (n < count)
  163.         return RET_TOOSMALL;
  164.       if (state1 != STATE_ASCII) {
  165.         r[0] = SI;
  166.         r += 1;
  167.         state1 = STATE_ASCII;
  168.       }
  169.       r[0] = buf[0];
  170.       if (wc == 0x000a || wc == 0x000d) {
  171.         state2 = STATE2_NONE; state3 = STATE3_NONE;
  172.       }
  173.       COMBINE_STATE;
  174.       conv->ostate = state;
  175.       return count;
  176.     }
  177.   }
  178.   /* Try GB 2312-1980. */
  179.   ret = gb2312_wctomb(conv,buf,wc,2);
  180.   if (ret != RET_ILSEQ) {
  181.     if (ret != 2) abort();
  182.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  183.       int count = (state2 == STATE2_DESIGNATED_GB2312 ? 0 : 4) + (state1 == STATE_TWOBYTE ? 0 : 1) + 2;
  184.       if (n < count)
  185.         return RET_TOOSMALL;
  186.       if (state2 != STATE2_DESIGNATED_GB2312) {
  187.         r[0] = ESC;
  188.         r[1] = '$';
  189.         r[2] = ')';
  190.         r[3] = 'A';
  191.         r += 4;
  192.         state2 = STATE2_DESIGNATED_GB2312;
  193.       }
  194.       if (state1 != STATE_TWOBYTE) {
  195.         r[0] = SO;
  196.         r += 1;
  197.         state1 = STATE_TWOBYTE;
  198.       }
  199.       r[0] = buf[0];
  200.       r[1] = buf[1];
  201.       COMBINE_STATE;
  202.       conv->ostate = state;
  203.       return count;
  204.     }
  205.   }
  206.   ret = cns11643_wctomb(conv,buf,wc,3);
  207.   if (ret != RET_ILSEQ) {
  208.     if (ret != 3) abort();
  209.     /* Try CNS 11643-1992 Plane 1. */
  210.     if (buf[0] == 0 && buf[1] < 0x80 && buf[2] < 0x80) {
  211.       int count = (state2 == STATE2_DESIGNATED_CNS11643_1 ? 0 : 4) + (state1 == STATE_TWOBYTE ? 0 : 1) + 2;
  212.       if (n < count)
  213.         return RET_TOOSMALL;
  214.       if (state2 != STATE2_DESIGNATED_CNS11643_1) {
  215.         r[0] = ESC;
  216.         r[1] = '$';
  217.         r[2] = ')';
  218.         r[3] = 'G';
  219.         r += 4;
  220.         state2 = STATE2_DESIGNATED_CNS11643_1;
  221.       }
  222.       if (state1 != STATE_TWOBYTE) {
  223.         r[0] = SO;
  224.         r += 1;
  225.         state1 = STATE_TWOBYTE;
  226.       }
  227.       r[0] = buf[1];
  228.       r[1] = buf[2];
  229.       COMBINE_STATE;
  230.       conv->ostate = state;
  231.       return count;
  232.     }
  233.     /* Try CNS 11643-1992 Plane 2. */
  234.     if (buf[0] == 1 && buf[1] < 0x80 && buf[2] < 0x80) {
  235.       int count = (state3 == STATE3_DESIGNATED_CNS11643_2 ? 0 : 4) + 4;
  236.       if (n < count)
  237.         return RET_TOOSMALL;
  238.       if (state3 != STATE3_DESIGNATED_CNS11643_2) {
  239.         r[0] = ESC;
  240.         r[1] = '$';
  241.         r[2] = '*';
  242.         r[3] = 'H';
  243.         r += 4;
  244.         state3 = STATE3_DESIGNATED_CNS11643_2;
  245.       }
  246.       r[0] = ESC;
  247.       r[1] = 'N';
  248.       r[2] = buf[1];
  249.       r[3] = buf[2];
  250.       COMBINE_STATE;
  251.       conv->ostate = state;
  252.       return count;
  253.     }
  254.   }
  255.   return RET_ILSEQ;
  256. }
  257. static int
  258. iso2022_cn_reset (conv_t conv, unsigned char *r, int n)
  259. {
  260.   state_t state = conv->ostate;
  261.   SPLIT_STATE;
  262.   (void)state2;
  263.   (void)state3;
  264.   if (state1 != STATE_ASCII) {
  265.     if (n < 1)
  266.       return RET_TOOSMALL;
  267.     r[0] = SI;
  268.     /* conv->ostate = 0; will be done by the caller */
  269.     return 1;
  270.   } else
  271.     return 0;
  272. }
  273. #undef COMBINE_STATE
  274. #undef SPLIT_STATE
  275. #undef STATE3_DESIGNATED_CNS11643_2
  276. #undef STATE3_NONE
  277. #undef STATE2_DESIGNATED_CNS11643_1
  278. #undef STATE2_DESIGNATED_GB2312
  279. #undef STATE2_NONE
  280. #undef STATE_TWOBYTE
  281. #undef STATE_ASCII