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

Last change on this file since 4529 was 4519, checked in by nmedfort, 5 years ago

Extra _ moved from char seperator to initial label.

File size: 4.5 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}
Note: See TracBrowser for help on using the repository browser.