Util.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. This source file is part of the Swift System open source project
  3. Copyright (c) 2020 - 2021 Apple Inc. and the Swift System project authors
  4. Licensed under Apache License v2.0 with Runtime Library Exception
  5. See https://swift.org/LICENSE.txt for license information
  6. */
  7. // Results in errno if i == -1
  8. @available(System 0.0.1, *)
  9. private func valueOrErrno<I: FixedWidthInteger>(
  10. _ i: I
  11. ) -> Result<I, Errno> {
  12. i == -1 ? .failure(Errno.current) : .success(i)
  13. }
  14. @available(System 0.0.1, *)
  15. private func nothingOrErrno<I: FixedWidthInteger>(
  16. _ i: I
  17. ) -> Result<(), Errno> {
  18. valueOrErrno(i).map { _ in () }
  19. }
  20. @available(System 0.0.1, *)
  21. internal func valueOrErrno<I: FixedWidthInteger>(
  22. retryOnInterrupt: Bool, _ f: () -> I
  23. ) -> Result<I, Errno> {
  24. repeat {
  25. switch valueOrErrno(f()) {
  26. case .success(let r): return .success(r)
  27. case .failure(let err):
  28. guard retryOnInterrupt && err == .interrupted else { return .failure(err) }
  29. break
  30. }
  31. } while true
  32. }
  33. @available(System 0.0.1, *)
  34. internal func nothingOrErrno<I: FixedWidthInteger>(
  35. retryOnInterrupt: Bool, _ f: () -> I
  36. ) -> Result<(), Errno> {
  37. valueOrErrno(retryOnInterrupt: retryOnInterrupt, f).map { _ in () }
  38. }
  39. // Run a precondition for debug client builds
  40. internal func _debugPrecondition(
  41. _ condition: @autoclosure () -> Bool,
  42. _ message: StaticString = StaticString(),
  43. file: StaticString = #file, line: UInt = #line
  44. ) {
  45. // Only check in debug mode.
  46. if _slowPath(_isDebugAssertConfiguration()) {
  47. precondition(
  48. condition(), String(describing: message), file: file, line: line)
  49. }
  50. }
  51. extension OpaquePointer {
  52. internal var _isNULL: Bool {
  53. OpaquePointer(bitPattern: Int(bitPattern: self)) == nil
  54. }
  55. }
  56. extension Sequence {
  57. // Tries to recast contiguous pointer if available, otherwise allocates memory.
  58. internal func _withRawBufferPointer<R>(
  59. _ body: (UnsafeRawBufferPointer) throws -> R
  60. ) rethrows -> R {
  61. guard let result = try self.withContiguousStorageIfAvailable({
  62. try body(UnsafeRawBufferPointer($0))
  63. }) else {
  64. return try Array(self).withUnsafeBytes(body)
  65. }
  66. return result
  67. }
  68. }
  69. extension OptionSet {
  70. // Helper method for building up a comma-separated list of options
  71. //
  72. // Taking an array of descriptions reduces code size vs
  73. // a series of calls due to avoiding register copies. Make sure
  74. // to pass an array literal and not an array built up from a series of
  75. // append calls, else that will massively bloat code size. This takes
  76. // StaticStrings because otherwise we get a warning about getting evicted
  77. // from the shared cache.
  78. @inline(never)
  79. internal func _buildDescription(
  80. _ descriptions: [(Element, StaticString)]
  81. ) -> String {
  82. var copy = self
  83. var result = "["
  84. for (option, name) in descriptions {
  85. if _slowPath(copy.contains(option)) {
  86. result += name.description
  87. copy.remove(option)
  88. if !copy.isEmpty { result += ", " }
  89. }
  90. }
  91. if _slowPath(!copy.isEmpty) {
  92. result += "\(Self.self)(rawValue: \(copy.rawValue))"
  93. }
  94. result += "]"
  95. return result
  96. }
  97. }
  98. internal func _dropCommonPrefix<C: Collection>(
  99. _ lhs: C, _ rhs: C
  100. ) -> (C.SubSequence, C.SubSequence)
  101. where C.Element: Equatable {
  102. var (lhs, rhs) = (lhs[...], rhs[...])
  103. while lhs.first != nil && lhs.first == rhs.first {
  104. lhs.removeFirst()
  105. rhs.removeFirst()
  106. }
  107. return (lhs, rhs)
  108. }
  109. extension MutableCollection where Element: Equatable {
  110. mutating func _replaceAll(_ e: Element, with new: Element) {
  111. for idx in self.indices {
  112. if self[idx] == e { self[idx] = new }
  113. }
  114. }
  115. }
  116. internal func _withOptionalUnsafePointerOrNull<T, R>(
  117. to value: T?,
  118. _ body: (UnsafePointer<T>?) throws -> R
  119. ) rethrows -> R {
  120. guard let value = value else {
  121. return try body(nil)
  122. }
  123. return try withUnsafePointer(to: value, body)
  124. }
  125. /// Calls `body` with a temporary buffer of the indicated size,
  126. /// possibly stack-allocated.
  127. internal func _withStackBuffer<R>(
  128. capacity: Int,
  129. _ body: (UnsafeMutableRawBufferPointer) throws -> R
  130. ) rethrows -> R {
  131. typealias StackStorage = (
  132. UInt64, UInt64, UInt64, UInt64,
  133. UInt64, UInt64, UInt64, UInt64,
  134. UInt64, UInt64, UInt64, UInt64,
  135. UInt64, UInt64, UInt64, UInt64
  136. )
  137. if capacity > MemoryLayout<StackStorage>.size {
  138. var buffer = _RawBuffer(minimumCapacity: capacity)
  139. return try buffer.withUnsafeMutableBytes { buffer in
  140. try body(.init(rebasing: buffer[..<capacity]))
  141. }
  142. } else {
  143. var storage: StackStorage = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  144. return try withUnsafeMutableBytes(of: &storage) { buffer in
  145. try body(.init(rebasing: buffer[..<capacity]))
  146. }
  147. }
  148. }