aboutsummaryrefslogtreecommitdiff
path: root/libcore/char.rs
diff options
context:
space:
mode:
authorpravic <[email protected]>2016-04-12 17:47:49 +0300
committerpravic <[email protected]>2016-04-12 17:47:49 +0300
commit91d227b219446d3a8b13f5bf7eb87bfc78a8b339 (patch)
tree0e438aefd2b3cf07354a68595d5aa4ed73f81f15 /libcore/char.rs
parentadd native import libraries (diff)
downloadkmd-env-rs-91d227b219446d3a8b13f5bf7eb87bfc78a8b339.tar.xz
kmd-env-rs-91d227b219446d3a8b13f5bf7eb87bfc78a8b339.zip
add libcore from 2016-04-11 nightly
Diffstat (limited to 'libcore/char.rs')
-rw-r--r--libcore/char.rs634
1 files changed, 634 insertions, 0 deletions
diff --git a/libcore/char.rs b/libcore/char.rs
new file mode 100644
index 0000000..b2b1dc5
--- /dev/null
+++ b/libcore/char.rs
@@ -0,0 +1,634 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Character manipulation.
+//!
+//! For more details, see ::rustc_unicode::char (a.k.a. std::char)
+
+#![allow(non_snake_case)]
+#![stable(feature = "core_char", since = "1.2.0")]
+
+use iter::Iterator;
+use mem::transmute;
+use option::Option::{None, Some};
+use option::Option;
+use slice::SliceExt;
+
+// UTF-8 ranges and tags for encoding characters
+const TAG_CONT: u8 = 0b1000_0000;
+const TAG_TWO_B: u8 = 0b1100_0000;
+const TAG_THREE_B: u8 = 0b1110_0000;
+const TAG_FOUR_B: u8 = 0b1111_0000;
+const MAX_ONE_B: u32 = 0x80;
+const MAX_TWO_B: u32 = 0x800;
+const MAX_THREE_B: u32 = 0x10000;
+
+/*
+ Lu Uppercase_Letter an uppercase letter
+ Ll Lowercase_Letter a lowercase letter
+ Lt Titlecase_Letter a digraphic character, with first part uppercase
+ Lm Modifier_Letter a modifier letter
+ Lo Other_Letter other letters, including syllables and ideographs
+ Mn Nonspacing_Mark a nonspacing combining mark (zero advance width)
+ Mc Spacing_Mark a spacing combining mark (positive advance width)
+ Me Enclosing_Mark an enclosing combining mark
+ Nd Decimal_Number a decimal digit
+ Nl Letter_Number a letterlike numeric character
+ No Other_Number a numeric character of other type
+ Pc Connector_Punctuation a connecting punctuation mark, like a tie
+ Pd Dash_Punctuation a dash or hyphen punctuation mark
+ Ps Open_Punctuation an opening punctuation mark (of a pair)
+ Pe Close_Punctuation a closing punctuation mark (of a pair)
+ Pi Initial_Punctuation an initial quotation mark
+ Pf Final_Punctuation a final quotation mark
+ Po Other_Punctuation a punctuation mark of other type
+ Sm Math_Symbol a symbol of primarily mathematical use
+ Sc Currency_Symbol a currency sign
+ Sk Modifier_Symbol a non-letterlike modifier symbol
+ So Other_Symbol a symbol of other type
+ Zs Space_Separator a space character (of various non-zero widths)
+ Zl Line_Separator U+2028 LINE SEPARATOR only
+ Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only
+ Cc Control a C0 or C1 control code
+ Cf Format a format control character
+ Cs Surrogate a surrogate code point
+ Co Private_Use a private-use character
+ Cn Unassigned a reserved unassigned code point or a noncharacter
+*/
+
+/// The highest valid code point a `char` can have.
+///
+/// A [`char`] is a [Unicode Scalar Value], which means that it is a [Code
+/// Point], but only ones within a certain range. `MAX` is the highest valid
+/// code point that's a valid [Unicode Scalar Value].
+///
+/// [`char`]: ../../std/primitive.char.html
+/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
+/// [Code Point]: http://www.unicode.org/glossary/#code_point
+#[stable(feature = "rust1", since = "1.0.0")]
+pub const MAX: char = '\u{10ffff}';
+
+/// Converts a `u32` to a `char`.
+///
+/// Note that all [`char`]s are valid [`u32`]s, and can be casted to one with
+/// [`as`]:
+///
+/// ```
+/// let c = '💯';
+/// let i = c as u32;
+///
+/// assert_eq!(128175, i);
+/// ```
+///
+/// However, the reverse is not true: not all valid [`u32`]s are valid
+/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
+/// for a [`char`].
+///
+/// [`char`]: ../../std/primitive.char.html
+/// [`u32`]: ../../std/primitive.u32.html
+/// [`as`]: ../../book/casting-between-types.html#as
+///
+/// For an unsafe version of this function which ignores these checks, see
+/// [`from_u32_unchecked()`].
+///
+/// [`from_u32_unchecked()`]: fn.from_u32_unchecked.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_u32(0x2764);
+///
+/// assert_eq!(Some('❤'), c);
+/// ```
+///
+/// Returning `None` when the input is not a valid [`char`]:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_u32(0x110000);
+///
+/// assert_eq!(None, c);
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn from_u32(i: u32) -> Option<char> {
+ // catch out-of-bounds and surrogates
+ if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
+ None
+ } else {
+ Some(unsafe { from_u32_unchecked(i) })
+ }
+}
+
+/// Converts a `u32` to a `char`, ignoring validity.
+///
+/// Note that all [`char`]s are valid [`u32`]s, and can be casted to one with
+/// [`as`]:
+///
+/// ```
+/// let c = '💯';
+/// let i = c as u32;
+///
+/// assert_eq!(128175, i);
+/// ```
+///
+/// However, the reverse is not true: not all valid [`u32`]s are valid
+/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
+/// [`char`], possibly creating an invalid one.
+///
+/// [`char`]: ../../std/primitive.char.html
+/// [`u32`]: ../../std/primitive.u32.html
+/// [`as`]: ../../book/casting-between-types.html#as
+///
+/// # Safety
+///
+/// This function is unsafe, as it may construct invalid `char` values.
+///
+/// For a safe version of this function, see the [`from_u32()`] function.
+///
+/// [`from_u32()`]: fn.from_u32.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char;
+///
+/// let c = unsafe { char::from_u32_unchecked(0x2764) };
+///
+/// assert_eq!('❤', c);
+/// ```
+#[inline]
+#[stable(feature = "char_from_unchecked", since = "1.5.0")]
+pub unsafe fn from_u32_unchecked(i: u32) -> char {
+ transmute(i)
+}
+
+/// Converts a digit in the given radix to a `char`.
+///
+/// A 'radix' here is sometimes also called a 'base'. A radix of two
+/// indicates a binary number, a radix of ten, decimal, and a radix of
+/// sixteen, hexadecimal, to give some common values. Arbitrary
+/// radicum are supported.
+///
+/// `from_digit()` will return `None` if the input is not a digit in
+/// the given radix.
+///
+/// # Panics
+///
+/// Panics if given a radix larger than 36.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_digit(4, 10);
+///
+/// assert_eq!(Some('4'), c);
+///
+/// // Decimal 11 is a single digit in base 16
+/// let c = char::from_digit(11, 16);
+///
+/// assert_eq!(Some('b'), c);
+/// ```
+///
+/// Returning `None` when the input is not a digit:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_digit(20, 10);
+///
+/// assert_eq!(None, c);
+/// ```
+///
+/// Passing a large radix, causing a panic:
+///
+/// ```
+/// use std::thread;
+/// use std::char;
+///
+/// let result = thread::spawn(|| {
+/// // this panics
+/// let c = char::from_digit(1, 37);
+/// }).join();
+///
+/// assert!(result.is_err());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn from_digit(num: u32, radix: u32) -> Option<char> {
+ if radix > 36 {
+ panic!("from_digit: radix is too high (maximum 36)");
+ }
+ if num < radix {
+ let num = num as u8;
+ if num < 10 {
+ Some((b'0' + num) as char)
+ } else {
+ Some((b'a' + num - 10) as char)
+ }
+ } else {
+ None
+ }
+}
+
+// NB: the stabilization and documentation for this trait is in
+// unicode/char.rs, not here
+#[allow(missing_docs)] // docs in libunicode/u_char.rs
+#[doc(hidden)]
+#[unstable(feature = "core_char_ext",
+ reason = "the stable interface is `impl char` in later crate",
+ issue = "32110")]
+pub trait CharExt {
+ #[stable(feature = "core", since = "1.6.0")]
+ fn is_digit(self, radix: u32) -> bool;
+ #[stable(feature = "core", since = "1.6.0")]
+ fn to_digit(self, radix: u32) -> Option<u32>;
+ #[stable(feature = "core", since = "1.6.0")]
+ fn escape_unicode(self) -> EscapeUnicode;
+ #[stable(feature = "core", since = "1.6.0")]
+ fn escape_default(self) -> EscapeDefault;
+ #[stable(feature = "core", since = "1.6.0")]
+ fn len_utf8(self) -> usize;
+ #[stable(feature = "core", since = "1.6.0")]
+ fn len_utf16(self) -> usize;
+ #[unstable(feature = "unicode", issue = "27784")]
+ fn encode_utf8(self) -> EncodeUtf8;
+ #[unstable(feature = "unicode", issue = "27784")]
+ fn encode_utf16(self) -> EncodeUtf16;
+}
+
+#[stable(feature = "core", since = "1.6.0")]
+impl CharExt for char {
+ #[inline]
+ fn is_digit(self, radix: u32) -> bool {
+ self.to_digit(radix).is_some()
+ }
+
+ #[inline]
+ fn to_digit(self, radix: u32) -> Option<u32> {
+ if radix > 36 {
+ panic!("to_digit: radix is too high (maximum 36)");
+ }
+ let val = match self {
+ '0' ... '9' => self as u32 - '0' as u32,
+ 'a' ... 'z' => self as u32 - 'a' as u32 + 10,
+ 'A' ... 'Z' => self as u32 - 'A' as u32 + 10,
+ _ => return None,
+ };
+ if val < radix { Some(val) }
+ else { None }
+ }
+
+ #[inline]
+ fn escape_unicode(self) -> EscapeUnicode {
+ EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash }
+ }
+
+ #[inline]
+ fn escape_default(self) -> EscapeDefault {
+ let init_state = match self {
+ '\t' => EscapeDefaultState::Backslash('t'),
+ '\r' => EscapeDefaultState::Backslash('r'),
+ '\n' => EscapeDefaultState::Backslash('n'),
+ '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
+ '\x20' ... '\x7e' => EscapeDefaultState::Char(self),
+ _ => EscapeDefaultState::Unicode(self.escape_unicode())
+ };
+ EscapeDefault { state: init_state }
+ }
+
+ #[inline]
+ fn len_utf8(self) -> usize {
+ let code = self as u32;
+ if code < MAX_ONE_B {
+ 1
+ } else if code < MAX_TWO_B {
+ 2
+ } else if code < MAX_THREE_B {
+ 3
+ } else {
+ 4
+ }
+ }
+
+ #[inline]
+ fn len_utf16(self) -> usize {
+ let ch = self as u32;
+ if (ch & 0xFFFF) == ch { 1 } else { 2 }
+ }
+
+ #[inline]
+ fn encode_utf8(self) -> EncodeUtf8 {
+ let code = self as u32;
+ let mut buf = [0; 4];
+ let pos = if code < MAX_ONE_B {
+ buf[3] = code as u8;
+ 3
+ } else if code < MAX_TWO_B {
+ buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
+ buf[3] = (code & 0x3F) as u8 | TAG_CONT;
+ 2
+ } else if code < MAX_THREE_B {
+ buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
+ buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
+ buf[3] = (code & 0x3F) as u8 | TAG_CONT;
+ 1
+ } else {
+ buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
+ buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
+ buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
+ buf[3] = (code & 0x3F) as u8 | TAG_CONT;
+ 0
+ };
+ EncodeUtf8 { buf: buf, pos: pos }
+ }
+
+ #[inline]
+ fn encode_utf16(self) -> EncodeUtf16 {
+ let mut buf = [0; 2];
+ let mut code = self as u32;
+ let pos = if (code & 0xFFFF) == code {
+ // The BMP falls through (assuming non-surrogate, as it should)
+ buf[1] = code as u16;
+ 1
+ } else {
+ // Supplementary planes break into surrogates.
+ code -= 0x1_0000;
+ buf[0] = 0xD800 | ((code >> 10) as u16);
+ buf[1] = 0xDC00 | ((code as u16) & 0x3FF);
+ 0
+ };
+ EncodeUtf16 { buf: buf, pos: pos }
+ }
+}
+
+/// Returns an iterator that yields the hexadecimal Unicode escape of a
+/// character, as `char`s.
+///
+/// This `struct` is created by the [`escape_unicode()`] method on [`char`]. See
+/// its documentation for more.
+///
+/// [`escape_unicode()`]: ../../std/primitive.char.html#method.escape_unicode
+/// [`char`]: ../../std/primitive.char.html
+#[derive(Clone, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct EscapeUnicode {
+ c: char,
+ state: EscapeUnicodeState
+}
+
+#[derive(Clone, Debug)]
+enum EscapeUnicodeState {
+ Backslash,
+ Type,
+ LeftBrace,
+ Value(usize),
+ RightBrace,
+ Done,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EscapeUnicode {
+ type Item = char;
+
+ fn next(&mut self) -> Option<char> {
+ match self.state {
+ EscapeUnicodeState::Backslash => {
+ self.state = EscapeUnicodeState::Type;
+ Some('\\')
+ }
+ EscapeUnicodeState::Type => {
+ self.state = EscapeUnicodeState::LeftBrace;
+ Some('u')
+ }
+ EscapeUnicodeState::LeftBrace => {
+ let mut n = 0;
+ while (self.c as u32) >> (4 * (n + 1)) != 0 {
+ n += 1;
+ }
+ self.state = EscapeUnicodeState::Value(n);
+ Some('{')
+ }
+ EscapeUnicodeState::Value(offset) => {
+ let c = from_digit(((self.c as u32) >> (offset * 4)) & 0xf, 16).unwrap();
+ if offset == 0 {
+ self.state = EscapeUnicodeState::RightBrace;
+ } else {
+ self.state = EscapeUnicodeState::Value(offset - 1);
+ }
+ Some(c)
+ }
+ EscapeUnicodeState::RightBrace => {
+ self.state = EscapeUnicodeState::Done;
+ Some('}')
+ }
+ EscapeUnicodeState::Done => None,
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let mut n = 0;
+ while (self.c as usize) >> (4 * (n + 1)) != 0 {
+ n += 1;
+ }
+ let n = match self.state {
+ EscapeUnicodeState::Backslash => n + 5,
+ EscapeUnicodeState::Type => n + 4,
+ EscapeUnicodeState::LeftBrace => n + 3,
+ EscapeUnicodeState::Value(offset) => offset + 2,
+ EscapeUnicodeState::RightBrace => 1,
+ EscapeUnicodeState::Done => 0,
+ };
+ (n, Some(n))
+ }
+}
+
+/// An iterator that yields the literal escape code of a `char`.
+///
+/// This `struct` is created by the [`escape_default()`] method on [`char`]. See
+/// its documentation for more.
+///
+/// [`escape_default()`]: ../../std/primitive.char.html#method.escape_default
+/// [`char`]: ../../std/primitive.char.html
+#[derive(Clone, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct EscapeDefault {
+ state: EscapeDefaultState
+}
+
+#[derive(Clone, Debug)]
+enum EscapeDefaultState {
+ Backslash(char),
+ Char(char),
+ Done,
+ Unicode(EscapeUnicode),
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EscapeDefault {
+ type Item = char;
+
+ fn next(&mut self) -> Option<char> {
+ match self.state {
+ EscapeDefaultState::Backslash(c) => {
+ self.state = EscapeDefaultState::Char(c);
+ Some('\\')
+ }
+ EscapeDefaultState::Char(c) => {
+ self.state = EscapeDefaultState::Done;
+ Some(c)
+ }
+ EscapeDefaultState::Done => None,
+ EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ match self.state {
+ EscapeDefaultState::Char(_) => (1, Some(1)),
+ EscapeDefaultState::Backslash(_) => (2, Some(2)),
+ EscapeDefaultState::Unicode(ref iter) => iter.size_hint(),
+ EscapeDefaultState::Done => (0, Some(0)),
+ }
+ }
+
+ fn count(self) -> usize {
+ match self.state {
+ EscapeDefaultState::Char(_) => 1,
+ EscapeDefaultState::Unicode(iter) => iter.count(),
+ EscapeDefaultState::Done => 0,
+ EscapeDefaultState::Backslash(_) => 2,
+ }
+ }
+
+ fn nth(&mut self, n: usize) -> Option<char> {
+ match self.state {
+ EscapeDefaultState::Backslash(c) if n == 0 => {
+ self.state = EscapeDefaultState::Char(c);
+ Some('\\')
+ },
+ EscapeDefaultState::Backslash(c) if n == 1 => {
+ self.state = EscapeDefaultState::Done;
+ Some(c)
+ },
+ EscapeDefaultState::Backslash(_) => {
+ self.state = EscapeDefaultState::Done;
+ None
+ },
+ EscapeDefaultState::Char(c) => {
+ self.state = EscapeDefaultState::Done;
+
+ if n == 0 {
+ Some(c)
+ } else {
+ None
+ }
+ },
+ EscapeDefaultState::Done => return None,
+ EscapeDefaultState::Unicode(ref mut i) => return i.nth(n),
+ }
+ }
+
+ fn last(self) -> Option<char> {
+ match self.state {
+ EscapeDefaultState::Unicode(iter) => iter.last(),
+ EscapeDefaultState::Done => None,
+ EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c),
+ }
+ }
+}
+
+/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
+/// value.
+///
+/// Constructed via the `.encode_utf8()` method on `char`.
+#[unstable(feature = "unicode", issue = "27784")]
+#[derive(Debug)]
+pub struct EncodeUtf8 {
+ buf: [u8; 4],
+ pos: usize,
+}
+
+impl EncodeUtf8 {
+ /// Returns the remaining bytes of this iterator as a slice.
+ #[unstable(feature = "unicode", issue = "27784")]
+ pub fn as_slice(&self) -> &[u8] {
+ &self.buf[self.pos..]
+ }
+}
+
+#[unstable(feature = "unicode", issue = "27784")]
+impl Iterator for EncodeUtf8 {
+ type Item = u8;
+
+ fn next(&mut self) -> Option<u8> {
+ if self.pos == self.buf.len() {
+ None
+ } else {
+ let ret = Some(self.buf[self.pos]);
+ self.pos += 1;
+ ret
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.as_slice().iter().size_hint()
+ }
+}
+
+/// An iterator over `u16` entries represending the UTF-16 encoding of a `char`
+/// value.
+///
+/// Constructed via the `.encode_utf16()` method on `char`.
+#[unstable(feature = "unicode", issue = "27784")]
+#[derive(Debug)]
+pub struct EncodeUtf16 {
+ buf: [u16; 2],
+ pos: usize,
+}
+
+impl EncodeUtf16 {
+ /// Returns the remaining bytes of this iterator as a slice.
+ #[unstable(feature = "unicode", issue = "27784")]
+ pub fn as_slice(&self) -> &[u16] {
+ &self.buf[self.pos..]
+ }
+}
+
+
+#[unstable(feature = "unicode", issue = "27784")]
+impl Iterator for EncodeUtf16 {
+ type Item = u16;
+
+ fn next(&mut self) -> Option<u16> {
+ if self.pos == self.buf.len() {
+ None
+ } else {
+ let ret = Some(self.buf[self.pos]);
+ self.pos += 1;
+ ret
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.as_slice().iter().size_hint()
+ }
+}