Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some "Special Casing" support to String#downcase, String#upcase, and String#titlecase #2070

Merged
merged 7 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions include/natalie/encoding_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,25 @@

namespace Natalie {

const int SPECIAL_CASE_LOWER_MAX_SIZE = 2;
const int SPECIAL_CASE_TITLE_MAX_SIZE = 3;
const int SPECIAL_CASE_UPPER_MAX_SIZE = 3;

struct SpecialCasingEntry {
uint32_t code;
uint32_t lower[SPECIAL_CASE_LOWER_MAX_SIZE];
uint32_t title[SPECIAL_CASE_TITLE_MAX_SIZE];
uint32_t upper[SPECIAL_CASE_UPPER_MAX_SIZE];
};

extern nat_int_t lcase_map[];
extern nat_int_t ucase_map[];
extern nat_int_t tcase_map[];
extern nat_int_t lcase_index[];
extern nat_int_t ucase_index[];
extern nat_int_t tcase_index[];
extern const int special_casing_map_size;
extern SpecialCasingEntry special_casing_map[];

using namespace TM;

Expand Down Expand Up @@ -82,9 +95,13 @@ class EncodingObject : public Object {
static EncodingObject *find_encoding_by_name(Env *env, String name);
static EncodingObject *find_encoding(Env *env, Value encoding);

static nat_int_t codepoint_to_lowercase(nat_int_t codepoint, bool ascii_only = false);
static nat_int_t codepoint_to_uppercase(nat_int_t codepoint, bool ascii_only = false);
static nat_int_t codepoint_to_titlecase(nat_int_t codepoint, bool ascii_only = false);
// must pass a buffer of nat_int_t to this function; uint8_t return is number of codepoints written
static uint8_t codepoint_to_lowercase(nat_int_t codepoint, nat_int_t result[], bool ascii_only = false);
static uint8_t codepoint_to_uppercase(nat_int_t codepoint, nat_int_t result[], bool ascii_only = false);
static uint8_t codepoint_to_titlecase(nat_int_t codepoint, nat_int_t result[], bool ascii_only = false);

static void init_special_casing_map();
static SpecialCasingEntry find_special_casing_map_entry(nat_int_t codepoint);

static Value casefold_common(nat_int_t codepoint);
static Value casefold_full(nat_int_t codepoint);
Expand Down
35 changes: 35 additions & 0 deletions lib/natalie/encoding/casemap_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@ def build_map_and_index(blocks)
ucase_map, ucase_index = build_map_and_index(ucase_blocks)
tcase_map, tcase_index = build_map_and_index(tcase_blocks)

unless File.exist?('/tmp/SpecialCasing.txt')
File.write(
'/tmp/SpecialCasing.txt',
URI.open('http://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt').read
)
end

data = File.read('/tmp/SpecialCasing.txt')
.split(/# Conditional Mappings\n/)
.first
.split(/\n/)
.reject { |l| l.start_with?('#') || l.strip.empty? }
special_casing_map = data.map do |line|
parts = line.sub!(/\s*#.*$/, '').split(/\s*;\s*/)
code, lower, title, upper = parts.map { |cc| cc.split.map { |c| c.to_i(16) } }
code = code.first
lower << 0 if lower.size < 2
title << 0 if title.size < 3
upper << 0 if upper.size < 3
{ code:, lower:, title:, upper: }
end

puts '// This file is auto-generated from http://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt'
puts '// See casemap_gen.rb in this repository for instructions regenerating it.'
puts '// DO NOT EDIT THIS FILE BY HAND!'
Expand All @@ -89,4 +111,17 @@ def build_map_and_index(blocks)
puts
puts "nat_int_t tcase_index[] = {\n#{format_array(tcase_index, count_per_line: 10, num_width: 4)}\n};"
puts
puts "const int special_casing_map_size = #{special_casing_map.size};"
puts "SpecialCasingEntry special_casing_map[#{special_casing_map.size}] = { { 0 } };"
puts
puts 'void EncodingObject::init_special_casing_map() {'
special_casing_map.each_with_index do |mapping, index|
code = "0x#{mapping[:code].to_s(16)}"
lower = "{ #{mapping[:lower].map { |c| "0x#{c.to_s(16)}" }.join(', ')} }"
title = "{ #{mapping[:title].map { |c| "0x#{c.to_s(16)}" }.join(', ')} }"
upper = "{ #{mapping[:upper].map { |c| "0x#{c.to_s(16)}" }.join(', ')} }"
puts " special_casing_map[#{index}] = { #{code}, #{lower}, #{title}, #{upper} };"
end
puts '}'
puts
puts '}'
38 changes: 15 additions & 23 deletions spec/core/string/capitalize_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,16 @@
end

it "only capitalizes the first resulting character when upcasing a character produces a multi-character sequence" do
NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
"ß".capitalize.should == "Ss"
end
"ß".capitalize.should == "Ss"
end

it "updates string metadata" do
NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
capitalized = "ßeT".capitalize
capitalized = "ßeT".capitalize

capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
capitalized.ascii_only?.should be_true
end
capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
capitalized.ascii_only?.should be_true
end
end

Expand Down Expand Up @@ -119,11 +115,9 @@
end

it "only capitalizes the first resulting character when upcasing a character produces a multi-character sequence" do
NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
a = "ß"
a.capitalize!
a.should == "Ss"
end
a = "ß"
a.capitalize!
a.should == "Ss"
end

it "works for non-ascii-compatible encodings" do
Expand All @@ -133,15 +127,13 @@
end

it "updates string metadata" do
NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
capitalized = "ßeT"
capitalized.capitalize!
capitalized = "ßeT"
capitalized.capitalize!

capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
capitalized.ascii_only?.should be_true
end
capitalized.should == "Sset"
capitalized.size.should == 4
capitalized.bytesize.should == 4
capitalized.ascii_only?.should be_true
end
end

Expand Down
28 changes: 10 additions & 18 deletions spec/core/string/upcase_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@
it "updates string metadata" do
upcased = "aßet".upcase

NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
upcased.ascii_only?.should be_true
end
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
upcased.ascii_only?.should be_true
end
end

Expand Down Expand Up @@ -59,9 +57,7 @@

describe "full Unicode case mapping adapted for Lithuanian" do
it "currently works the same as full Unicode case mapping" do
NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
"iß".upcase(:lithuanian).should == "ISS"
end
"iß".upcase(:lithuanian).should == "ISS"
end

it "allows Turkic as an extra option (and applies Turkic semantics)" do
Expand Down Expand Up @@ -118,12 +114,10 @@
upcased = "aßet"
upcased.upcase!

NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
upcased.ascii_only?.should be_true
end
upcased.should == "ASSET"
upcased.size.should == 5
upcased.bytesize.should == 5
upcased.ascii_only?.should be_true
end
end

Expand Down Expand Up @@ -167,9 +161,7 @@
it "currently works the same as full Unicode case mapping" do
a = "iß"
a.upcase!(:lithuanian)
NATFIXME 'Pending unicode casemap support', exception: SpecFailedException do
a.should == "ISS"
end
a.should == "ISS"
end

it "allows Turkic as an extra option (and applies Turkic semantics)" do
Expand Down
115 changes: 112 additions & 3 deletions src/encoding/casemap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,7 @@ nat_int_t lcase_index[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0
0, 0, 0, 0
};

nat_int_t ucase_index[] = {
Expand All @@ -2034,7 +2034,7 @@ nat_int_t ucase_index[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0
0, 0, 0, 0
};

nat_int_t tcase_index[] = {
Expand All @@ -2058,7 +2058,116 @@ nat_int_t tcase_index[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0
0, 0, 0, 0
};

const int special_casing_map_size = 103;
SpecialCasingEntry special_casing_map[103] = { { 0 } };

void EncodingObject::init_special_casing_map() {
special_casing_map[0] = { 0xdf, { 0xdf, 0x0 }, { 0x53, 0x73, 0x0 }, { 0x53, 0x53, 0x0 } };
special_casing_map[1] = { 0x130, { 0x69, 0x307 }, { 0x130, 0x0 }, { 0x130, 0x0 } };
special_casing_map[2] = { 0xfb00, { 0xfb00, 0x0 }, { 0x46, 0x66, 0x0 }, { 0x46, 0x46, 0x0 } };
special_casing_map[3] = { 0xfb01, { 0xfb01, 0x0 }, { 0x46, 0x69, 0x0 }, { 0x46, 0x49, 0x0 } };
special_casing_map[4] = { 0xfb02, { 0xfb02, 0x0 }, { 0x46, 0x6c, 0x0 }, { 0x46, 0x4c, 0x0 } };
special_casing_map[5] = { 0xfb03, { 0xfb03, 0x0 }, { 0x46, 0x66, 0x69 }, { 0x46, 0x46, 0x49 } };
special_casing_map[6] = { 0xfb04, { 0xfb04, 0x0 }, { 0x46, 0x66, 0x6c }, { 0x46, 0x46, 0x4c } };
special_casing_map[7] = { 0xfb05, { 0xfb05, 0x0 }, { 0x53, 0x74, 0x0 }, { 0x53, 0x54, 0x0 } };
special_casing_map[8] = { 0xfb06, { 0xfb06, 0x0 }, { 0x53, 0x74, 0x0 }, { 0x53, 0x54, 0x0 } };
special_casing_map[9] = { 0x587, { 0x587, 0x0 }, { 0x535, 0x582, 0x0 }, { 0x535, 0x552, 0x0 } };
special_casing_map[10] = { 0xfb13, { 0xfb13, 0x0 }, { 0x544, 0x576, 0x0 }, { 0x544, 0x546, 0x0 } };
special_casing_map[11] = { 0xfb14, { 0xfb14, 0x0 }, { 0x544, 0x565, 0x0 }, { 0x544, 0x535, 0x0 } };
special_casing_map[12] = { 0xfb15, { 0xfb15, 0x0 }, { 0x544, 0x56b, 0x0 }, { 0x544, 0x53b, 0x0 } };
special_casing_map[13] = { 0xfb16, { 0xfb16, 0x0 }, { 0x54e, 0x576, 0x0 }, { 0x54e, 0x546, 0x0 } };
special_casing_map[14] = { 0xfb17, { 0xfb17, 0x0 }, { 0x544, 0x56d, 0x0 }, { 0x544, 0x53d, 0x0 } };
special_casing_map[15] = { 0x149, { 0x149, 0x0 }, { 0x2bc, 0x4e, 0x0 }, { 0x2bc, 0x4e, 0x0 } };
special_casing_map[16] = { 0x390, { 0x390, 0x0 }, { 0x399, 0x308, 0x301 }, { 0x399, 0x308, 0x301 } };
special_casing_map[17] = { 0x3b0, { 0x3b0, 0x0 }, { 0x3a5, 0x308, 0x301 }, { 0x3a5, 0x308, 0x301 } };
special_casing_map[18] = { 0x1f0, { 0x1f0, 0x0 }, { 0x4a, 0x30c, 0x0 }, { 0x4a, 0x30c, 0x0 } };
special_casing_map[19] = { 0x1e96, { 0x1e96, 0x0 }, { 0x48, 0x331, 0x0 }, { 0x48, 0x331, 0x0 } };
special_casing_map[20] = { 0x1e97, { 0x1e97, 0x0 }, { 0x54, 0x308, 0x0 }, { 0x54, 0x308, 0x0 } };
special_casing_map[21] = { 0x1e98, { 0x1e98, 0x0 }, { 0x57, 0x30a, 0x0 }, { 0x57, 0x30a, 0x0 } };
special_casing_map[22] = { 0x1e99, { 0x1e99, 0x0 }, { 0x59, 0x30a, 0x0 }, { 0x59, 0x30a, 0x0 } };
special_casing_map[23] = { 0x1e9a, { 0x1e9a, 0x0 }, { 0x41, 0x2be, 0x0 }, { 0x41, 0x2be, 0x0 } };
special_casing_map[24] = { 0x1f50, { 0x1f50, 0x0 }, { 0x3a5, 0x313, 0x0 }, { 0x3a5, 0x313, 0x0 } };
special_casing_map[25] = { 0x1f52, { 0x1f52, 0x0 }, { 0x3a5, 0x313, 0x300 }, { 0x3a5, 0x313, 0x300 } };
special_casing_map[26] = { 0x1f54, { 0x1f54, 0x0 }, { 0x3a5, 0x313, 0x301 }, { 0x3a5, 0x313, 0x301 } };
special_casing_map[27] = { 0x1f56, { 0x1f56, 0x0 }, { 0x3a5, 0x313, 0x342 }, { 0x3a5, 0x313, 0x342 } };
special_casing_map[28] = { 0x1fb6, { 0x1fb6, 0x0 }, { 0x391, 0x342, 0x0 }, { 0x391, 0x342, 0x0 } };
special_casing_map[29] = { 0x1fc6, { 0x1fc6, 0x0 }, { 0x397, 0x342, 0x0 }, { 0x397, 0x342, 0x0 } };
special_casing_map[30] = { 0x1fd2, { 0x1fd2, 0x0 }, { 0x399, 0x308, 0x300 }, { 0x399, 0x308, 0x300 } };
special_casing_map[31] = { 0x1fd3, { 0x1fd3, 0x0 }, { 0x399, 0x308, 0x301 }, { 0x399, 0x308, 0x301 } };
special_casing_map[32] = { 0x1fd6, { 0x1fd6, 0x0 }, { 0x399, 0x342, 0x0 }, { 0x399, 0x342, 0x0 } };
special_casing_map[33] = { 0x1fd7, { 0x1fd7, 0x0 }, { 0x399, 0x308, 0x342 }, { 0x399, 0x308, 0x342 } };
special_casing_map[34] = { 0x1fe2, { 0x1fe2, 0x0 }, { 0x3a5, 0x308, 0x300 }, { 0x3a5, 0x308, 0x300 } };
special_casing_map[35] = { 0x1fe3, { 0x1fe3, 0x0 }, { 0x3a5, 0x308, 0x301 }, { 0x3a5, 0x308, 0x301 } };
special_casing_map[36] = { 0x1fe4, { 0x1fe4, 0x0 }, { 0x3a1, 0x313, 0x0 }, { 0x3a1, 0x313, 0x0 } };
special_casing_map[37] = { 0x1fe6, { 0x1fe6, 0x0 }, { 0x3a5, 0x342, 0x0 }, { 0x3a5, 0x342, 0x0 } };
special_casing_map[38] = { 0x1fe7, { 0x1fe7, 0x0 }, { 0x3a5, 0x308, 0x342 }, { 0x3a5, 0x308, 0x342 } };
special_casing_map[39] = { 0x1ff6, { 0x1ff6, 0x0 }, { 0x3a9, 0x342, 0x0 }, { 0x3a9, 0x342, 0x0 } };
special_casing_map[40] = { 0x1f80, { 0x1f80, 0x0 }, { 0x1f88, 0x0 }, { 0x1f08, 0x399, 0x0 } };
special_casing_map[41] = { 0x1f81, { 0x1f81, 0x0 }, { 0x1f89, 0x0 }, { 0x1f09, 0x399, 0x0 } };
special_casing_map[42] = { 0x1f82, { 0x1f82, 0x0 }, { 0x1f8a, 0x0 }, { 0x1f0a, 0x399, 0x0 } };
special_casing_map[43] = { 0x1f83, { 0x1f83, 0x0 }, { 0x1f8b, 0x0 }, { 0x1f0b, 0x399, 0x0 } };
special_casing_map[44] = { 0x1f84, { 0x1f84, 0x0 }, { 0x1f8c, 0x0 }, { 0x1f0c, 0x399, 0x0 } };
special_casing_map[45] = { 0x1f85, { 0x1f85, 0x0 }, { 0x1f8d, 0x0 }, { 0x1f0d, 0x399, 0x0 } };
special_casing_map[46] = { 0x1f86, { 0x1f86, 0x0 }, { 0x1f8e, 0x0 }, { 0x1f0e, 0x399, 0x0 } };
special_casing_map[47] = { 0x1f87, { 0x1f87, 0x0 }, { 0x1f8f, 0x0 }, { 0x1f0f, 0x399, 0x0 } };
special_casing_map[48] = { 0x1f88, { 0x1f80, 0x0 }, { 0x1f88, 0x0 }, { 0x1f08, 0x399, 0x0 } };
special_casing_map[49] = { 0x1f89, { 0x1f81, 0x0 }, { 0x1f89, 0x0 }, { 0x1f09, 0x399, 0x0 } };
special_casing_map[50] = { 0x1f8a, { 0x1f82, 0x0 }, { 0x1f8a, 0x0 }, { 0x1f0a, 0x399, 0x0 } };
special_casing_map[51] = { 0x1f8b, { 0x1f83, 0x0 }, { 0x1f8b, 0x0 }, { 0x1f0b, 0x399, 0x0 } };
special_casing_map[52] = { 0x1f8c, { 0x1f84, 0x0 }, { 0x1f8c, 0x0 }, { 0x1f0c, 0x399, 0x0 } };
special_casing_map[53] = { 0x1f8d, { 0x1f85, 0x0 }, { 0x1f8d, 0x0 }, { 0x1f0d, 0x399, 0x0 } };
special_casing_map[54] = { 0x1f8e, { 0x1f86, 0x0 }, { 0x1f8e, 0x0 }, { 0x1f0e, 0x399, 0x0 } };
special_casing_map[55] = { 0x1f8f, { 0x1f87, 0x0 }, { 0x1f8f, 0x0 }, { 0x1f0f, 0x399, 0x0 } };
special_casing_map[56] = { 0x1f90, { 0x1f90, 0x0 }, { 0x1f98, 0x0 }, { 0x1f28, 0x399, 0x0 } };
special_casing_map[57] = { 0x1f91, { 0x1f91, 0x0 }, { 0x1f99, 0x0 }, { 0x1f29, 0x399, 0x0 } };
special_casing_map[58] = { 0x1f92, { 0x1f92, 0x0 }, { 0x1f9a, 0x0 }, { 0x1f2a, 0x399, 0x0 } };
special_casing_map[59] = { 0x1f93, { 0x1f93, 0x0 }, { 0x1f9b, 0x0 }, { 0x1f2b, 0x399, 0x0 } };
special_casing_map[60] = { 0x1f94, { 0x1f94, 0x0 }, { 0x1f9c, 0x0 }, { 0x1f2c, 0x399, 0x0 } };
special_casing_map[61] = { 0x1f95, { 0x1f95, 0x0 }, { 0x1f9d, 0x0 }, { 0x1f2d, 0x399, 0x0 } };
special_casing_map[62] = { 0x1f96, { 0x1f96, 0x0 }, { 0x1f9e, 0x0 }, { 0x1f2e, 0x399, 0x0 } };
special_casing_map[63] = { 0x1f97, { 0x1f97, 0x0 }, { 0x1f9f, 0x0 }, { 0x1f2f, 0x399, 0x0 } };
special_casing_map[64] = { 0x1f98, { 0x1f90, 0x0 }, { 0x1f98, 0x0 }, { 0x1f28, 0x399, 0x0 } };
special_casing_map[65] = { 0x1f99, { 0x1f91, 0x0 }, { 0x1f99, 0x0 }, { 0x1f29, 0x399, 0x0 } };
special_casing_map[66] = { 0x1f9a, { 0x1f92, 0x0 }, { 0x1f9a, 0x0 }, { 0x1f2a, 0x399, 0x0 } };
special_casing_map[67] = { 0x1f9b, { 0x1f93, 0x0 }, { 0x1f9b, 0x0 }, { 0x1f2b, 0x399, 0x0 } };
special_casing_map[68] = { 0x1f9c, { 0x1f94, 0x0 }, { 0x1f9c, 0x0 }, { 0x1f2c, 0x399, 0x0 } };
special_casing_map[69] = { 0x1f9d, { 0x1f95, 0x0 }, { 0x1f9d, 0x0 }, { 0x1f2d, 0x399, 0x0 } };
special_casing_map[70] = { 0x1f9e, { 0x1f96, 0x0 }, { 0x1f9e, 0x0 }, { 0x1f2e, 0x399, 0x0 } };
special_casing_map[71] = { 0x1f9f, { 0x1f97, 0x0 }, { 0x1f9f, 0x0 }, { 0x1f2f, 0x399, 0x0 } };
special_casing_map[72] = { 0x1fa0, { 0x1fa0, 0x0 }, { 0x1fa8, 0x0 }, { 0x1f68, 0x399, 0x0 } };
special_casing_map[73] = { 0x1fa1, { 0x1fa1, 0x0 }, { 0x1fa9, 0x0 }, { 0x1f69, 0x399, 0x0 } };
special_casing_map[74] = { 0x1fa2, { 0x1fa2, 0x0 }, { 0x1faa, 0x0 }, { 0x1f6a, 0x399, 0x0 } };
special_casing_map[75] = { 0x1fa3, { 0x1fa3, 0x0 }, { 0x1fab, 0x0 }, { 0x1f6b, 0x399, 0x0 } };
special_casing_map[76] = { 0x1fa4, { 0x1fa4, 0x0 }, { 0x1fac, 0x0 }, { 0x1f6c, 0x399, 0x0 } };
special_casing_map[77] = { 0x1fa5, { 0x1fa5, 0x0 }, { 0x1fad, 0x0 }, { 0x1f6d, 0x399, 0x0 } };
special_casing_map[78] = { 0x1fa6, { 0x1fa6, 0x0 }, { 0x1fae, 0x0 }, { 0x1f6e, 0x399, 0x0 } };
special_casing_map[79] = { 0x1fa7, { 0x1fa7, 0x0 }, { 0x1faf, 0x0 }, { 0x1f6f, 0x399, 0x0 } };
special_casing_map[80] = { 0x1fa8, { 0x1fa0, 0x0 }, { 0x1fa8, 0x0 }, { 0x1f68, 0x399, 0x0 } };
special_casing_map[81] = { 0x1fa9, { 0x1fa1, 0x0 }, { 0x1fa9, 0x0 }, { 0x1f69, 0x399, 0x0 } };
special_casing_map[82] = { 0x1faa, { 0x1fa2, 0x0 }, { 0x1faa, 0x0 }, { 0x1f6a, 0x399, 0x0 } };
special_casing_map[83] = { 0x1fab, { 0x1fa3, 0x0 }, { 0x1fab, 0x0 }, { 0x1f6b, 0x399, 0x0 } };
special_casing_map[84] = { 0x1fac, { 0x1fa4, 0x0 }, { 0x1fac, 0x0 }, { 0x1f6c, 0x399, 0x0 } };
special_casing_map[85] = { 0x1fad, { 0x1fa5, 0x0 }, { 0x1fad, 0x0 }, { 0x1f6d, 0x399, 0x0 } };
special_casing_map[86] = { 0x1fae, { 0x1fa6, 0x0 }, { 0x1fae, 0x0 }, { 0x1f6e, 0x399, 0x0 } };
special_casing_map[87] = { 0x1faf, { 0x1fa7, 0x0 }, { 0x1faf, 0x0 }, { 0x1f6f, 0x399, 0x0 } };
special_casing_map[88] = { 0x1fb3, { 0x1fb3, 0x0 }, { 0x1fbc, 0x0 }, { 0x391, 0x399, 0x0 } };
special_casing_map[89] = { 0x1fbc, { 0x1fb3, 0x0 }, { 0x1fbc, 0x0 }, { 0x391, 0x399, 0x0 } };
special_casing_map[90] = { 0x1fc3, { 0x1fc3, 0x0 }, { 0x1fcc, 0x0 }, { 0x397, 0x399, 0x0 } };
special_casing_map[91] = { 0x1fcc, { 0x1fc3, 0x0 }, { 0x1fcc, 0x0 }, { 0x397, 0x399, 0x0 } };
special_casing_map[92] = { 0x1ff3, { 0x1ff3, 0x0 }, { 0x1ffc, 0x0 }, { 0x3a9, 0x399, 0x0 } };
special_casing_map[93] = { 0x1ffc, { 0x1ff3, 0x0 }, { 0x1ffc, 0x0 }, { 0x3a9, 0x399, 0x0 } };
special_casing_map[94] = { 0x1fb2, { 0x1fb2, 0x0 }, { 0x1fba, 0x345, 0x0 }, { 0x1fba, 0x399, 0x0 } };
special_casing_map[95] = { 0x1fb4, { 0x1fb4, 0x0 }, { 0x386, 0x345, 0x0 }, { 0x386, 0x399, 0x0 } };
special_casing_map[96] = { 0x1fc2, { 0x1fc2, 0x0 }, { 0x1fca, 0x345, 0x0 }, { 0x1fca, 0x399, 0x0 } };
special_casing_map[97] = { 0x1fc4, { 0x1fc4, 0x0 }, { 0x389, 0x345, 0x0 }, { 0x389, 0x399, 0x0 } };
special_casing_map[98] = { 0x1ff2, { 0x1ff2, 0x0 }, { 0x1ffa, 0x345, 0x0 }, { 0x1ffa, 0x399, 0x0 } };
special_casing_map[99] = { 0x1ff4, { 0x1ff4, 0x0 }, { 0x38f, 0x345, 0x0 }, { 0x38f, 0x399, 0x0 } };
special_casing_map[100] = { 0x1fb7, { 0x1fb7, 0x0 }, { 0x391, 0x342, 0x345 }, { 0x391, 0x342, 0x399 } };
special_casing_map[101] = { 0x1fc7, { 0x1fc7, 0x0 }, { 0x397, 0x342, 0x345 }, { 0x397, 0x342, 0x399 } };
special_casing_map[102] = { 0x1ff7, { 0x1ff7, 0x0 }, { 0x3a9, 0x342, 0x345 }, { 0x3a9, 0x342, 0x399 } };
}

}
Loading
Loading