License conversion from Flora to Apache 2.0
[platform/core/uifw/dali-core.git] / dali / internal / event / text / utf8-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/text/utf8-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 namespace Dali
25 {
26
27 namespace Internal
28 {
29
30 size_t UTF8SequenceLength(const unsigned char leadByte)
31 {
32   size_t length = 0;
33
34   if ((leadByte & 0x80) == 0 )          //ASCII character (lead bit zero)
35   {
36     length = 1;
37   }
38   else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx
39   {
40     length = 2;
41   }
42   else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx
43   {
44     length = 3;
45   }
46   else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx
47   {
48     length = 4;
49   }
50   else
51   {
52     DALI_LOG_WARNING("Unrecognized lead byte  %c\n", leadByte);
53   }
54
55   return length;
56 }
57
58 uint32_t UTF8Read(const unsigned char* utf8Data, const size_t sequenceLength)
59 {
60   uint32_t code = 0;
61
62   if (sequenceLength == 1)
63   {
64     code = *utf8Data;
65   }
66   else if (sequenceLength == 2)
67   {
68     code = *utf8Data++ & 0x1f;
69     code <<= 6;
70     code |= *utf8Data  & 0x3f;
71   }
72   else if (sequenceLength == 3)
73   {
74     code =  *utf8Data++ & 0x0f;
75     code <<= 6;
76     code |= *utf8Data++ & 0x3f;
77     code <<= 6;
78     code |= *utf8Data   & 0x3f;
79   }
80   else if (sequenceLength == 4)
81   {
82     code =  *utf8Data++ & 0x07;
83     code <<= 6;
84     code |= *utf8Data++ & 0x3f;
85     code <<= 6;
86     code |= *utf8Data++ & 0x3f;
87     code <<= 6;
88     code |= *utf8Data   & 0x3f;
89   }
90
91   return code;
92 }
93
94 size_t UTF8Write(const uint32_t code, unsigned char* utf8Data)
95 {
96   size_t sequenceLength = 0;
97   if (code < 0x80u)
98   {
99     *utf8Data = code;
100     sequenceLength = 1;
101   }
102   else if (code < 0x800u)
103   {
104     *utf8Data++ = static_cast<uint8_t>( code >> 6)          | 0xc0; // lead byte for 2 byte sequence
105     *utf8Data   = static_cast<uint8_t>( code        & 0x3f) | 0x80; // continuation byte
106     sequenceLength = 2;
107   }
108   else if (code < 0x10000u)
109   {
110     *utf8Data++ = static_cast<uint8_t>( code >> 12)         | 0xe0; // lead byte for 2 byte sequence
111     *utf8Data++ = static_cast<uint8_t>((code >> 6)  & 0x3f) | 0x80; // continuation byte
112     *utf8Data   = static_cast<uint8_t>( code        & 0x3f) | 0x80; // continuation byte
113     sequenceLength = 3;
114   }
115   else if (code < 0x200000u)
116   {
117     *utf8Data++ = static_cast<uint8_t>( code >> 18)         | 0xf0; // lead byte for 2 byte sequence
118     *utf8Data++ = static_cast<uint8_t>((code >> 12) & 0x3f) | 0x80; // continuation byte
119     *utf8Data++ = static_cast<uint8_t>((code >> 6)  & 0x3f) | 0x80; // continuation byte
120     *utf8Data   = static_cast<uint8_t>( code        & 0x3f) | 0x80; // continuation byte
121     sequenceLength = 4;
122   }
123
124   return sequenceLength;
125 }
126
127 size_t UTF8Tokenize(const unsigned char* utf8Data, const size_t utf8DataLength, TextArray& tokens)
128 {
129   size_t dataLength = utf8DataLength;
130
131   while (dataLength)
132   {
133     uint32_t code;
134     size_t sequenceLength = UTF8SequenceLength(*utf8Data);
135
136     if (!sequenceLength)
137     {
138       break;
139     }
140
141     if (sequenceLength > dataLength)
142     {
143       // utf8 data error
144       break;
145     }
146
147     code = UTF8Read(utf8Data, sequenceLength);
148     tokens.push_back(code);
149
150     utf8Data += sequenceLength;
151     dataLength -= sequenceLength;
152   }
153   return tokens.size();
154 }
155
156 } // namespace Internal
157
158 } // namespace Dali