/* * Copyright 2023 Stephen Tetley * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */////// Functions for working with Unicode code points.////// The `CodePoint` module complements the `Char` module. `Char` only/// represents characters in Unicode's _Basic Multilingual Plane_/// (U+0000 to U+FFFF)./// CodePoint extends access to include _supplementary characters_ so all/// Unicode characters can be represented.///pubmod CodePoint {import java.lang.Characterimport java.lang.IllegalArgumentException////// Returns the minimum integer value of a Unicode code point.///pubdefminValue(): Int32 = Character.MIN_CODE_POINT////// Returns the maximum integer value of a Unicode code point.///pubdefmaxValue(): Int32 = Character.MAX_CODE_POINT////// Returns `true` if the given char `c` is an ascii character.///pubdefisAscii(cp: Int32): Bool =0x0000<=cpandcp<=0x0080////// Returns `true` if the given code point `cp` represents a letter character.///pubdefisLetter(cp: Int32): Bool = Character.isLetter(cp)////// Returns `true` if the given code point `cp` represents a recognized Unicode digit./// This includes the ASCII range 0..9 but also Arabic-Indic digits, Devagari digits and Fullwidth digits.///pubdefisDigit(cp: Int32): Bool = Character.isDigit(cp)////// Returns `true` if the given code point `cp` represents a recognized Unicode letter or digit.///pubdefisLetterOrDigit(cp: Int32): Bool = Character.isLetterOrDigit(cp)////// Returns `true` if the given code point `cp` represents a character strictly in the/// range of ASCII digits 0...9.///pubdefisAsciiDigit(cp: Int32): Bool =isAscii(cp) andisDigit(cp)////// Returns `true` if the given code point `cp` represents a character in the range 0...7.///pubdefisOctDigit(cp: Int32): Bool =0x0030<=cpandcp<=0x0037// '0'..'7'////// Returns `true` if the given code point `cp` represents a character in the range 0...F.///pubdefisHexDigit(cp: Int32): Bool = matchcp {caseiif0x0030<=iandi<=0x0039 => true// '0'..'9'caseiif0x0041<=iandi<=0x0046 => true// 'A'..'F'caseiif0x0061<=iandi<=0x0066 => true// 'a'..'f'case_ => false }////// Returns `true` if the given code point `cp` represents a lowercase letter.///pubdefisLowerCase(cp: Int32): Bool = Character.isLowerCase(cp)////// Returns `true` if the given code point `cp` represents an uppercase letter.///pubdefisUpperCase(cp: Int32): Bool = Character.isUpperCase(cp)////// Returns `true` if the given code point `cp` represents a titlecase letter.///pubdefisTitleCase(cp: Int32): Bool = Character.isTitleCase(cp)////// Returns `true` if the given code point `cp` represents a white space character.///pubdefisWhitespace(cp: Int32): Bool = Character.isWhitespace(cp)////// Returns `true` if the given code point `cp` represents an alphabetic character.///pubdefisAlphabetic(cp: Int32): Bool = Character.isAlphabetic(cp)////// Returns `true` if the given code point `cp` is within Unicode's Basic Multilingual Plane.////// If the code point is within the BMP it can be represented by Flix's `Char` datatype.///pubdefisBmpCodePoint(cp: Int32): Bool = Character.isBmpCodePoint(cp)////// Returns `true` if the given code point `cp` is defined either as a entry in the/// UnicodeData file or a value within a range defined in the UnicodeData file.///pubdefisDefined(cp: Int32): Bool = Character.isDefined(cp)////// Returns `true` if the given code point `cp` is Chinese, Japanase, Korean/// or Vietnamese ideograph.///pubdefisIdeographic(cp: Int32): Bool = Character.isIdeographic(cp)////// Returns `true` if the given code point `cp` is an ISO control character.///pubdefisISOControl(cp: Int32): Bool = Character.isISOControl(cp)////// Returns `true` if the given code point `cp` is mirrored.///pubdefisMirrored(cp: Int32): Bool = Character.isMirrored(cp)////// Returns `true` if the given code point `cp` is in Unicode's supplementary character range.///pubdefisSupplementaryCodePoint(cp: Int32): Bool = Character.isSupplementaryCodePoint(cp)////// Returns `true` if the code point `cp` is between `U+0000` and `U+10FFFF`.///pubdefisValidCodePoint(cp: Int32): Bool = Character.isValidCodePoint(cp)////// Converts a code point representing a letter to its lowercase version.////// Returns the original code point if it does not have a lowercase version.///pubdeftoLowerCase(cp: Int32): Int32 = Character.toLowerCase(cp)////// Converts a code point representing a letter to its uppercase version.////// Returns the original code point if it does not have a uppercase version.///pubdeftoUpperCase(cp: Int32): Int32 = Character.toUpperCase(cp)////// Converts a code point representing a letter to its titlecase version.////// Returns the original character if it does not have either a titlecase/// version or a mapping to uppercase.///pubdeftoTitleCase(cp: Int32): Int32 = Character.toTitleCase(cp)////// Returns the name of the code point `cp`.////// See the Java JDK documentation of the method `java.lang.Character.getName` for a full/// description of how names are derived.///pubdefgetName(cp: Int32): Option[String] =try { Character.getName(cp) |> Object.toOption } catch {case_: IllegalArgumentException => None }////// Returns the integer value represented by the code point `cp` e.g. code point 0x0031/// which is the char '1' returns `Some(1)`.////// Returns `None` if `cp` does not represent a number.////// This function handles supplementary characters.///pubdefgetNumericValue(cp: Int32): Option[Int32] =match Character.getNumericValue(cp) {caseiifi<0 => Nonecasei => Some(i) }////// Returns the number of Chars needed to represent the code point `cp`.////// The answer is either 2 for a supplementary character or 1 for any other character.///pubdefcharCount(cp: Int32): Int32 = Character.charCount(cp)////// Optionally returns a vector of Chars representing the code point `cp`.////// A valid `Some(_)` answer is either a length 2 Vector for a supplementary character/// or a length 1 Vector for any other valid character.////// Returns 'None' if `cp` is not a valid code point.///pubdeftoChars(cp: Int32): Option[Vector[Char]] = try {regionrc {letarr: Array[Char, rc] = Array.empty(rc, 2);letsize = unchecked_cast(Character.toChars(cp, arr, 0) as _ \ rc);Array.toVector(arr) |> Vector.takeLeft(size) |> Some } } catch {case_: IllegalArgumentException => None }////// Optionally returns a Char represention the code point `cp` if `cp` is within/// Unicode's Basic Multilingual Plane.///pubdeftoBmpChar(cp: Int32): Option[Char] = try {regionrc {letarr: Array[Char, rc] = Array.empty(rc, 2);leti = Character.toChars(cp, arr, 0);if (i==1)Array.nth(0, arr)else None } } catch {case_: IllegalArgumentException => None }////// Optionally returns a pair of Chars representing the high and low surrogate characters of the/// code point `cp` if `cp` is a supplementary character.///pubdeftoSupplementaryChars(cp: Int32): Option[(Char, Char)] = try {regionrc {letarr: Array[Char, rc] = Array.empty(rc, 2);leti = Character.toChars(cp, arr, 0);if (i==2) Some((Array.get(0, arr), Array.get(1, arr)))else None } } catch {case_: IllegalArgumentException => None }////// Returns a String representing the code point `cp`.///pubdeftoString(cp: Int32): String =try { Character.toString(cp) } catch {case_: IllegalArgumentException => "" }////// Optionally returns the high surrogate character of the code point `cp`/// if `cp` is a supplementary character.///pubdefhighSurrogate(cp: Int32): Option[Char] =if (isSupplementaryCodePoint(cp)) Some(Character.highSurrogate(cp))else None////// Optionally returns the low surrogate character of the code point `cp`/// if `cp` is a supplementary character.///pubdeflowSurrogate(cp: Int32): Option[Char] =if (isSupplementaryCodePoint(cp)) Some(Character.lowSurrogate(cp))else None}