source: icGREP/icgrep-devel/icgrep/UCD/PropertyObjects.cpp @ 5672

Last change on this file since 5672 was 5672, checked in by cameron, 22 months ago

StringOverride? properties (simple case conversion vs full case conversion)

File size: 10.4 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters, Inc.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters, Inc.
5 *
6 */
7
8#include "PropertyObjects.h"
9#include "PropertyObjectTable.h"
10#include <llvm/Support/Casting.h>
11#include <algorithm>
12#include <assert.h>
13#include <sstream>
14#include <llvm/Support/raw_ostream.h>
15#include <llvm/Support/ErrorHandling.h>
16using namespace llvm;
17
18namespace UCD {
19
20std::string canonicalize_value_name(const std::string & prop_or_val) {
21    std::locale loc;
22    std::stringstream s;
23
24    for (char c : prop_or_val) {
25        if ((c != '_') && (c != ' ') && (c != '-')) {
26            s << std::tolower(c, loc);
27        }
28    }
29    return s.str();
30}
31
32const std::string & PropertyObject::GetPropertyValueGrepString() {
33    llvm::report_fatal_error("Property Value Grep String unsupported.");
34}
35
36const UnicodeSet PropertyObject::GetCodepointSet(const std::string &) {
37    llvm::report_fatal_error("Property " + UCD::property_full_name[the_property] + " unsupported.");
38}
39
40const UnicodeSet EnumeratedPropertyObject::GetCodepointSet(const std::string & value_spec) {
41    const int property_enum_val = GetPropertyValueEnumCode(value_spec);
42    if (property_enum_val < 0) {
43        llvm::report_fatal_error("Enumerated Property " + UCD::property_full_name[the_property] + ": unknown value: " + value_spec);
44    }
45    return GetCodepointSet(property_enum_val);
46}
47
48const UnicodeSet & EnumeratedPropertyObject::GetCodepointSet(const int property_enum_val) const {
49    assert (property_enum_val >= 0);
50    return *(property_value_sets[property_enum_val]);
51}
52
53std::vector<UnicodeSet> & EnumeratedPropertyObject::GetEnumerationBasisSets() {
54    // Return the previously computed vector of basis sets, if it exists.
55    if (LLVM_UNLIKELY(enumeration_basis_sets.empty())) {
56        // Otherwise compute and return.
57        // Basis set i is the set of all codepoints whose numerical enumeration code e
58        // has bit i set, i.e., (e >> i) & 1 == 1.
59        unsigned basis_count = 1;
60        while ((1UL << basis_count) < independent_enum_count) {
61            basis_count++;
62        }
63        for (unsigned i = 0; i < basis_count; i++) {
64            enumeration_basis_sets.push_back(UnicodeSet());
65            for (unsigned e = 0; e < independent_enum_count; e++) {
66                if (((e >> i) & 1UL) == 0) {
67                    enumeration_basis_sets[i] = enumeration_basis_sets[i] + *property_value_sets[e];
68                }
69            }
70        }
71    }
72    return enumeration_basis_sets;
73}
74
75const std::string & EnumeratedPropertyObject::GetPropertyValueGrepString() {
76    if (LLVM_LIKELY(mPropertyValueGrepString.empty())) {
77        std::stringstream buffer;
78        for (unsigned i = 0; i != property_value_full_names.size(); i++) {
79            buffer << property_value_full_names[i] + "\n";
80        }
81        for (unsigned i = 0; i != property_value_enum_names.size(); i++) {
82            if (property_value_enum_names[i] == property_value_full_names[i]) continue;
83            buffer << property_value_enum_names[i] + "\n";
84        }
85        for (auto & a : property_value_aliases) {
86            buffer << a.first + "\n";
87        }
88        mPropertyValueGrepString = buffer.str();
89    }
90    return mPropertyValueGrepString;
91}
92
93int EnumeratedPropertyObject::GetPropertyValueEnumCode(const std::string & value_spec) {
94    // The canonical full names are not stored in the precomputed alias map,
95    // to save space in the executable.   Add them if the property is used.
96    if (uninitialized) {
97        for (unsigned i = 0; i != property_value_full_names.size(); i++) {
98            property_value_aliases.insert({canonicalize_value_name(property_value_full_names[i]), i});
99        }
100        for (unsigned i = 0; i != property_value_enum_names.size(); i++) {
101            property_value_aliases.insert({canonicalize_value_name(property_value_enum_names[i]), i});
102        }
103        uninitialized = false;
104    }
105    const auto valit = property_value_aliases.find(canonicalize_value_name(value_spec));
106    if (valit == property_value_aliases.end())
107        return -1;
108    return valit->second;
109}
110
111PropertyObject::iterator ExtensionPropertyObject::begin() const {
112    if (const auto * obj = dyn_cast<EnumeratedPropertyObject>(property_object_table[base_property])) {
113        return obj->begin();
114    }
115    llvm::report_fatal_error("Iterators unsupported for this type of PropertyObject.");
116}
117
118PropertyObject::iterator ExtensionPropertyObject::end() const {
119    if (const auto * obj = dyn_cast<EnumeratedPropertyObject>(property_object_table[base_property])) {
120        return obj->end();
121    }
122    llvm::report_fatal_error("Iterators unsupported for this type of PropertyObject.");
123}
124
125const UnicodeSet ExtensionPropertyObject::GetCodepointSet(const std::string & value_spec) {
126    int property_enum_val = GetPropertyValueEnumCode(value_spec);
127    if (property_enum_val == -1) {
128        llvm::report_fatal_error("Extension Property " + UCD::property_full_name[the_property] +  ": unknown value: " + value_spec);
129    }
130    return GetCodepointSet(property_enum_val);
131}
132
133const UnicodeSet & ExtensionPropertyObject::GetCodepointSet(const int property_enum_val) const {
134    assert (property_enum_val >= 0);
135    return *(property_value_sets[property_enum_val]);
136}
137
138int ExtensionPropertyObject::GetPropertyValueEnumCode(const std::string & value_spec) {
139    return cast<EnumeratedPropertyObject>(property_object_table[base_property])->GetPropertyValueEnumCode(value_spec);
140}
141
142const std::string & ExtensionPropertyObject::GetPropertyValueGrepString() {
143    return property_object_table[base_property]->GetPropertyValueGrepString();
144}
145
146const UnicodeSet BinaryPropertyObject::GetCodepointSet(const std::string & value_spec) {
147    int property_enum_val = Binary_ns::Y;
148    if (value_spec.length() != 0) {
149        auto valit = Binary_ns::aliases_only_map.find(canonicalize_value_name(value_spec));
150        if (valit == Binary_ns::aliases_only_map.end()) {
151            llvm::report_fatal_error("Binary Property " + UCD::property_full_name[the_property] +  ": bad value: " + value_spec);
152        }
153        property_enum_val = valit->second;
154    }
155    return GetCodepointSet(property_enum_val);
156}
157
158const UnicodeSet & BinaryPropertyObject::GetCodepointSet(const int property_enum_val) {
159    if (property_enum_val == Binary_ns::Y) {
160        return mY;
161    }
162    if (mNoUninitialized) {
163        mN = ~mY;
164        mNoUninitialized = false;
165    }
166    return mN;
167}
168
169const std::string & BinaryPropertyObject::GetPropertyValueGrepString() {
170    if (mPropertyValueGrepString.empty()) {
171        std::stringstream buffer;
172        for (const auto & prop : Binary_ns::aliases_only_map) {
173            buffer << std::get<0>(prop) + "\n";
174        }
175        mPropertyValueGrepString = buffer.str();
176    }
177    return mPropertyValueGrepString;
178}
179   
180const unsigned firstCodepointLengthAndVal(const std::string & s, codepoint_t & cp) {
181    size_t lgth = s.length();
182    if (lgth == 0) return 0;
183    unsigned char s0 = s[0];
184    cp = static_cast<codepoint_t>(s0);
185    if (s0 < 0x80) return 1;
186    if (lgth == 1) return 0;  // invalid UTF-8
187    cp = ((cp & 0x1F) << 6) | (s[1] & 0x3F);
188    if ((s0 >= 0xC2) && (s0 <= 0xDF)) return 2;
189    if (lgth == 2) return 0;  // invalid UTF-8
190    cp = ((cp & 0x3FFF) << 6) | (s[2] & 0x3F);
191    if ((s0 >= 0xE0) && (s0 <= 0xEF)) return 3;
192    if (lgth == 3) return 0;  // invalid UTF-8
193    cp = ((cp & 0x7FFF) << 6) | (s[3] & 0x3F);
194    if ((s0 >= 0xF0) && (s0 <= 0xF4)) return 4;
195    return 0;
196}
197   
198const UnicodeSet NumericPropertyObject::GetCodepointSet(const std::string & value_spec) {
199    if (value_spec == "NaN") return mNaNCodepointSet;
200    else {
201        UnicodeSet result_set;
202        unsigned val_bytes = value_spec.length();
203        const char * value_str = value_spec.c_str();
204        const char * search_str = mStringBuffer;
205        unsigned buffer_line = 0;
206        while (buffer_line < mExplicitCps.size()) {
207            const char * eol = strchr(search_str, '\n');
208            unsigned len = eol - search_str;
209            if ((len == val_bytes) && (memcmp(search_str, value_str, len) == 0)) {
210                result_set.insert(mExplicitCps[buffer_line]);
211            }
212            buffer_line++;
213            search_str = eol+1;
214        }
215        return result_set;
216    }
217}
218
219const UnicodeSet StringPropertyObject::GetCodepointSet(const std::string & value_spec) {
220    if (value_spec == "") return mNullCodepointSet;
221    else {
222        UnicodeSet result_set;
223        unsigned val_bytes = value_spec.length();
224        codepoint_t cp;
225        if (val_bytes == firstCodepointLengthAndVal(value_spec, cp)) {
226            if (mSelfCodepointSet.contains(cp)) {
227                result_set.insert(cp);
228            }
229        }
230        const char * value_str = value_spec.c_str();
231        const char * search_str = mStringBuffer;
232        unsigned buffer_line = 0;
233        while (buffer_line < mExplicitCps.size()) {
234            const char * eol = strchr(search_str, '\n');
235            unsigned len = eol - search_str;
236            if ((len == val_bytes) && (memcmp(search_str, value_str, len) == 0)) {
237                result_set.insert(mExplicitCps[buffer_line]);
238            }
239            buffer_line++;
240            search_str = eol+1;
241        }
242        return result_set;
243    }
244}
245
246const UnicodeSet StringOverridePropertyObject::GetCodepointSet(const std::string & value_spec) {
247    // First step: get the codepoints from the base object and then remove any overridden ones.
248    UnicodeSet result_set = mBaseObject.GetCodepointSet(value_spec) - mOverriddenSet;
249    // Now search for additional entries.
250    unsigned val_bytes = value_spec.length();
251    const char * value_str = value_spec.c_str();
252    const char * search_str = mStringBuffer;
253    unsigned buffer_line = 0;
254    while (buffer_line < mExplicitCps.size()) {
255        const char * eol = strchr(search_str, '\n');
256        unsigned len = eol - search_str;
257        if ((len == val_bytes) && (memcmp(search_str, value_str, len) == 0)) {
258            result_set.insert(mExplicitCps[buffer_line]);
259        }
260        buffer_line++;
261        search_str = eol+1;
262    }
263    return result_set;
264}
265   
266const std::string & ObsoletePropertyObject::GetPropertyValueGrepString() {
267    llvm::report_fatal_error("Property " + UCD::property_full_name[the_property] + " is obsolete.");
268}
269
270const UnicodeSet ObsoletePropertyObject::GetCodepointSet(const std::string &) {
271    llvm::report_fatal_error("Property " + UCD::property_full_name[the_property] + " is obsolete.");
272}
273
274
275}
Note: See TracBrowser for help on using the repository browser.