Skip to content

Commit 3b333ff

Browse files
authored
Merge pull request #9176 from apple/new-unicode-decoders
2 parents 55b7d17 + feea061 commit 3b333ff

13 files changed

+825
-744
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,11 @@ set(SWIFTLIB_ESSENTIAL
130130
StringUTF8.swift
131131
Substring.swift.gyb
132132
SwiftNativeNSArray.swift
133+
UIntBuffer.swift
133134
UnavailableStringAPIs.swift.gyb
134135
Unicode.swift
136+
UnicodeEncoding.swift
137+
UnicodeParser.swift
135138
UnicodeScalar.swift
136139
UnicodeTrie.swift.gyb
137140
Unmanaged.swift
@@ -140,6 +143,9 @@ set(SWIFTLIB_ESSENTIAL
140143
UnsafeRawBufferPointer.swift.gyb
141144
UnsafePointer.swift.gyb
142145
UnsafeRawPointer.swift.gyb
146+
UTFEncoding.swift
147+
UTF8.swift
148+
UTF16.swift
143149
WriteBackMutableSlice.swift
144150
)
145151

stdlib/public/core/GroupInfo.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@
2323
"StringUnicodeScalarView.swift",
2424
"Substring.swift",
2525
"Unicode.swift",
26+
"UnicodeEncoding.swift",
27+
"UnicodeParser.swift",
2628
"UnicodeScalar.swift",
2729
"UnicodeTrie.swift",
28-
"UnavailableStringAPIs.swift"
30+
"UnavailableStringAPIs.swift",
31+
"UTFEncoding.swift",
32+
"UTF8.swift",
33+
"UTF16.swift"
2934
],
3035
"Bool": [
3136
"Bool.swift"
@@ -52,6 +57,7 @@
5257
"Existential.swift",
5358
"WriteBackMutableSlice.swift",
5459
"UnfoldSequence.swift",
60+
"UIntBuffer.swift",
5561
{
5662
"Type-erased": [
5763
"ExistentialCollection.swift"

stdlib/public/core/MutableCollection.swift

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ public protocol _MutableIndexable : _Indexable {
2727
// `Iterator` type from a minimal collection, but it is also used in
2828
// exposed places like as a constraint on `IndexingIterator`.
2929

30-
/// A type that represents a valid position in the collection.
31-
///
32-
/// Valid indices consist of the position of every element and a
33-
/// "past the end" position that's not valid for use as a subscript.
34-
// TODO: swift-3-indexing-model - Index only needs to be comparable or must be comparable..?
35-
associatedtype Index
36-
3730
/// The position of the first element in a nonempty collection.
3831
///
3932
/// If the collection is empty, `startIndex` is equal to `endIndex`.
@@ -56,16 +49,6 @@ public protocol _MutableIndexable : _Indexable {
5649
/// If the collection is empty, `endIndex` is equal to `startIndex`.
5750
var endIndex: Index { get }
5851

59-
// The declaration of _Element and subscript here is a trick used to
60-
// break a cyclic conformance/deduction that Swift can't handle. We
61-
// need something other than a Collection.Iterator.Element that can
62-
// be used as IndexingIterator<T>'s Element. Here we arrange for
63-
// the Collection itself to have an Element type that's deducible from
64-
// its subscript. Ideally we'd like to constrain this Element to be the same
65-
// as Collection.Iterator.Element (see below), but we have no way of
66-
// expressing it today.
67-
associatedtype _Element
68-
6952
/// Accesses the element at the specified position.
7053
///
7154
/// For example, you can replace an element of an array by using its
@@ -86,10 +69,6 @@ public protocol _MutableIndexable : _Indexable {
8669
/// `endIndex` property.
8770
subscript(position: Index) -> _Element { get set }
8871

89-
/// A collection that represents a contiguous subrange of the collection's
90-
/// elements.
91-
associatedtype SubSequence
92-
9372
/// Accesses a contiguous subrange of the collection's elements.
9473
///
9574
/// The accessed slice uses the same indices for the same elements as the

stdlib/public/core/Reverse.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,36 @@ extension MutableCollection where Self : BidirectionalCollection {
3434
}
3535
}
3636

37+
/// An iterator that can be much faster than the iterator of a reversed slice.
38+
// TODO: See about using this in more places
39+
@_fixed_layout
40+
public struct _ReverseIndexingIterator<
41+
Elements : BidirectionalCollection
42+
> : IteratorProtocol, Sequence {
43+
44+
@_inlineable
45+
@inline(__always)
46+
/// Creates an iterator over the given collection.
47+
public /// @testable
48+
init(_elements: Elements, _position: Elements.Index) {
49+
self._elements = _elements
50+
self._position = _position
51+
}
52+
53+
@_inlineable
54+
@inline(__always)
55+
public mutating func next() -> Elements._Element? {
56+
guard _fastPath(_position != _elements.startIndex) else { return nil }
57+
_position = _elements.index(before: _position)
58+
return _elements[_position]
59+
}
60+
61+
@_versioned
62+
internal let _elements: Elements
63+
@_versioned
64+
internal var _position: Elements.Index
65+
}
66+
3767
// FIXME(ABI)#59 (Conditional Conformance): we should have just one type,
3868
// `ReversedCollection`, that has conditional conformances to
3969
// `RandomAccessCollection`, and possibly `MutableCollection` and

stdlib/public/core/Stride.swift.gyb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ public protocol ${Self} : ${Conformance} {
2727
% if Self == '_Strideable':
2828
/// A type that represents the distance between two values of `Self`.
2929
associatedtype Stride : SignedNumeric, Comparable
30-
% else:
31-
/// A type that represents the distance between two values of `Self`.
32-
associatedtype Stride
3330
% end
3431

3532
/// Returns a stride `x` such that `self.advanced(by: x)` approximates

stdlib/public/core/UIntBuffer.swift

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
//===--- UIntBuffer.swift - Bounded Collection of Unisigned Integer -------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Stores a smaller unsigned integer type inside a larger one, with a limit of
14+
// 255 elements.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
@_fixed_layout
18+
public struct _UIntBuffer<
19+
Storage: UnsignedInteger & FixedWidthInteger,
20+
Element: UnsignedInteger & FixedWidthInteger
21+
> {
22+
public var _storage: Storage
23+
public var _bitCount: UInt8
24+
25+
@inline(__always)
26+
public init(_storage: Storage, _bitCount: UInt8) {
27+
self._storage = _storage
28+
self._bitCount = _bitCount
29+
}
30+
31+
@inline(__always)
32+
public init(containing e: Element) {
33+
_storage = Storage(extendingOrTruncating: e)
34+
_bitCount = UInt8(extendingOrTruncating: Element.bitWidth)
35+
}
36+
}
37+
38+
extension _UIntBuffer : Sequence {
39+
public typealias SubSequence = RangeReplaceableRandomAccessSlice<_UIntBuffer>
40+
41+
@_fixed_layout
42+
public struct Iterator : IteratorProtocol, Sequence {
43+
@inline(__always)
44+
public init(_ x: _UIntBuffer) { _impl = x }
45+
46+
@inline(__always)
47+
public mutating func next() -> Element? {
48+
if _impl._bitCount == 0 { return nil }
49+
defer {
50+
_impl._storage = _impl._storage &>> Element.bitWidth
51+
_impl._bitCount = _impl._bitCount &- _impl._elementWidth
52+
}
53+
return Element(extendingOrTruncating: _impl._storage)
54+
}
55+
public
56+
var _impl: _UIntBuffer
57+
}
58+
59+
@inline(__always)
60+
public func makeIterator() -> Iterator {
61+
return Iterator(self)
62+
}
63+
}
64+
65+
extension _UIntBuffer : Collection {
66+
public typealias _Element = Element
67+
68+
public struct Index : Comparable {
69+
@_versioned
70+
var bitOffset: UInt8
71+
72+
@_versioned
73+
init(bitOffset: UInt8) { self.bitOffset = bitOffset }
74+
75+
public static func == (lhs: Index, rhs: Index) -> Bool {
76+
return lhs.bitOffset == rhs.bitOffset
77+
}
78+
public static func < (lhs: Index, rhs: Index) -> Bool {
79+
return lhs.bitOffset < rhs.bitOffset
80+
}
81+
}
82+
83+
public var startIndex : Index {
84+
@inline(__always)
85+
get { return Index(bitOffset: 0) }
86+
}
87+
88+
public var endIndex : Index {
89+
@inline(__always)
90+
get { return Index(bitOffset: _bitCount) }
91+
}
92+
93+
@inline(__always)
94+
public func index(after i: Index) -> Index {
95+
return Index(bitOffset: i.bitOffset &+ _elementWidth)
96+
}
97+
98+
@_versioned
99+
internal var _elementWidth : UInt8 {
100+
return UInt8(extendingOrTruncating: Element.bitWidth)
101+
}
102+
103+
public subscript(i: Index) -> Element {
104+
@inline(__always)
105+
get {
106+
return Element(extendingOrTruncating: _storage &>> i.bitOffset)
107+
}
108+
}
109+
}
110+
111+
extension _UIntBuffer : BidirectionalCollection {
112+
@inline(__always)
113+
public func index(before i: Index) -> Index {
114+
return Index(bitOffset: i.bitOffset &- _elementWidth)
115+
}
116+
}
117+
118+
extension _UIntBuffer : RandomAccessCollection {
119+
public typealias Indices = DefaultRandomAccessIndices<_UIntBuffer>
120+
public typealias IndexDistance = Int
121+
122+
@inline(__always)
123+
public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
124+
let x = IndexDistance(i.bitOffset) &+ n &* Element.bitWidth
125+
return Index(bitOffset: UInt8(extendingOrTruncating: x))
126+
}
127+
128+
@inline(__always)
129+
public func distance(from i: Index, to j: Index) -> IndexDistance {
130+
return (Int(j.bitOffset) &- Int(i.bitOffset)) / Element.bitWidth
131+
}
132+
}
133+
134+
extension FixedWidthInteger {
135+
@inline(__always)
136+
@_versioned
137+
func _fullShiftLeft<N: FixedWidthInteger>(_ n: N) -> Self {
138+
return (self &<< ((n &+ 1) &>> 1)) &<< (n &>> 1)
139+
}
140+
@inline(__always)
141+
@_versioned
142+
func _fullShiftRight<N: FixedWidthInteger>(_ n: N) -> Self {
143+
return (self &>> ((n &+ 1) &>> 1)) &>> (n &>> 1)
144+
}
145+
@inline(__always)
146+
@_versioned
147+
static func _lowBits<N: FixedWidthInteger>(_ n: N) -> Self {
148+
return ~((~0 as Self)._fullShiftLeft(n))
149+
}
150+
}
151+
152+
extension Range {
153+
@inline(__always)
154+
@_versioned
155+
func _contains_(_ other: Range) -> Bool {
156+
return other.clamped(to: self) == other
157+
}
158+
}
159+
160+
extension _UIntBuffer : RangeReplaceableCollection {
161+
@inline(__always)
162+
public init() {
163+
_storage = 0
164+
_bitCount = 0
165+
}
166+
167+
public var capacity: Int {
168+
return Storage.bitWidth / Element.bitWidth
169+
}
170+
171+
@inline(__always)
172+
public mutating func append(_ newElement: Element) {
173+
_debugPrecondition(count + 1 <= capacity)
174+
_storage |= Storage(newElement) &<< _bitCount
175+
_bitCount = _bitCount &+ _elementWidth
176+
}
177+
178+
@inline(__always)
179+
public mutating func replaceSubrange<C: Collection>(
180+
_ target: Range<Index>, with replacement: C
181+
) where C._Element == Element {
182+
_debugPrecondition(
183+
(0..<_bitCount)._contains_(
184+
target.lowerBound.bitOffset..<target.upperBound.bitOffset))
185+
186+
let replacement1 = _UIntBuffer(replacement)
187+
188+
let targetCount = distance(
189+
from: target.lowerBound, to: target.upperBound)
190+
let growth = replacement1.count &- targetCount
191+
_debugPrecondition(count + growth <= capacity)
192+
193+
let headCount = distance(from: startIndex, to: target.lowerBound)
194+
let tailOffset = distance(from: startIndex, to: target.upperBound)
195+
196+
let w = Element.bitWidth
197+
let headBits = _storage & ._lowBits(headCount &* w)
198+
let tailBits = _storage._fullShiftRight(tailOffset &* w)
199+
200+
_storage = headBits
201+
_storage |= replacement1._storage &<< (headCount &* w)
202+
_storage |= tailBits &<< ((tailOffset &+ growth) &* w)
203+
_bitCount = UInt8(
204+
extendingOrTruncating: IndexDistance(_bitCount) &+ growth &* w)
205+
}
206+
}

0 commit comments

Comments
 (0)