source: icGREP/icgrep-devel/UCD-scripts/UCD_properties.py @ 6134

Last change on this file since 6134 was 6134, checked in by cameron, 11 months ago

GetStringValue? method for string properties

File size: 30.0 KB
Line 
1#
2# UCD_properties.py - parsing Unicode Character Database (UCD) files
3# and generating C headers for property data using a compact bitset
4# representation.
5#
6# Robert D. Cameron
7# January 2, 2015
8#
9# Licensed under Open Software License 3.0.
10#
11#
12import string, os.path
13from UCD_parser import *
14from UCD_property_objects import *
15
16PropertyAliases_template = r"""
17namespace UCD {
18    enum property_t {
19        %s};
20    const static std::vector<std::string> property_enum_name = {
21        %s};
22    const static std::vector<std::string> property_full_name = {
23        %s};
24    static std::unordered_map<std::string, int> alias_map {{
25        %s}};
26}
27"""
28
29EnumeratedProperty_template = r"""
30    namespace %s_ns {
31        enum value_t {
32            %s};
33        const static std::vector<std::string> enum_names = {
34            %s};
35        const static std::vector<std::string> value_names = {
36            %s};
37        static std::unordered_map<std::string, int> aliases_only_map {{
38            %s}};
39    }
40"""
41
42def emit_string_property(f, property_code, null_set, reflexive_set, cp_value_map):
43    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
44        /** Code Point Ranges for ${prop_enum} mapping to <none>
45        ${null_set_ranges}**/
46       
47        ${null_set_value}
48
49        /** Code Point Ranges for ${prop_enum} mapping to <codepoint>
50        ${reflexive_set_ranges}**/
51       
52        ${reflexive_set_value}
53
54        const static std::vector<unsigned> buffer_offsets = {
55        ${buffer_offsets}};
56        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
57
58        const static std::vector<codepoint_t> defined_cps{
59        ${explicitly_defined_cps}};
60        static StringPropertyObject property_object(${prop_enum},
61                                                    std::move(null_codepoint_set),
62                                                    std::move(reflexive_set),
63                                                    static_cast<const char *>(string_buffer),
64                                                    std::move(buffer_offsets),
65                                                    std::move(defined_cps));
66    }
67""")
68    cps = sorted(cp_value_map.keys())
69    string_buffer = ""
70    buffer_offsets = [0]
71    for cp in cps: 
72        string_buffer += cp_value_map[cp] + "\n"
73        buffer_offsets.append(len(string_buffer.encode("utf-8")))
74    buffer_length = buffer_offsets[-1]
75    f.write(s.substitute(prop_enum = property_code,
76                         prop_enum_up = property_code.upper(),
77                         string_buffer = string_buffer,
78                         buffer_offsets = cformat.multiline_fill(['%i' % o for o in buffer_offsets], ',', 8),
79                         allocation_length = (buffer_length + 255) & -256,
80                         null_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(null_set)], ',', 8),
81                         null_set_value = null_set.generate("null_codepoint_set", 8),
82                         reflexive_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(reflexive_set)], ',', 8),
83                         reflexive_set_value = reflexive_set.generate("reflexive_set", 8),
84                         explicitly_defined_cp_count = len(cps),
85                         explicitly_defined_cps = cformat.multiline_fill(['0x%04x' % cp for cp in cps], ',', 8)
86                         ))
87
88def emit_string_override_property(f, property_code, overridden_code, override_set, cp_value_map):
89    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
90        /** Code Point Ranges for ${prop_enum} (possibly overriding values from ${overridden})
91        ${overridden_set_ranges}**/
92
93        ${overridden_set_value}
94
95        const static std::vector<unsigned> buffer_offsets = {
96        ${buffer_offsets}};
97        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
98
99        const static std::vector<codepoint_t> defined_cps{
100        ${explicitly_defined_cps}};
101        static StringOverridePropertyObject property_object(${prop_enum},
102                                                    ${overridden}_ns::property_object,
103                                                    std::move(explicitly_defined_set),
104                                                    static_cast<const char *>(string_buffer),
105                                                    std::move(buffer_offsets),
106                                                    std::move(defined_cps));
107    }
108""")
109    cps = sorted(cp_value_map.keys())
110    string_buffer = ""
111    buffer_offsets = [0]
112    for cp in cps: 
113        string_buffer += cp_value_map[cp] + "\n"
114        buffer_offsets.append(len(string_buffer.encode("utf-8")))
115    buffer_length = buffer_offsets[-1]
116    f.write(s.substitute(prop_enum = property_code,
117                         prop_enum_up = property_code.upper(),
118                         overridden = overridden_code.upper(),
119                         string_buffer = string_buffer,
120                         buffer_offsets = cformat.multiline_fill(['%i' % o for o in buffer_offsets], ',', 8),
121                         allocation_length = (buffer_length + 255) & -256,
122                         overridden_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(override_set)], ',', 8),
123                         overridden_set_value = override_set.generate("explicitly_defined_set", 8),
124                         explicitly_defined_cp_count = len(cps),
125                         explicitly_defined_cps = cformat.multiline_fill(['0x%04x' % cp for cp in cps], ',', 8)
126                         ))
127
128def emit_numeric_property(f, property_code, NaN_set, cp_value_map):
129    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
130        /** Code Point Ranges for ${prop_enum} mapping to NaN
131        ${NaN_set_ranges}**/
132
133        ${NaN_set_value}
134
135        const unsigned buffer_length = ${buffer_length};
136        const static char string_buffer LLVM_ALIGNAS(32) [${allocation_length}] = u8R"__(${string_buffer})__";
137
138        const static std::vector<codepoint_t> defined_cps = {
139        ${explicitly_defined_cps}};
140        static NumericPropertyObject property_object(${prop_enum},
141                                                    std::move(NaN_set),
142                                                    static_cast<const char *>(string_buffer),
143                                                    buffer_length,
144                                                    std::move(defined_cps));
145    }
146""")
147    cps = sorted(cp_value_map.keys())
148    string_buffer = ""
149    for cp in cps: 
150        string_buffer += cp_value_map[cp] + "\n"
151    string_buffer += "NaN\n"  # This inserts the standard default value for strings as the last entry
152    buffer_length = len(string_buffer.encode("utf-8"))
153    f.write(s.substitute(prop_enum = property_code,
154                         prop_enum_up = property_code.upper(),
155                         string_buffer = string_buffer,
156                         buffer_length = buffer_length,
157                         allocation_length = (buffer_length + 255) & -256,
158                         NaN_set_ranges = cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(NaN_set)], ',', 8),
159                         NaN_set_value = NaN_set.generate("NaN_set", 8),
160                         explicitly_defined_cp_count = len(cps),
161                         explicitly_defined_cps = cformat.multiline_fill(['0x%04x' % cp for cp in cps], ',', 8)
162                         ))
163
164
165def emit_binary_property(f, property_code, property_set):
166    f.write("    namespace %s_ns {\n" % property_code.upper())
167    f.write("        /** Code Point Ranges for %s\n        " % property_code)
168    f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(property_set)], ',', 8))
169    f.write("**/\n\n")
170    f.write(property_set.generate("codepoint_set", 8))
171    f.write("        static BinaryPropertyObject property_object{%s, std::move(codepoint_set)};\n    }\n" % property_code)
172
173def emit_enumerated_property(f, property_code, independent_prop_values, prop_values, value_map):
174    f.write("  namespace %s_ns {\n" % property_code.upper())
175    f.write("    const unsigned independent_prop_values = %s;\n" % independent_prop_values)
176    for v in prop_values:
177        f.write("    /** Code Point Ranges for %s\n    " % v)
178        f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(value_map[v])], ',', 4))
179        f.write("**/\n\n")
180        f.write(value_map[v].generate(v.lower() + "_Set", 4))
181    set_list = ['&%s_Set' % v.lower() for v in prop_values]
182    f.write("    static EnumeratedPropertyObject property_object\n")
183    f.write("        {%s,\n" % property_code)
184    f.write("        %s_ns::independent_prop_values,\n" % property_code.upper())
185    f.write("        std::move(%s_ns::enum_names),\n" % property_code.upper())
186    f.write("        std::move(%s_ns::value_names),\n" % property_code.upper())
187    f.write("        std::move(%s_ns::aliases_only_map),{\n" % property_code.upper())
188    f.write("        " + cformat.multiline_fill(set_list, ',', 8))
189    f.write("\n        }};"
190            "\n    }\n")
191
192def emit_Obsolete_property(f, property_code):
193    s = string.Template(r"""    namespace ${prop_enum_up}_ns {
194        static ObsoletePropertyObject property_object(${prop_enum});
195    }
196""")
197    f.write(s.substitute(prop_enum = property_code, prop_enum_up = property_code.upper()))
198
199
200def simple_CaseClosure_map(fold_data):
201   simpleFoldMap = {}
202   for k in fold_data['S'].keys(): simpleFoldMap[k] = int(fold_data['S'][k], 16)
203   for k in fold_data['C'].keys(): simpleFoldMap[k] = int(fold_data['C'][k], 16)
204   cl_map = {}
205   for k in simpleFoldMap.keys():
206      v = simpleFoldMap[k]
207      if not v in cl_map: cl_map[v] = [k]
208      else: cl_map[v].append(k)
209      if not k in cl_map: cl_map[k] = [v]
210      else: cl_map[k].append(v)
211   newEntries = True
212   while newEntries:
213      newEntries = False
214      for k in cl_map.keys():
215         vlist = cl_map[k]
216         for v in vlist:
217            for w in cl_map[v]:
218               if k != w and not k in cl_map[w]:
219                  cl_map[w].append(k)
220                  newEntries = True
221   return cl_map
222
223#
224# Simple case fold map.     
225# The simple case fold map is an ordered list of fold entries each of
226# the form (lo_codepoint, hicodepoint, offset).  Each entry describes
227# the case fold that applies for the consecutive entries in the given
228# codepoint range, according to the following equations. 
229# casefold(x) = x + offset, if ((x - low_codepoint) div offset) mod 2 = 0
230#             = x - offset, if ((x - low_codepoint) div offset) mod 2 = 1
231#
232#
233def caseFoldRangeMap(casemap):
234   foldable = sorted(casemap.keys())
235   entries = []
236   cp = foldable[0]
237   open_entries = [(cp, f - cp) for f in casemap[cp]]
238   last_cp = cp
239   for cp in foldable[1:]:
240      if cp != last_cp + 1:
241         # Close the pending range entries
242         for (cp0, offset) in open_entries:
243            entries.append((cp0, last_cp, offset))
244         open_entries = [(cp, f - cp) for f in casemap[cp]]
245      else:
246         new_open = []
247         projected = []
248         for (cp0, offset) in open_entries:
249            even_odd_offset_group = int(abs(cp - cp0)/ abs(offset)) & 1
250            if even_odd_offset_group == 0: 
251               projected_foldcp = cp + offset
252            else: projected_foldcp = cp - offset
253            if not projected_foldcp in casemap[cp]:
254               entries.append((cp0, last_cp, offset))
255            else:
256               new_open.append((cp0, offset))
257               projected.append(projected_foldcp)
258         open_entries = new_open
259         for f in casemap[cp]:
260            if not f in projected:
261               open_entries.append((cp, f-cp))
262      last_cp = cp
263   # Close the final entries.
264   for (cp0, offset) in open_entries:
265      entries.append((cp0, last_cp, offset))
266   return entries
267
268
269
270def genFoldEntryData(casemap):
271   rMap = caseFoldRangeMap(casemap)
272   individuals = [(m[0],m[0]+m[2]) for m in rMap if m[0] == m[1]]
273   ranges = [m for m in rMap if m[0] != m[1]]
274   last_hi = -1
275   generated = "const FoldEntry foldTable[foldTableSize] = {\n"
276   foldTableSize = 0
277   for (lo, hi, offset) in ranges:
278      if lo != last_hi + 1:
279         pairs = ["{0x%x, 0x%x}" % (m[0], m[1]) for m in individuals if m[0]>last_hi and m[0]< lo]
280         generated += "  {0x%x, 0, {" % (last_hi + 1) + cformat.multiline_fill(pairs) + "}},\n"
281         foldTableSize += 1
282      last_hi = hi
283      pairs = ["{0x%x, 0x%x}" % (m[0], m[1]) for m in individuals if m[0]>=lo and m[0]<= hi]
284      generated += "  {0x%x, %i, {" % (lo, offset) + cformat.multiline_fill(pairs) + "}},\n"
285      foldTableSize += 1
286   if last_hi != 0x10FFFF:
287      pairs = ["{0x%x, 0x%x}" % (m[0], m[1]) for m in individuals if m[0]>last_hi]
288      generated += "  {0x%x, 0, {" % (last_hi + 1) + cformat.multiline_fill(pairs) + "}},\n"
289      foldTableSize += 1
290   generated += "  {0x110000, 0, {}}};"
291   foldTableSize += 1
292   generated = "\nconst int foldTableSize = %s;\n\n" % foldTableSize  + generated
293   return generated
294
295foldDeclarations = r"""
296struct FoldEntry {
297    const UCD::codepoint_t range_lo;
298    const int fold_offset;
299    const std::vector<UCD::interval_t> fold_pairs;
300};
301
302UCD::UnicodeSet caseInsensitize(const UCD::UnicodeSet & cc);
303
304"""
305
306
307class UCD_generator():
308    def __init__(self):
309        self.supported_props = []
310        self.property_data_headers = []
311        self.missing_specs = {}
312        self.binary_properties = {}
313
314    def load_property_name_info(self):
315        (self.property_enum_name_list, self.property_object_map) = parse_PropertyAlias_txt()
316        self.property_lookup_map = getPropertyLookupMap(self.property_object_map)
317        self.full_name_map = {}
318        for p in self.property_enum_name_list:
319            self.full_name_map[p] = self.property_object_map[p].getPropertyFullName()
320
321
322    def generate_PropertyAliases_h(self):
323        f = cformat.open_header_file_for_write('PropertyAliases')
324        cformat.write_imports(f, ["<string>", "<unordered_map>", "<vector>"])
325        enum_text = cformat.multiline_fill(self.property_enum_name_list, ',', 8)
326        enum_text2 = cformat.multiline_fill(['"%s"' % e for e in self.property_enum_name_list], ',', 8)
327        full_name_text = cformat.multiline_fill(['"%s"' % self.full_name_map[e] for e in self.property_enum_name_list], ',', 8)
328        map_text = cformat.multiline_fill(['{"%s", %s}' % (k, self.property_lookup_map[k]) for k in sorted(self.property_lookup_map.keys())], ',', 8)
329        f.write(PropertyAliases_template % (enum_text, enum_text2, full_name_text, map_text))
330        cformat.close_header_file(f)
331
332    def load_property_value_info(self):
333        initializePropertyValues(self.property_object_map, self.property_lookup_map)
334
335    def generate_PropertyValueAliases_h(self):
336        f = cformat.open_header_file_for_write('PropertyValueAliases')
337        cformat.write_imports(f, ['"PropertyAliases.h"', "<vector>", "<unordered_map>", "<string>"])
338        f.write("namespace UCD {\n")
339        #  Generate the aliases for all Binary properties.
340        enum_text = cformat.multiline_fill(['N', 'Y'], ',', 12)
341        enum_names = cformat.multiline_fill(['"N"', '"Y"'], ',', 12)
342        full_name_text = cformat.multiline_fill(['"No"', '"Yes"'], ',', 12)
343        binary_properties = ['{"n", N}', '{"y", Y}', '{"no", N}', '{"yes", Y}', '{"f", N}', '{"t", Y}', '{"false", N}', '{"true", Y}']
344        binary_map_text = cformat.multiline_fill(binary_properties, ',', 12)
345        f.write(EnumeratedProperty_template % ('Binary', enum_text, enum_names, full_name_text, binary_map_text))
346        #
347        for p in self.property_enum_name_list:
348            po = self.property_object_map[p]
349            if isinstance(po, EnumeratedPropertyObject):
350                ordered_enum_list = po.property_value_list
351                enum_text = cformat.multiline_fill(ordered_enum_list, ',', 12)
352                enum_names = cformat.multiline_fill(['"%s"' % s for s in ordered_enum_list], ',', 12)
353                if p == 'ccc': # Special case: add numeric value information for ccc.
354                    enum_text += r"""
355        };
356        const uint16_t enum_val[] = {
357        """
358                    enum_text += "      " + cformat.multiline_fill(["%s" % (po.property_value_enum_integer[e]) for e in ordered_enum_list], ',', 12)
359                full_names = [po.property_value_full_name_map[e] for e in ordered_enum_list]
360                full_name_text = cformat.multiline_fill(['"%s"' % name for name in full_names], ',', 12)
361                canon_full_names = [canonicalize(name) for name in full_names]
362                canon_enums = [canonicalize(e) for e in ordered_enum_list]
363                canon_keys = [canonicalize(k) for k in po.property_value_lookup_map.keys()]
364                aliases_only = []
365                for k in canon_keys:
366                    if k in canon_enums: continue
367                    if k in canon_full_names: continue
368                    if k in aliases_only: continue
369                    aliases_only.append(k)
370                map_text = cformat.multiline_fill(['{"%s", %s_ns::%s}' % (k, p.upper(), po.property_value_lookup_map[k]) for k in sorted(aliases_only)], ',', 12)
371                f.write(EnumeratedProperty_template % (p.upper(), enum_text, enum_names, full_name_text, map_text))
372        f.write("}\n")
373        cformat.close_header_file(f)
374
375    def emit_property(self, f, property_code):
376        property_object = self.property_object_map[property_code]
377        if isinstance(property_object, BinaryPropertyObject):
378            emit_binary_property(f, property_code, property_object.value_map['Y'])
379            print("%s: %s bytes" % (property_object.getPropertyFullName(), property_object.value_map['Y'].bytes()))
380        elif isinstance(property_object, EnumeratedPropertyObject):
381            prop_values = property_object.name_list_order
382            independent_prop_values = property_object.independent_prop_values
383            emit_enumerated_property(f, property_code, independent_prop_values, prop_values, property_object.value_map)
384            print("%s: %s bytes" % (property_object.getPropertyFullName(), sum([property_object.value_map[v].bytes() for v in property_object.value_map.keys()])))
385        elif isinstance(property_object, StringPropertyObject):
386            emit_string_property(f, property_code, property_object.null_str_set, property_object.reflexive_set, property_object.cp_value_map)
387        elif isinstance(property_object, StringOverridePropertyObject):
388            emit_string_override_property(f, property_code, property_object.overridden_code, property_object.overridden_set, property_object.cp_value_map)
389        elif isinstance(property_object, NumericPropertyObject):
390            emit_numeric_property(f, property_code, property_object.NaN_set, property_object.cp_value_map)
391        elif isinstance(property_object, ObsoletePropertyObject):
392            emit_Obsolete_property(f, property_code)
393        else: 
394            print("%s: unsupported property.")
395            return
396        self.supported_props.append(property_code)
397
398    def generate_property_value_file(self, filename_root, property_code):
399        property_object = self.property_object_map[property_code]
400        parse_property_data(self.property_object_map[property_code], filename_root + '.txt')
401        basename = os.path.basename(filename_root)
402        f = cformat.open_header_file_for_write(basename)
403        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
404        f.write("\nnamespace UCD {\n")
405        self.emit_property(f, property_code)
406        f.write("}\n")
407        cformat.close_header_file(f)
408        self.property_data_headers.append(basename)
409
410    def generate_multisection_properties_file(self, filename_root):
411        props = parse_multisection_property_data(filename_root + '.txt', self.property_object_map, self.property_lookup_map)
412        #(props, prop_map) = parse_UCD_codepoint_name_map(filename_root + '.txt', self.property_lookup_map)
413        basename = os.path.basename(filename_root)
414        f = cformat.open_header_file_for_write(basename)
415        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
416        f.write("\nnamespace UCD {\n")
417        for p in sorted(props):
418            self.emit_property(f, p)
419            property_object = self.property_object_map[p]
420        f.write("}\n\n")
421        cformat.close_header_file(f)
422        self.property_data_headers.append(basename)
423
424    def generate_multicolumn_properties_file(self, filename_root, prop_code_list):
425        props = parse_multicolumn_property_data(filename_root + '.txt', self.property_object_map, self.property_lookup_map, prop_code_list)
426        #(props, prop_map) = parse_UCD_codepoint_name_map(filename_root + '.txt', self.property_lookup_map)
427        basename = os.path.basename(filename_root)
428        f = cformat.open_header_file_for_write(basename)
429        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
430        f.write("\nnamespace UCD {\n")
431        for p in prop_code_list:
432            if p in self.property_object_map: self.emit_property(f, p)
433        f.write("}\n\n")
434        cformat.close_header_file(f)
435        self.property_data_headers.append(basename)
436
437    def generate_UnicodeData_h(self):
438        basename = 'UnicodeData'
439        parse_UnicodeData_txt(self.property_object_map)
440        f = cformat.open_header_file_for_write(basename)
441        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
442        prop_code_list = ['na', 'dm', 'suc', 'slc', 'stc', 'na1', 'isc', 'nv']
443        f.write("\nnamespace UCD {\n")
444        for p in prop_code_list:
445            self.emit_property(f, p)
446            property_object = self.property_object_map[p]
447        f.write("}\n\n")
448        cformat.close_header_file(f)
449        self.property_data_headers.append(basename)
450
451    def generate_SpecialCasing_h(self):
452        basename = 'SpecialCasing'
453        parse_SpecialCasing_txt(self.property_object_map)
454        f = cformat.open_header_file_for_write(basename)
455        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"UnicodeData.h"', '"unicode_set.h"'])
456        f.write("\nnamespace UCD {\n")
457        for p in ['lc', 'uc', 'tc']:
458            self.emit_property(f, p)
459            property_object = self.property_object_map[p]
460        f.write("}\n\n")
461        cformat.close_header_file(f)
462        self.property_data_headers.append(basename)
463
464    def generate_ScriptExtensions_h(self):
465        filename_root = 'ScriptExtensions'
466        property_code = 'scx'
467        extension_object = self.property_object_map['scx']
468        extension_object.setBaseProperty(self.property_object_map['sc'])
469        parse_property_data(extension_object, filename_root+'.txt')
470        basename = os.path.basename(filename_root)
471        f = cformat.open_header_file_for_write(basename)
472        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"'])
473        prop_list = self.property_object_map['sc'].name_list_order
474        value_map = extension_object.value_map
475        f.write("\nnamespace UCD {\n")
476        f.write("    namespace SCX_ns {\n")
477        for v in prop_list:
478            f.write("        /** Code Point Ranges for %s\n        " % v)
479            f.write(cformat.multiline_fill(['[%04x, %04x]' % (lo, hi) for (lo, hi) in uset_to_range_list(value_map[v])], ',', 8))
480            f.write("**/\n")
481            f.write(value_map[v].generate(v.lower() + "_Ext", 8))
482        set_list = ['&%s_Ext' % v.lower() for v in prop_list]
483        f.write("        static ExtensionPropertyObject property_object\n")
484        f.write("       {%s,\n" % property_code)
485        f.write("        UCD::sc,\n")
486        f.write("       {")
487        f.write(cformat.multiline_fill(set_list, ',', 8))
488        f.write("\n        }};\n    }\n}\n")
489        cformat.close_header_file(f)
490        print("%s: %s bytes" % (basename, sum([value_map[v].bytes() for v in value_map.keys()])))
491        self.supported_props.append(property_code)
492        self.property_data_headers.append(basename)
493
494    def generate_PropertyObjectTable_h(self):
495        f = cformat.open_header_file_for_write('PropertyObjectTable')
496        cformat.write_imports(f, ['"PropertyObjects.h"', '"PropertyAliases.h"', '<array>'])
497        cformat.write_imports(f, ['"%s.h"' % fname for fname in self.property_data_headers])
498        f.write("\nnamespace UCD {\n")
499        objlist = []
500        for p in self.property_enum_name_list:
501            k = self.property_object_map[p].getPropertyKind()
502            if p in self.supported_props:
503                objlist.append("&%s_ns::property_object" % p.upper())
504            else:
505                objlist.append("new UnsupportedPropertyObject(%s, PropertyObject::ClassTypeId::%sProperty)" % (p, k))
506        f.write("\n  const std::array<PropertyObject *, %i> property_object_table = {{\n    " % len(objlist))
507        f.write(",\n    ".join(objlist) + '  }};\n}\n')
508        cformat.close_header_file(f)
509
510    def generate_UCD_Config_h(self):
511        setVersionfromReadMe_txt()
512        f = cformat.open_header_file_for_write('UCD_Config')
513        f.write("#include <utility>\n")
514        f.write("namespace UCD {\n")
515        f.write("\tconst auto UnicodeVersion = \"%s\";\n" % UCD_config.version)
516        f.write("\tusing codepoint_t = unsigned;\n")
517        f.write("\tenum : codepoint_t { UNICODE_MAX = %s };\n" % UCD_config.UCD_max_code_point)
518        f.write("\tusing interval_t = std::pair<codepoint_t, codepoint_t>;\n")
519        f.write("}\n")
520        cformat.close_header_file(f)
521
522
523    def genCaseFolding_h(self):
524        basename = 'CaseFolding'
525        fold_data = parse_CaseFolding_txt(self.property_object_map)
526        cm = simple_CaseClosure_map(fold_data)
527        f = cformat.open_header_file_for_write(basename, 'UCD_properties.py')
528        cformat.write_imports(f, ['"PropertyAliases.h"', '"PropertyObjects.h"', '"PropertyValueAliases.h"', '"unicode_set.h"', '<vector>'])
529        f.write(foldDeclarations)
530        f.write(genFoldEntryData(cm))
531        f.write("\nnamespace UCD {\n")
532        self.emit_property(f, 'scf')
533        self.emit_property(f, 'cf')
534        f.write("}\n")
535        cformat.close_header_file(f)
536        self.supported_props.append(['scf', 'cf'])
537        self.property_data_headers.append(basename)
538
539
540
541def UCD_main():
542    ucd = UCD_generator()
543
544    # First parse all property names and their aliases
545    ucd.load_property_name_info()
546    #
547    # Generate the PropertyAliases.h file to define all the Unicode property_t enum
548    # and the basic property information.
549    ucd.generate_PropertyAliases_h()
550    #
551    # Next parse all property value names and their aliases.  Generate the data.
552    ucd.load_property_value_info()
553
554    ucd.generate_UnicodeData_h()
555   
556    ucd.generate_SpecialCasing_h()
557   
558    ucd.genCaseFolding_h()
559   
560    ucd.generate_multicolumn_properties_file('NameAliases', ['Name_Alias', 'Alias_Kind'])
561
562    #
563    # The Age property
564    ucd.generate_property_value_file('DerivedAge', 'age')
565    #
566    # The Block property
567    ucd.generate_property_value_file('Blocks', 'blk')
568   
569    # Scripts
570    ucd.generate_property_value_file('Scripts', 'sc')
571    #
572    # # Script Extensions
573    ucd.generate_ScriptExtensions_h()
574    # #
575    # General Category
576    ucd.generate_property_value_file('extracted/DerivedGeneralCategory', 'gc')
577   
578    # Binary properties from PropList.txt
579    ucd.generate_multisection_properties_file('PropList')
580   
581    # Binary properties from DerivedCoreProperties.txt
582    ucd.generate_multisection_properties_file('DerivedCoreProperties')
583    #
584    #
585    # LineBreak types
586    #ucd.generate_property_value_file('extracted/DerivedLineBreak', 'lb')
587    ucd.generate_property_value_file('LineBreak', 'lb')
588    #
589    # Grapheme Cluster Break property
590    ucd.generate_property_value_file('auxiliary/GraphemeBreakProperty', 'GCB')
591    #
592    # Sentence Break property
593    ucd.generate_property_value_file('auxiliary/SentenceBreakProperty', 'SB')
594    #
595    # Word Break property
596    ucd.generate_property_value_file('auxiliary/WordBreakProperty', 'WB')
597    #
598    # Vertical orientation property
599    ucd.generate_property_value_file('VerticalOrientation', 'vo')
600
601    # East Asian Width - can use either source
602    ucd.generate_property_value_file('EastAsianWidth', 'ea')
603    #ucd.generate_property_value_file('extracted/DerivedEastAsianWidth', 'ea')
604    #
605    # Hangul Syllable Type
606    ucd.generate_property_value_file('HangulSyllableType', 'hst')
607    #
608    ucd.generate_multisection_properties_file('extracted/DerivedBinaryProperties')
609    # #
610    # # Canonical_Combining_Class
611    ucd.generate_property_value_file('extracted/DerivedCombiningClass', 'ccc')
612    #
613    # Decomposition Type
614    ucd.generate_property_value_file('extracted/DerivedDecompositionType', 'dt')
615    #
616    # Joining Group and Type
617    ucd.generate_property_value_file('extracted/DerivedJoiningGroup', 'jg')
618    ucd.generate_property_value_file('extracted/DerivedJoiningType', 'jt')
619    #
620    # Numeric Type and Value
621    ucd.generate_property_value_file('extracted/DerivedNumericType', 'nt')
622    #ucd.generate_property_value_file('extracted/DerivedNumericValue', 'nv')
623    #
624    # Normalization properties.
625    ucd.generate_multisection_properties_file('DerivedNormalizationProps')
626    #
627    # Bidirectional properties
628    ucd.generate_property_value_file('extracted/DerivedBidiClass', 'bc')
629    ucd.generate_multicolumn_properties_file('BidiBrackets', ['bpb', 'bpt'])
630    ucd.generate_property_value_file('BidiMirroring', 'bmg')
631
632    # Indic properties
633    ucd.generate_property_value_file('IndicPositionalCategory', 'InPC')
634    ucd.generate_property_value_file('IndicSyllabicCategory', 'InSC')
635
636    ucd.generate_property_value_file('CompositionExclusions', 'CE')
637    #
638    ucd.generate_property_value_file('Jamo', 'JSN')
639    #
640    #
641    #
642    ucd.generate_PropertyValueAliases_h()
643
644    ucd.generate_PropertyObjectTable_h()
645
646    ucd.generate_UCD_Config_h()
647
648if __name__ == "__main__":
649  UCD_main()
Note: See TracBrowser for help on using the repository browser.