source: icGREP/icgrep-devel/icgrep/utf8_encoder.cpp @ 3998

Last change on this file since 3998 was 3998, checked in by cameron, 5 years ago

Preserve negated attribute

File size: 6.3 KB
Line 
1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "utf8_encoder.h"
8
9
10RE* UTF8_Encoder::toUTF8(RE* re)
11{
12    RE* retVal = 0;
13
14    if (Alt* re_alt = dynamic_cast<Alt*>(re))
15    {
16        std::list<RE*> re_list;
17        std::list<RE*>::reverse_iterator rit = re_alt->GetREList()->rbegin();
18
19        for (rit = re_alt->GetREList()->rbegin(); rit != re_alt->GetREList()->rend(); ++rit)
20        {
21            re_list.push_back(toUTF8(*rit));
22        }
23
24        retVal = new Alt(&re_list);
25    }
26    else if (Seq* re_seq = dynamic_cast<Seq*>(re))
27    {
28
29        std::list<RE*> re_list;
30        std::list<RE*>::iterator it;
31
32        for (it = re_seq->GetREList()->begin(); it != re_seq->GetREList()->end(); ++it)
33        {
34            //If this is a previously encoded Unicode byte sequence.
35            if (re_seq->getType() == Seq::Byte)
36            {
37                if (CC* seq_cc = dynamic_cast<CC*>(*it))
38                {
39                    CharSetItem item = seq_cc->getItems().front();
40                    re_list.push_front(new CC(item.lo_codepoint));
41                }
42            }
43            else
44            {
45                re_list.push_front(toUTF8(*it));
46            }
47        }
48
49        Seq* new_seq = new Seq(&re_list);
50        new_seq->setType(re_seq->getType());
51        retVal = new_seq;
52    }
53    else if (Rep* re_rep = dynamic_cast<Rep*>(re))
54    {
55        retVal = new Rep(toUTF8(re_rep->getRE()), re_rep->getLB(), re_rep->getUB());
56    }
57    else if (CC* re_cc = dynamic_cast<CC*>(re))
58    { 
59        if (re_cc->getItems().size() == 1)
60        {
61            retVal = rangeToUTF8(re_cc->getItems().front());
62        }
63        else if (re_cc->getItems().size() > 1)
64        {           
65            std::list<RE*> re_list;
66            for (int i = 0; i < re_cc->getItems().size(); i++)
67            {
68                re_list.push_back(rangeToUTF8(re_cc->getItems().at(i)));
69            }
70            retVal = RE_Simplifier::mkAlt(&re_list);
71            //retVal = new Alt(&re_list);
72        }
73    }
74    else if (Name* re_name = dynamic_cast<Name*>(re))
75    {
76        Name* name = new Name(re_name->getName());
77        name->setType(re_name->getType());
78        name->setNegated(re_name->isNegated());   // TODO:  Hide this in the re_name module.
79        retVal = name;
80    }
81    else if (Start* re_start = dynamic_cast<Start*>(re))
82    {
83        retVal = new Start();
84    }
85    else if (End* re_end = dynamic_cast<End*>(re))
86    {
87        retVal = new End();
88    }
89
90    return retVal;
91}
92
93RE* UTF8_Encoder::rangeToUTF8(CharSetItem item)
94{
95    int u8len_lo = u8len(item.lo_codepoint);
96    int u8len_hi = u8len(item.hi_codepoint);
97
98    if (u8len_lo < u8len_hi)
99    {
100        int m = max_of_u8len(u8len_lo);
101        Alt* alt = new Alt();
102
103        CharSetItem lo_item;
104        lo_item.lo_codepoint = item.lo_codepoint;
105        lo_item.hi_codepoint = m;
106        alt->AddREListItem(rangeToUTF8(lo_item));
107        CharSetItem hi_item;
108        hi_item.lo_codepoint = m + 1;
109        hi_item.hi_codepoint = item.hi_codepoint;
110        alt->AddREListItem(rangeToUTF8(hi_item));
111
112        return alt;
113    }
114    else
115    {
116        return rangeToUTF8_helper(item.lo_codepoint, item.hi_codepoint, 1, u8len_hi);
117    }
118}
119
120RE* UTF8_Encoder::rangeToUTF8_helper(int lo, int hi, int n, int hlen)
121{
122    int hbyte = u8byte(hi, n);
123    int lbyte = u8byte(lo, n);
124
125    if (n == hlen)
126    {
127        return makeByteRange(lbyte, hbyte);
128    }
129    else if (hbyte == lbyte)
130    {
131        Seq* seq = new Seq();
132        seq->setType((u8Prefix(hbyte) ? Seq::Byte : Seq::Normal));
133        seq->AddREListItem(makeByteClass(hbyte));
134        seq->AddREListItem(rangeToUTF8_helper(lo, hi, n+1, hlen));
135        return seq;
136    }
137    else
138    {
139        int suffix_mask = (1 << ((hlen - n) * 6)) - 1;
140
141        if ((hi & suffix_mask) != suffix_mask)
142        {
143            int hi_floor = (~suffix_mask) & hi;
144
145            Alt* alt = new Alt();
146            alt->AddREListItem(rangeToUTF8_helper(hi_floor, hi, n, hlen));
147            alt->AddREListItem(rangeToUTF8_helper(lo, hi_floor - 1, n, hlen));
148            return alt;
149        }
150        else if ((lo & suffix_mask) != 0)
151        {
152            int low_ceil = lo | suffix_mask;
153
154            Alt* alt = new Alt();
155            alt->AddREListItem(rangeToUTF8_helper(low_ceil + 1, hi, n, hlen));
156            alt->AddREListItem(rangeToUTF8_helper(lo, low_ceil, n, hlen));
157            return alt;
158        }
159        else
160        {
161            Seq* seq = new Seq();
162            seq->AddREListItem(makeByteRange(lbyte, hbyte));
163            seq->AddREListItem(rangeToUTF8_helper(lo, hi, n + 1, hlen));
164            return seq;
165        }
166    }
167}
168
169bool UTF8_Encoder::u8Prefix(int cp)
170{
171    bool retVal = false;
172
173    if ((cp >= 0xC2) && (cp <= 0xDF))
174    {
175        retVal = true;
176    }
177    else if ((cp >= 0xE0) && (cp <= 0xEF))
178    {
179        retVal = true;
180    }
181    else if ((cp >= 0xF0) && (cp <= 0xF4))
182    {
183        retVal = true;
184    }
185
186    return retVal;
187}
188
189CC* UTF8_Encoder::makeByteRange(int lo, int hi)
190{
191    return new CC(lo, hi);
192}
193
194CC* UTF8_Encoder::makeByteClass(int byteval)
195{
196    return new CC(byteval, byteval);
197}
198
199int UTF8_Encoder::u8byte(int codepoint, int n)
200{
201    int retVal = 0;
202
203    int len = u8len(codepoint);
204
205    if (n == 1)
206    {
207        if (len == 1)
208        {
209            retVal = codepoint;
210        }
211        else if (len == 2)
212        {
213            retVal = 0xC0 | (codepoint >> 6);
214        }
215        else if (len == 3)
216        {
217            retVal = 0xE0 | (codepoint >> 12);
218        }
219        else
220        {
221            retVal = 0xF0 | (codepoint >> 18);
222        }
223    }
224    else
225    {
226        retVal = 0x80 | ((codepoint >> (6 * (len - n))) & 0x3F);
227    }
228
229    return retVal;
230}
231
232int UTF8_Encoder::u8len(int cp)
233{
234    if (cp <= 0x7F)
235    {
236        return 1;
237    }
238    else if (cp <= 0x7FF)
239    {
240        return 2;
241    }
242    else if (cp <= 0xFFFF)
243    {
244        return 3;
245    }
246    else
247    {
248        return 4;
249    }
250}
251
252int UTF8_Encoder::max_of_u8len(int lgth)
253{
254    if (lgth == 1)
255    {
256        return 0x7F;
257    }
258    else if (lgth == 2)
259    {
260        return 0x7FF;
261    }
262    else if (lgth == 3)
263    {
264        return 0xFFFF;
265    }
266    else if (lgth == 4)
267    {
268        return 0x10FFFF;
269    }
270    else
271    {
272        return -1;
273    }
274}
275
Note: See TracBrowser for help on using the repository browser.