mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
224 lines
5.3 KiB
Swift
224 lines
5.3 KiB
Swift
//===----------------------------------------------------------------------===//
|
||
// Char Type
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
struct Char : BuiltinCharacterLiteralConvertible, CharacterLiteralConvertible {
|
||
var _value : Builtin.Int32
|
||
|
||
var value : UInt32 {
|
||
get:
|
||
return UInt32(_value)
|
||
}
|
||
|
||
static func _convertFromBuiltinCharacterLiteral(val : Builtin.Int32) -> Char {
|
||
return Char(val)
|
||
}
|
||
|
||
typealias CharacterLiteralType = Char
|
||
static func convertFromCharacterLiteral(value : Char) -> Char {
|
||
return value
|
||
}
|
||
|
||
constructor() {
|
||
this._value = Int32(0).value
|
||
}
|
||
|
||
constructor(value : Builtin.Int32) {
|
||
this._value = value
|
||
}
|
||
|
||
constructor(v : UInt32) {
|
||
var lowHalf = v & 0xFFFF
|
||
// reserved in each plane
|
||
debugTrap(lowHalf != 0xFFFE && lowHalf != 0xFFFF)
|
||
// UTF-16 surrogate pair values are not valid code points
|
||
debugTrap(v < 0xD800 || v > 0xDFFF)
|
||
// U+FDD0...U+FDEF are also reserved
|
||
debugTrap(v < 0xFDD0 || v > 0xFDEF)
|
||
// beyond what is defined to be valid
|
||
debugTrap(v < 0x10FFFF)
|
||
|
||
this._value = v.value
|
||
}
|
||
|
||
func replPrint() {
|
||
print('\'')
|
||
replPrintCharBody()
|
||
print('\'')
|
||
}
|
||
|
||
func replPrintCharBody() {
|
||
if this == '\\' {
|
||
print('\\')
|
||
print('\\')
|
||
} else if this == '"' {
|
||
print('\\')
|
||
print('"')
|
||
} else if this == '\'' {
|
||
print('\\')
|
||
print('\'')
|
||
} else if isPrint() {
|
||
print(this)
|
||
} else if this == '\0' {
|
||
print('\\')
|
||
print('0')
|
||
} else if this == '\n' {
|
||
print('\\')
|
||
print('n')
|
||
} else if this == '\r' {
|
||
print('\\')
|
||
print('r')
|
||
} else if this == '\t' {
|
||
print('\\')
|
||
print('t')
|
||
} else if UInt32(this) < 128 {
|
||
print('\\')
|
||
print('x')
|
||
_printNibbleAsHex(UInt32(this) >> 4)
|
||
_printNibbleAsHex(UInt32(this))
|
||
} else if _isUTF8() {
|
||
print(this)
|
||
} else if UInt32(this) <= 0xFFFF {
|
||
print('\\')
|
||
print('u')
|
||
_printNibbleAsHex(UInt32(this) >> 12)
|
||
_printNibbleAsHex(UInt32(this) >> 8)
|
||
_printNibbleAsHex(UInt32(this) >> 4)
|
||
_printNibbleAsHex(UInt32(this))
|
||
} else {
|
||
print('\\')
|
||
print('U')
|
||
_printNibbleAsHex(UInt32(this) >> 28)
|
||
_printNibbleAsHex(UInt32(this) >> 24)
|
||
_printNibbleAsHex(UInt32(this) >> 20)
|
||
_printNibbleAsHex(UInt32(this) >> 16)
|
||
_printNibbleAsHex(UInt32(this) >> 12)
|
||
_printNibbleAsHex(UInt32(this) >> 8)
|
||
_printNibbleAsHex(UInt32(this) >> 4)
|
||
_printNibbleAsHex(UInt32(this))
|
||
}
|
||
}
|
||
|
||
// FIXME: Move to nested function when IRGen supports it.
|
||
func _printNibbleAsHex(v : UInt32) {
|
||
v = v & 15
|
||
if v < 10 {
|
||
print(Char(v+48)) // 48 = '0'
|
||
} else {
|
||
print(Char(v-10+65)) // 65 = 'A'
|
||
}
|
||
}
|
||
|
||
/// \returns true if this is an ASCII character (code point 0 to 127
|
||
/// inclusive).
|
||
func isASCII() -> Bool {
|
||
return value <= 127
|
||
}
|
||
|
||
// FIXME: Locales make this interesting
|
||
func isAlpha() -> Bool {
|
||
return (this >= 'A' && this <= 'Z') || (this >= 'a' && this <= 'z')
|
||
}
|
||
|
||
// FIXME: Locales make this interesting
|
||
func isDigit() -> Bool {
|
||
return this >= '0' && this <= '9'
|
||
}
|
||
|
||
// FIXME: Locales make this interesting
|
||
var uppercase : Char {
|
||
if this >= 'a' && this <= 'z' {
|
||
return Char(UInt32(this) - 32)
|
||
} else if this >= 'à' && this <= 'þ' && this != '÷' {
|
||
return Char(UInt32(this) - 32)
|
||
}
|
||
return this
|
||
}
|
||
|
||
// FIXME: Locales make this interesting
|
||
var lowercase : Char {
|
||
if this >= 'A' && this <= 'Z' {
|
||
return Char(UInt32(this) + 32)
|
||
} else if this >= 'À' && this <= 'Þ' && this != '×' {
|
||
return Char(UInt32(this) + 32)
|
||
}
|
||
return this
|
||
}
|
||
|
||
// FIXME: Locales make this interesting.
|
||
func isSpace() -> Bool {
|
||
// FIXME: The constraint-based type checker goes painfully exponential
|
||
// when we turn this into one large expression. Break it up for now,
|
||
// until we can optimize the constraint solver better.
|
||
if this == ' ' || this == '\t' { return true }
|
||
if this == '\n' || this == '\r' { return true }
|
||
return this == '\x0B' || this == '\x0C'
|
||
}
|
||
}
|
||
|
||
extension Char : FormattedPrintable {
|
||
func format(kind : Char, layout : String) -> String {
|
||
return String(this).format(kind, layout)
|
||
}
|
||
}
|
||
|
||
extension Char : Hashable {
|
||
func hashValue() -> Int {
|
||
return Int(this.value)
|
||
}
|
||
}
|
||
|
||
extension Char {
|
||
constructor(v : Int) {
|
||
this = Char(UInt32(v))
|
||
}
|
||
}
|
||
|
||
extension UInt8 {
|
||
constructor(v : Char) {
|
||
debugTrap(v.value <= UInt32(UInt8.max()), "Code point value does not fit into UInt8")
|
||
this = UInt8(v.value)
|
||
}
|
||
}
|
||
extension UInt32 {
|
||
constructor(v : Char) {
|
||
this = v.value
|
||
}
|
||
}
|
||
extension UInt64 {
|
||
constructor(v : Char) {
|
||
this = UInt64(v.value)
|
||
}
|
||
}
|
||
|
||
func - (lhs: Char, rhs: Char) -> Int {
|
||
return Int(lhs.value) - Int(rhs.value)
|
||
}
|
||
|
||
func - (lhs: Char, rhs: Int) -> Char {
|
||
return Char(lhs.value - UInt32(rhs))
|
||
}
|
||
|
||
func + (lhs: Char, rhs: Int) -> Char {
|
||
return Char(lhs.value + UInt32(rhs))
|
||
}
|
||
|
||
func + (lhs: Int, rhs: Char) -> Char {
|
||
return rhs + lhs
|
||
}
|
||
|
||
extension Char : Comparable {
|
||
func __equal__(rhs: Char) -> Bool {
|
||
return this.value == rhs.value
|
||
}
|
||
func __less__(rhs: Char) -> Bool {
|
||
return this.value < rhs.value
|
||
}
|
||
}
|
||
|
||
extension Char {
|
||
func isPrint() -> Bool {
|
||
return (this >= Char(0o040) && this <= Char(0o176))
|
||
}
|
||
}
|