//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// func ==(lhs: UnicodeScalarView.IndexType, rhs: UnicodeScalarView.IndexType) -> Bool { return lhs._position == rhs._position } struct UnicodeScalarView : Sliceable, Sequence { init(_ _base: _StringCore) { self._base = _base } struct ScratchGenerator : Generator { var base :_StringCore var idx : Int init(_ core : _StringCore, _ pos : Int) { idx = pos base = core } mutating func next() -> UTF16.CodeUnit? { return self.base[idx++] } } // FIXME: This index should probably become bidirectional, as UTF16 // is traversable in either direction. struct IndexType : BidirectionalIndex { init(_ _position: Int, _ _base: _StringCore) { self._position = _position self._base = _base } func succ() -> IndexType { var scratch = ScratchGenerator(_base, _position) UTF16.decode(&scratch) return IndexType(scratch.idx, _base) } func pred() -> IndexType { var i = _position let codeUnit = self._base[--i] if codeUnit >= 0xD800 && codeUnit <= 0xE000 { --i } return IndexType(i, _base) } var _position: Int var _base: _StringCore } var startIndex: IndexType { return IndexType(_base.startIndex, _base) } var endIndex: IndexType { return IndexType(_base.endIndex, _base) } subscript(i: IndexType) -> UnicodeScalar { var scratch = ScratchGenerator(_base, i._position) return UTF16.decode(&scratch)! } func __slice__(start: IndexType, end: IndexType) -> UnicodeScalarView { return UnicodeScalarView(_base[start._position..end._position]) } subscript(r: Range) -> UnicodeScalarView { return UnicodeScalarView(_base[r.startIndex._position..r.endIndex._position]) } struct GeneratorType : Generator { init(_ _base: _StringCore.GeneratorType) { self._base = _base } mutating func next() -> UnicodeScalar? { return UTF16.decode(&self._base) } var _base: _StringCore.GeneratorType } func generate() -> GeneratorType { return GeneratorType(_base.generate()) } @conversion func __conversion() -> String { return String(_base) } func compare(other : UnicodeScalarView) -> Int { // Try to compare the string without decoding // the UTF16 string. var AIdx = self._base.startIndex var BIdx = other._base.startIndex var AEnd = self._base.endIndex var BEnd = other._base.endIndex while true { if AIdx < AEnd { if BIdx < BEnd { let e1 = self._base[AIdx] let e2 = other._base[BIdx] if (e1 >= 0x80 || e2 >= 0x80) { // Use slow unicode comparator if // we found multi-byte scalar. return _compareUnicode(other) } if e1 < e2 { return -1 } if e2 < e1 { return 1 } AIdx++ BIdx++ continue // equivalent } return 1 } if BIdx < BEnd { return -1 } return 0 } } func _compareUnicode(other : UnicodeScalarView) -> Int { var g1 = self.generate() var g2 = other.generate() while true { let e1_ = g1.next() let e2_ = g2.next() if let e1 = e1_ { if let e2 = e2_ { if e1 < e2 { return -1 } if e2 < e1 { return 1 } continue // equivalent } return 1 } if e2_ { return -1 } return 0 } } var _base: _StringCore } extension String { func compare(other : String) -> Int { return(UnicodeScalarView(core).compare(UnicodeScalarView(other.core))) } var unicodeScalars : UnicodeScalarView { return UnicodeScalarView(core) } }