@@ -173,4 +173,98 @@ extension StringProtocol {
173173 }
174174}
175175
176+ // Contiguous UTF-8 strings
177+ extension String {
178+ /// Returns whether this string is capable of providing access to
179+ /// validly-encoded UTF-8 contents in contiguous memory in O(1) time.
180+ ///
181+ /// Contiguous strings always operate in O(1) time for withUTF8 and always
182+ /// give a result for String.UTF8View.withContiguousStorageIfAvailable.
183+ /// Contiguous strings also benefit from fast-paths and better optimizations.
184+ ///
185+ @_alwaysEmitIntoClient
186+ public var isContiguousUTF8 : Bool { return _guts. isFastUTF8 }
187+
188+ /// If this string is not contiguous, make it so. If this mutates the string,
189+ /// it will invalidate any pre-existing indices.
190+ ///
191+ /// Complexity: O(n) if non-contiguous, O(1) if already contiguous
192+ ///
193+ @_alwaysEmitIntoClient
194+ public mutating func makeContiguousUTF8( ) {
195+ if _fastPath ( isContiguousUTF8) { return }
196+ self = String . _copying ( self )
197+ }
198+
199+ /// Runs `body` over the content of this string in contiguous memory. If this
200+ /// string is not contiguous, this will first make it contiguous, which will
201+ /// also speed up subsequent access. If this mutates the string,
202+ /// it will invalidate any pre-existing indices.
203+ ///
204+ /// Note that it is unsafe to escape the pointer provided to `body`. For
205+ /// example, strings of up to 15 UTF-8 code units in length may be represented
206+ /// in a small-string representation, and thus will be spilled into
207+ /// temporary stack space which is invalid after `withUTF8` finishes
208+ /// execution.
209+ ///
210+ /// Complexity: O(n) if non-contiguous, O(1) if already contiguous
211+ ///
212+ @_alwaysEmitIntoClient
213+ public mutating func withUTF8< R> (
214+ _ body: ( UnsafeBufferPointer < UInt8 > ) throws -> R
215+ ) rethrows -> R {
216+ makeContiguousUTF8 ( )
217+ return try _guts. withFastUTF8 ( body)
218+ }
219+ }
176220
221+ // Contiguous UTF-8 strings
222+ extension Substring {
223+ /// Returns whether this string is capable of providing access to
224+ /// validly-encoded UTF-8 contents in contiguous memory in O(1) time.
225+ ///
226+ /// Contiguous strings always operate in O(1) time for withUTF8 and always
227+ /// give a result for String.UTF8View.withContiguousStorageIfAvailable.
228+ /// Contiguous strings also benefit from fast-paths and better optimizations.
229+ ///
230+ @_alwaysEmitIntoClient
231+ public var isContiguousUTF8 : Bool { return self . base. isContiguousUTF8 }
232+
233+ /// If this string is not contiguous, make it so. If this mutates the
234+ /// substring, it will invalidate any pre-existing indices.
235+ ///
236+ /// Complexity: O(n) if non-contiguous, O(1) if already contiguous
237+ ///
238+ @_alwaysEmitIntoClient
239+ public mutating func makeContiguousUTF8( ) {
240+ if _fastPath ( isContiguousUTF8) { return }
241+ self = String . _copying ( self ) [ ... ]
242+ }
243+
244+ /// Runs `body` over the content of this substring in contiguous memory. If
245+ /// this substring is not contiguous, this will first make it contiguous,
246+ /// which will also speed up subsequent access. If this mutates the substring,
247+ /// it will invalidate any pre-existing indices.
248+ ///
249+ /// Note that it is unsafe to escape the pointer provided to `body`. For
250+ /// example, strings of up to 15 UTF-8 code units in length may be represented
251+ /// in a small-string representation, and thus will be spilled into
252+ /// temporary stack space which is invalid after `withUTF8` finishes
253+ /// execution.
254+ ///
255+ /// Complexity: O(n) if non-contiguous, O(1) if already contiguous
256+ ///
257+ @_alwaysEmitIntoClient
258+ public mutating func withUTF8< R> (
259+ _ body: ( UnsafeBufferPointer < UInt8 > ) throws -> R
260+ ) rethrows -> R {
261+ if _fastPath ( isContiguousUTF8) {
262+ return try _wholeGuts. withFastUTF8 ( range: self . _offsetRange) {
263+ return try body ( $0)
264+ }
265+ }
266+
267+ makeContiguousUTF8 ( )
268+ return try _wholeGuts. withFastUTF8 ( body)
269+ }
270+ }
0 commit comments