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

Last change on this file since 5668 was 5668, checked in by cameron, 21 months ago

PropertyObject? restructuring - remove Miscellaneous and Codepoint objects, add Obsolete

File size: 8.8 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 StringPropertyObject::GetCodepointSet(const std::string & value_spec) {
199    if (value_spec == "") return mNullCodepointSet;
200    else {
201        UnicodeSet result_set;
202        unsigned val_bytes = value_spec.length();
203        codepoint_t cp;
204        if (val_bytes == firstCodepointLengthAndVal(value_spec, cp)) {
205            if (mSelfCodepointSet.contains(cp)) {
206                result_set.insert(cp);
207            }
208        }
209        const char * value_str = value_spec.c_str();
210        const char * search_str = mStringBuffer;
211        unsigned buffer_line = 0;
212        while (buffer_line < mExplicitCps.size()) {
213            const char * eol = strchr(search_str, '\n');
214            unsigned len = eol - search_str;
215            if ((len == val_bytes) && (memcmp(search_str, value_str, len) == 0)) {
216                result_set.insert(mExplicitCps[buffer_line]);
217            }
218            buffer_line++;
219            search_str = eol+1;
220        }
221        return result_set;
222    }
223}
224
225const std::string & ObsoletePropertyObject::GetPropertyValueGrepString() {
226    llvm::report_fatal_error("Property " + UCD::property_full_name[the_property] + " is obsolete.");
227}
228
229const UnicodeSet ObsoletePropertyObject::GetCodepointSet(const std::string &) {
230    llvm::report_fatal_error("Property " + UCD::property_full_name[the_property] + " is obsolete.");
231}
232
233
234}
Note: See TracBrowser for help on using the repository browser.