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

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

Progress on multi-target UCD compiler.

File size: 4.8 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::IntervalAllocator 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 interval_t & i : cc2->mSparseCharSet) {
19        insert_range(lo_codepoint(i), hi_codepoint(i));
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) && (max_codepoint() >= 0x80)) {
33        name << "BC";
34    } else {
35        name << "CC";
36    }
37    char separator = '_';
38    for (const interval_t & i : mSparseCharSet) {
39        name << separator;
40        if (lo_codepoint(i) == hi_codepoint(i)) {
41            name << lo_codepoint(i);
42        }
43        else {
44            name << lo_codepoint(i) << '_' << hi_codepoint(i);
45        }
46        separator = ',';
47    }
48    return name.str();
49}
50
51void CC::insert_range(const codepoint_t lo, const codepoint_t hi) {
52    for (auto i = mSparseCharSet.begin(); i != mSparseCharSet.end(); ) {
53        if (hi < lo_codepoint(i) - 1) {
54            mSparseCharSet.emplace(i, lo, hi);
55            return;
56        } else if (lo > hi_codepoint(i) + 1) {
57            ++i;
58        } else {
59            // ranges overlap; expand the range to include the overlapp
60            lo_codepoint(i) = std::min(lo_codepoint(i), lo);
61            hi_codepoint(i) = std::max(hi_codepoint(i), hi);
62            // Test whether the new hi code point of this range touches the subsequent
63            // interval. If so extend it over that one and remove it from the list.
64            for (auto j = i + 1; j != mSparseCharSet.end(); ) {
65                if (LLVM_LIKELY(hi_codepoint(i) + 1 < lo_codepoint(j))) {
66                    break;
67                }
68                hi_codepoint(i) = std::max(hi_codepoint(i), hi_codepoint(j));
69                j = mSparseCharSet.erase(j);
70            }
71            return;
72        }
73    }
74    mSparseCharSet.emplace_back(lo, hi);
75}
76
77void CC::remove_range(const codepoint_t lo, const codepoint_t hi) {
78    for (auto i = mSparseCharSet.begin(); i != mSparseCharSet.end(); ) {
79        if (lo > hi_codepoint(i) + 1) {
80            ++i;
81        }
82        else if (hi < lo_codepoint(i) - 1) {
83            break;
84        }
85        else if (lo <= lo_codepoint(i) && hi >= hi_codepoint(i)) {
86            i = mSparseCharSet.erase(i);
87        }
88        else if (lo <= lo_codepoint(i)) {
89            lo_codepoint(i) = hi + 1;
90            break;
91        }
92        else if (hi >= hi_codepoint(i)) {
93            hi_codepoint(i) = lo - 1;
94            ++i;
95        }
96        else {         
97            mSparseCharSet.emplace(++i, hi + 1, hi_codepoint(i));
98            hi_codepoint(i) = lo - 1;
99            break;
100        }
101    }
102}
103
104CC * subtractCC(const CC * a, const CC * b) {
105    CC * diff = makeCC();
106    auto i = a->cbegin();
107    const auto i_end = a->cend();
108    auto j = b->cbegin();
109    const auto j_end = b->cend();
110    while (i != i_end && j != j_end) {
111        if (hi_codepoint(j) < lo_codepoint(i)) {
112            ++j;
113        }
114        else { // test whether the intervals overlap
115            if (lo_codepoint(i) < lo_codepoint(j)) {
116                diff->insert_range(lo_codepoint(i), std::min(lo_codepoint(j) - 1, hi_codepoint(i)));
117            }
118            if (hi_codepoint(i) > hi_codepoint(j)) {
119                diff->insert_range(std::max(hi_codepoint(j) + 1, lo_codepoint(i)), hi_codepoint(i));
120            }
121            ++i;
122        }
123    }
124    for (; i != i_end; ++i) {
125        diff->insert_range(lo_codepoint(i), hi_codepoint(i));
126    }
127    return diff;
128}
129   
130CC * intersectCC(const CC * a, const CC * b) {
131    CC * isect = makeCC();
132    auto ai = a->cbegin();
133    const auto ai_end = a->cend();
134    auto bi = b->cbegin();
135    const auto bi_end = b->cend();
136    while (ai != ai_end && bi != bi_end) {
137        if (hi_codepoint(ai) < lo_codepoint(bi)) {
138            ++ai;
139        }
140        else if (hi_codepoint(bi) < lo_codepoint(ai)) {
141            ++bi;
142        }
143        else {
144            isect->insert_range(std::max(lo_codepoint(ai), lo_codepoint(bi)), std::min(hi_codepoint(ai), hi_codepoint(bi)));
145            if (hi_codepoint(ai) < hi_codepoint(bi)) {
146                ++ai;
147            }
148            else {
149                ++bi;
150            }
151        }
152    }
153    return isect;
154}
155   
156CC * caseInsensitize(const CC * cc) {
157    CC * cci = makeCC();
158    for (const interval_t & i : *cc) {
159        caseInsensitiveInsertRange(cci, lo_codepoint(i), hi_codepoint(i));
160    }
161    return cci;
162}
163   
164}
Note: See TracBrowser for help on using the repository browser.