Packages
localize
0.13.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/utils/string.ex
defmodule Localize.Utils.String do
@moduledoc """
String manipulation functions not provided in the standard library.
Provides utilities for hashing strings, converting between
naming conventions (camelCase to snake_case), and character
case conversion.
"""
@p 99991
@m trunc(1.0e9) + 9
@doc """
Hashes a string using a polynomial rolling hash function.
See https://cp-algorithms.com/string/string-hashing.html for
a description of the algorithm.
### Arguments
* `string` — the string to hash.
### Returns
* A non-negative integer hash value.
### Examples
iex> Localize.Utils.String.hash("hello")
61_454_117
"""
@spec hash(String.t()) :: non_neg_integer()
def hash(string) do
{hash, _} =
string
|> String.to_charlist()
|> Enum.reduce({0, 1}, fn char, {hash, p_pow} ->
hash = rem(hash + char * p_pow, @m)
p_pow = rem(p_pow * @p, @m)
{hash, p_pow}
end)
hash
end
@doc """
Replaces hyphens with underscores in a string.
### Arguments
* `string` — the string to transform.
### Returns
* A new string with all `"-"` characters replaced by `"_"`.
### Examples
iex> Localize.Utils.String.to_underscore("this-one")
"this_one"
"""
@spec to_underscore(String.t()) :: String.t()
def to_underscore(string) when is_binary(string) do
String.replace(string, "-", "_")
end
@doc """
Converts a CamelCase or PascalCase string or atom to snake_case.
This is a modified version of `Macro.underscore/1` that correctly
handles strings containing underscores between capitalized words
(e.g., `"This_That"` becomes `"this_that"` instead of `"this__that"`).
### Arguments
* `value` — an atom or string to convert.
### Returns
* A snake_case string.
### Examples
iex> Localize.Utils.String.underscore("HelloWorld")
"hello_world"
iex> Localize.Utils.String.underscore("This_That")
"this_that"
"""
@spec underscore(atom() | String.t()) :: String.t()
def underscore(atom) when is_atom(atom) do
"Elixir." <> rest = Atom.to_string(atom)
underscore(rest)
end
def underscore(<<h, t::binary>>) do
<<to_lower_char(h)>> <> do_underscore(t, h)
end
def underscore("") do
""
end
# h is upper case, next char is not uppercase, or a _ or . => and prev != _
defp do_underscore(<<h, t, rest::binary>>, prev)
when h >= ?A and h <= ?Z and not (t >= ?A and t <= ?Z) and t != ?. and t != ?_ and
prev != ?_ do
<<?_, to_lower_char(h), t>> <> do_underscore(rest, t)
end
# h is uppercase, previous was not uppercase or _
defp do_underscore(<<h, t::binary>>, prev)
when h >= ?A and h <= ?Z and not (prev >= ?A and prev <= ?Z) and prev != ?_ do
<<?_, to_lower_char(h)>> <> do_underscore(t, h)
end
# h is .
defp do_underscore(<<?., t::binary>>, _) do
<<?/>> <> underscore(t)
end
# Any other char
defp do_underscore(<<h, t::binary>>, _) do
<<to_lower_char(h)>> <> do_underscore(t, h)
end
defp do_underscore(<<>>, _) do
<<>>
end
@doc """
Converts a single character to its uppercase equivalent.
Only operates on ASCII lowercase letters (a-z).
### Arguments
* `char` — an integer codepoint.
### Returns
* The uppercase codepoint if the input is a lowercase ASCII letter, otherwise the input unchanged.
"""
@spec to_upper_char(integer()) :: integer()
def to_upper_char(char) when char >= ?a and char <= ?z, do: char - 32
def to_upper_char(char), do: char
@doc """
Converts a single character to its lowercase equivalent.
Only operates on ASCII uppercase letters (A-Z).
### Arguments
* `char` — an integer codepoint.
### Returns
* The lowercase codepoint if the input is an uppercase ASCII letter, otherwise the input unchanged.
"""
@spec to_lower_char(integer()) :: integer()
def to_lower_char(char) when char >= ?A and char <= ?Z, do: char + 32
def to_lower_char(char), do: char
end