update to 0.19.7
[platform/upstream/fribidi.git] / charset / fribidi-char-sets-utf8.c
1 /* FriBidi
2  * fribidi-char-sets-utf8.c - UTF-8 character set conversion routines
3  *
4  * $Id: fribidi-char-sets-utf8.c,v 1.3 2005-07-30 09:06:28 behdad Exp $
5  * $Author: behdad $
6  * $Date: 2005-07-30 09:06:28 $
7  * $Revision: 1.3 $
8  * $Source: /home/behdad/src/fdo/fribidi/togit/git/../fribidi/fribidi2/charset/fribidi-char-sets-utf8.c,v $
9  *
10  * Authors:
11  *   Behdad Esfahbod, 2001, 2002, 2004
12  *   Dov Grobgeld, 1999, 2000
13  *
14  * Copyright (C) 2004 Sharif FarsiWeb, Inc
15  * Copyright (C) 2001,2002 Behdad Esfahbod
16  * Copyright (C) 1999,2000 Dov Grobgeld
17  * 
18  * This library is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU Lesser General Public
20  * License as published by the Free Software Foundation; either
21  * version 2.1 of the License, or (at your option) any later version.
22  * 
23  * This library is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * Lesser General Public License for more details.
27  * 
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with this library, in a file named COPYING; if not, write to the
30  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
31  * Boston, MA 02110-1301, USA
32  * 
33  * For licensing issues, contact <license@farsiweb.info>.
34  */
35
36 #include <common.h>
37
38 #include <fribidi-char-sets-utf8.h>
39
40 #include <fribidi-unicode.h>
41
42 FriBidiStrIndex
43 fribidi_utf8_to_unicode (
44   /* input */
45   const char *ss,
46   FriBidiStrIndex len,
47   /* output */
48   FriBidiChar *us
49 )
50 {
51   FriBidiStrIndex length;
52   const unsigned char *s = (unsigned const char *) ss;
53   const unsigned char *t = s;
54
55   length = 0;
56   while ((FriBidiStrIndex) (s - t) < len)
57     {
58       register unsigned char ch = *s;
59       if (ch <= 0x7f)           /* one byte */
60         {
61           *us++ = *s++;
62         }
63       else if (ch <= 0xdf)      /* 2 byte */
64         {
65           *us++ = ((*s & 0x1f) << 6) + (*(s + 1) & 0x3f);
66           s += 2;
67         }
68       else if (ch <= 0xef)      /* 3 byte */
69         {
70           *us++ =
71             ((int) (*s & 0x0f) << 12) +
72             ((*(s + 1) & 0x3f) << 6) + (*(s + 2) & 0x3f);
73           s += 3;
74         }
75       else                     /* 4 byte */
76       {
77           *us++ =
78             ((int) (*s & 0x07) << 18) +
79             ((*(s + 1) & 0x3f) << 12) +
80             ((*(s + 2) & 0x3f) << 6) +
81             ((*(s + 3) & 0x3f) << 0);
82           s += 4;
83       }
84       length++;
85     }
86   return (length);
87 }
88
89 FriBidiStrIndex
90 fribidi_unicode_to_utf8 (
91   /* input */
92   const FriBidiChar *us,
93   FriBidiStrIndex len,
94   /* output */
95   char *ss
96 )
97 {
98   FriBidiStrIndex i;
99   unsigned char *s = (unsigned char *) ss;
100   unsigned char *t = s;
101
102   for (i = 0; i < len; i++)
103     {
104       FriBidiChar mychar = us[i];
105       if (mychar <= 0x7F)
106         {                       /* 7 sig bits */
107           *t++ = mychar;
108         }
109       else if (mychar <= 0x7FF)
110         {                       /* 11 sig bits */
111           *t++ = 0xC0 | (unsigned char) (mychar >> 6);  /* upper 5 bits */
112           *t++ = 0x80 | (unsigned char) (mychar & 0x3F);        /* lower 6 bits */
113         }
114       else if (mychar <= 0xFFFF)
115         {                       /* 16 sig bits */
116           *t++ = 0xE0 | (unsigned char) (mychar >> 12); /* upper 4 bits */
117           *t++ = 0x80 | (unsigned char) ((mychar >> 6) & 0x3F); /* next 6 bits */
118           *t++ = 0x80 | (unsigned char) (mychar & 0x3F);        /* lowest 6 bits */
119         }
120       else if (mychar < FRIBIDI_UNICODE_CHARS)
121         {                       /* 21 sig bits */
122           *t++ = 0xF0 | (unsigned char) ((mychar >> 18) & 0x07);        /* upper 3 bits */
123           *t++ = 0x80 | (unsigned char) ((mychar >> 12) & 0x3F);        /* next 6 bits */
124           *t++ = 0x80 | (unsigned char) ((mychar >> 6) & 0x3F); /* next 6 bits */
125           *t++ = 0x80 | (unsigned char) (mychar & 0x3F);        /* lowest 6 bits */
126         }
127     }
128   *t = 0;
129
130   return (t - s);
131 }
132
133 /* Editor directions:
134  * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
135  */