Packages
localize
0.1.0
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.41.3
0.41.2
0.41.1
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.1
0.30.0
retired
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
0.1.0-alpha.1
Localization (parsing, formatting) of numbers, dates/time/calendar, units of measure, messages and lists. Includes localized collation.
Current section
Files
Jump to
Current section
Files
lib/localize/collation/unicode.ex
defmodule Localize.Collation.Unicode do
@moduledoc false
# Provides Unicode Character Database lookups for the collation
# system: canonical combining class and decimal digit detection.
#
# Data is loaded from pre-generated ETF files in
# `priv/localize/supplemental_data/` and cached in
# `:persistent_term` on first access.
@combining_classes_key {:localize, :combining_classes}
@decimal_digit_ranges_key {:localize, :decimal_digit_ranges}
@doc false
@spec combining_class(non_neg_integer()) :: non_neg_integer()
def combining_class(codepoint) do
classes = load_combining_classes()
Map.get(classes, codepoint, 0)
end
@doc false
@spec decimal_digit?(non_neg_integer()) :: boolean()
def decimal_digit?(codepoint) do
ranges = load_decimal_digit_ranges()
in_ranges?(codepoint, ranges)
end
defp load_combining_classes do
Localize.DataLoader.load(@combining_classes_key, fn ->
load_etf("combining_classes.etf")
end)
end
defp load_decimal_digit_ranges do
Localize.DataLoader.load(@decimal_digit_ranges_key, fn ->
load_etf("decimal_digit_ranges.etf")
end)
end
defp load_etf(filename) do
:localize
|> Application.app_dir(["priv", "localize", "supplemental_data", filename])
|> File.read!()
|> :erlang.binary_to_term()
end
# Binary search over sorted {start, finish} ranges.
defp in_ranges?(codepoint, ranges) do
binary_search(codepoint, ranges, 0, length(ranges) - 1)
end
defp binary_search(_cp, _ranges, low, high) when low > high, do: false
defp binary_search(cp, ranges, low, high) do
mid = div(low + high, 2)
{range_start, range_end} = Enum.at(ranges, mid)
cond do
cp < range_start -> binary_search(cp, ranges, low, mid - 1)
cp > range_end -> binary_search(cp, ranges, mid + 1, high)
true -> true
end
end
end