source: icGREP/icgrep-devel/icgrep/re/re_cc.cpp @ 4611

Last change on this file since 4611 was 4611, checked in by nmedfort, 4 years ago

Temporary check-in

File size: 7.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 "re_cc.h"
8#include <llvm/Support/Compiler.h>
9#include <UCD/CaseFolding_txt.h>
10#include <sstream>
11
12namespace re {
13CC::CharSetAllocator CC::mCharSetAllocator;
14
15CC::CC(const CC * cc1, const CC * cc2)
16: RE(ClassTypeId::CC)
17, mSparseCharSet(cc1->cbegin(), cc1->cend(), mCharSetAllocator) {
18    for (const CharSetItem & i : cc2->mSparseCharSet) {
19        insert_range(i.lo_codepoint, i.hi_codepoint);
20    }
21}
22
23CC::CC(const CC & cc)
24: RE(ClassTypeId::CC)
25, mSparseCharSet(cc.cbegin(), cc.cend(), mCharSetAllocator) {
26
27}
28
29std::string CC::canonicalName(const CC_type type) const {
30    std::stringstream name;
31    name << std::hex;
32    if ((type == ByteClass) && (mSparseCharSet.back().hi_codepoint >= 0x80)) {
33      name << "BC_";
34    }
35    else {
36        name << "CC_";
37    }
38    char separator = '_';
39    for (const CharSetItem & i : mSparseCharSet) {
40        name << separator;
41        if (i.lo_codepoint == i.hi_codepoint) {
42            name << i.lo_codepoint;
43        }
44        else {
45            name << i.lo_codepoint << '_' << i.hi_codepoint;
46        }
47    }
48    return name.str();
49}
50
51CodePointType CC::max_codepoint() {
52    return mSparseCharSet.size() == 0 ? 0 : mSparseCharSet.back().hi_codepoint;
53}
54
55void CC::insert_range(const CodePointType lo_codepoint, const CodePointType hi_codepoint) {
56    CharSetItem item(lo_codepoint, hi_codepoint);
57    for (auto i = mSparseCharSet.begin(); i != mSparseCharSet.end(); ) {
58        CharSetItem & range = *i;
59        if (item.hi_codepoint < range.lo_codepoint - 1) {
60            mSparseCharSet.insert(i, item);
61            return;
62        }
63        else if (item.lo_codepoint > range.hi_codepoint + 1) {
64            ++i;
65        }
66        else {
67            // ranges overlap; expand the range to include the prior one and
68            // remove the old one from the list
69            range.lo_codepoint = std::min(range.lo_codepoint, item.lo_codepoint);
70            range.hi_codepoint = std::max(range.hi_codepoint, item.hi_codepoint);
71            return;
72        }
73    }
74    mSparseCharSet.push_back(item);
75}
76
77void CC::remove_range(const CodePointType lo_codepoint, const CodePointType hi_codepoint) {
78    for (auto i = mSparseCharSet.begin(); i != mSparseCharSet.end(); ) {
79        CharSetItem & range = *i;
80        if (lo_codepoint > range.hi_codepoint + 1) {
81            ++i;
82        }
83        else if (hi_codepoint < range.lo_codepoint - 1) {
84            break;
85        }
86        else if (lo_codepoint <= range.lo_codepoint && hi_codepoint >= range.hi_codepoint) {
87            i = mSparseCharSet.erase(i);
88        }
89        else if (lo_codepoint <= range.lo_codepoint) {
90            range.lo_codepoint = hi_codepoint + 1;
91            break;
92        }
93        else if (hi_codepoint >= range.hi_codepoint) {
94            range.hi_codepoint = lo_codepoint - 1;
95            ++i;
96        }
97        else {
98            CharSetItem item(hi_codepoint + 1, range.hi_codepoint);
99            range.hi_codepoint = lo_codepoint - 1;
100            mSparseCharSet.insert(++i, std::move(item));
101            break;
102        }
103    }
104}
105
106CC * subtractCC(const CC * cc1, const CC * cc2) {
107    CC * diff = makeCC();
108    for (const CharSetItem & i : cc1->mSparseCharSet) {
109        diff->insert_range(i.lo_codepoint, i.hi_codepoint);
110    }
111    for (const CharSetItem & i : cc2->mSparseCharSet) {
112        diff->remove_range(i.lo_codepoint, i.hi_codepoint);
113    }
114    return diff;
115}
116   
117CC * intersectCC(const CC * a, const CC * b) {
118    CC * isect = makeCC();
119    auto ai = a->cbegin();
120    const auto ai_end = a->cend();
121    auto bi = b->cbegin();
122    const auto bi_end = b->cend();
123    while (ai != ai_end && bi != bi_end) {
124        const CharSetItem & ra = *ai;
125        const CharSetItem & rb = *bi;
126        if (ra.hi_codepoint < rb.lo_codepoint) {
127            ++ai;
128            continue;
129        }
130        else if (rb.hi_codepoint < ra.lo_codepoint) {
131            ++bi;
132            continue;
133        }
134        isect->insert_range(std::max(ra.lo_codepoint, rb.lo_codepoint), std::min(ra.hi_codepoint, rb.hi_codepoint));
135        if (ra.hi_codepoint < rb.hi_codepoint) ++ai; 
136        else ++bi;
137    }
138    return isect;
139}
140   
141CC * caseInsensitize(const CC * cc) {
142    CC * cci = makeCC();
143    for (auto i = cc->cbegin(); i != cc->cend(); i++) {
144        caseInsensitiveInsertRange(cci, i->lo_codepoint, i->hi_codepoint);
145    }
146    return cci;
147}
148
149/** ------------------------------------------------------------------------------------------------------------- *
150 * @brief rangeIntersect
151 * @param cc
152 * @param lo
153 * @param hi
154 ** ------------------------------------------------------------------------------------------------------------- */
155CC * rangeIntersect(const CC * cc, const CodePointType lo, const CodePointType hi) {
156    assert ("cc cannot be null" && cc);
157    CC * intersect = makeCC();
158    for (const auto & p : *cc) {
159        if ((p.lo_codepoint <= hi) && (p.hi_codepoint >= lo)) {
160            intersect->insert_range(std::max(lo, p.lo_codepoint), std::min(hi, p.hi_codepoint));
161        }
162    }
163    return intersect;
164}
165
166/** ------------------------------------------------------------------------------------------------------------- *
167 * @brief rangeGaps
168 * @param cc
169 * @param lo
170 * @param hi
171 ** ------------------------------------------------------------------------------------------------------------- */
172CC * rangeGaps(const CC * cc, const CodePointType lo, const CodePointType hi) {
173    assert ("cc cannot be null" && cc);
174    CC * gaps = makeCC();
175    CodePointType cp = lo;
176    if (cp < hi) {
177        auto i = cc->cbegin(), end = cc->cend();
178        for (; i != end && cp < hi; ++i) {
179            if (i->hi_codepoint < cp) {
180                continue;
181            }
182            else if (i->lo_codepoint > cp) {
183                gaps->insert_range(cp, i->lo_codepoint - 1);
184            }
185            cp = i->hi_codepoint + 1;
186        }
187        if (cp < hi) {
188            gaps->insert_range(cp, hi);
189        }
190    }
191    return gaps;
192}
193
194/** ------------------------------------------------------------------------------------------------------------- *
195 * @brief outerRanges
196 * @param cc
197 ** ------------------------------------------------------------------------------------------------------------- */
198CC * outerRanges(const CC * cc) {
199    assert ("cc cannot be null" && cc);
200    CC * ranges = makeCC();
201    auto i = cc->cbegin();
202    const auto end = cc->cend();
203    for (auto j = i; ++j != end; ) {
204        if (j->hi_codepoint > i->hi_codepoint) {
205            ranges->insert_range(i->lo_codepoint, i->hi_codepoint);
206            i = j;
207        }
208    }
209    return ranges;
210}
211
212/** ------------------------------------------------------------------------------------------------------------- *
213 * @brief innerRanges
214 * @param cc
215 ** ------------------------------------------------------------------------------------------------------------- */
216CC * innerRanges(const CC * cc) {
217    assert ("cc cannot be null" && cc);
218    CC * ranges = makeCC();
219    auto i = cc->cbegin();
220    const auto end = cc->cend();
221    for (auto j = i; ++j != end; ) {
222        if (j->hi_codepoint <= i->hi_codepoint) {
223            ranges->insert_range(j->lo_codepoint, j->hi_codepoint);
224        }
225        else {
226            i = j;
227        }
228    }
229    return ranges;
230}
231   
232}
Note: See TracBrowser for help on using the repository browser.