1
0

PlatformString.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. This source file is part of the Swift System open source project
  3. Copyright (c) 2020 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. @available(System 0.0.2, *)
  8. extension String {
  9. /// Creates a string by interpreting the null-terminated platform string as
  10. /// UTF-8 on Unix and UTF-16 on Windows.
  11. ///
  12. /// - Parameter platformString: The null-terminated platform string to be
  13. /// interpreted as `CInterop.PlatformUnicodeEncoding`.
  14. ///
  15. /// If the content of the platform string isn't well-formed Unicode,
  16. /// this initializer replaces invalid bytes with U+FFFD.
  17. /// This means that, depending on the semantics of the specific platform,
  18. /// conversion to a string and back might result in a value that's different
  19. /// from the original platform string.
  20. @_disfavoredOverload
  21. public init(platformString: UnsafePointer<CInterop.PlatformChar>) {
  22. self.init(_errorCorrectingPlatformString: platformString)
  23. }
  24. /// Creates a string by interpreting the null-terminated platform string as
  25. /// UTF-8 on Unix and UTF-16 on Windows.
  26. ///
  27. /// - Parameter platformString: The null-terminated platform string to be
  28. /// interpreted as `CInterop.PlatformUnicodeEncoding`.
  29. ///
  30. /// - Note It is a precondition that `platformString` must be null-terminated.
  31. /// The absence of a null byte will trigger a runtime error.
  32. ///
  33. /// If the content of the platform string isn't well-formed Unicode,
  34. /// this initializer replaces invalid bytes with U+FFFD.
  35. /// This means that, depending on the semantics of the specific platform,
  36. /// conversion to a string and back might result in a value that's different
  37. /// from the original platform string.
  38. @inlinable
  39. @_alwaysEmitIntoClient
  40. public init(platformString: [CInterop.PlatformChar]) {
  41. guard let _ = platformString.firstIndex(of: 0) else {
  42. fatalError(
  43. "input of String.init(platformString:) must be null-terminated"
  44. )
  45. }
  46. self = platformString.withUnsafeBufferPointer {
  47. String(platformString: $0.baseAddress!)
  48. }
  49. }
  50. @inlinable
  51. @_alwaysEmitIntoClient
  52. @available(*, deprecated, message: "Use String.init(_ scalar: Unicode.Scalar)")
  53. public init(platformString: inout CInterop.PlatformChar) {
  54. guard platformString == 0 else {
  55. fatalError(
  56. "input of String.init(platformString:) must be null-terminated"
  57. )
  58. }
  59. self = ""
  60. }
  61. @inlinable
  62. @_alwaysEmitIntoClient
  63. @available(*, deprecated, message: "Use a copy of the String argument")
  64. public init(platformString: String) {
  65. if let nullLoc = platformString.firstIndex(of: "\0") {
  66. self = String(platformString[..<nullLoc])
  67. } else {
  68. self = platformString
  69. }
  70. }
  71. /// Creates a string by interpreting the null-terminated platform string as
  72. /// UTF-8 on Unix and UTF-16 on Windows.
  73. ///
  74. /// - Parameter platformString: The null-terminated platform string to be
  75. /// interpreted as `CInterop.PlatformUnicodeEncoding`.
  76. ///
  77. /// If the contents of the platform string isn't well-formed Unicode,
  78. /// this initializer returns `nil`.
  79. public init?(
  80. validatingPlatformString platformString: UnsafePointer<CInterop.PlatformChar>
  81. ) {
  82. self.init(_platformString: platformString)
  83. }
  84. /// Creates a string by interpreting the null-terminated platform string as
  85. /// UTF-8 on Unix and UTF-16 on Windows.
  86. ///
  87. /// - Parameter platformString: The null-terminated platform string to be
  88. /// interpreted as `CInterop.PlatformUnicodeEncoding`.
  89. ///
  90. /// - Note It is a precondition that `platformString` must be null-terminated.
  91. /// The absence of a null byte will trigger a runtime error.
  92. ///
  93. /// If the contents of the platform string isn't well-formed Unicode,
  94. /// this initializer returns `nil`.
  95. @inlinable
  96. @_alwaysEmitIntoClient
  97. public init?(
  98. validatingPlatformString platformString: [CInterop.PlatformChar]
  99. ) {
  100. guard let _ = platformString.firstIndex(of: 0) else {
  101. fatalError(
  102. "input of String.init(validatingPlatformString:) must be null-terminated"
  103. )
  104. }
  105. guard let string = platformString.withUnsafeBufferPointer({
  106. String(validatingPlatformString: $0.baseAddress!)
  107. }) else {
  108. return nil
  109. }
  110. self = string
  111. }
  112. @inlinable
  113. @_alwaysEmitIntoClient
  114. @available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
  115. public init?(
  116. validatingPlatformString platformString: inout CInterop.PlatformChar
  117. ) {
  118. guard platformString == 0 else {
  119. fatalError(
  120. "input of String.init(validatingPlatformString:) must be null-terminated"
  121. )
  122. }
  123. self = ""
  124. }
  125. @inlinable
  126. @_alwaysEmitIntoClient
  127. @available(*, deprecated, message: "Use a copy of the String argument")
  128. public init?(
  129. validatingPlatformString platformString: String
  130. ) {
  131. if let nullLoc = platformString.firstIndex(of: "\0") {
  132. self = String(platformString[..<nullLoc])
  133. } else {
  134. self = platformString
  135. }
  136. }
  137. /// Calls the given closure with a pointer to the contents of the string,
  138. /// represented as a null-terminated platform string.
  139. ///
  140. /// - Parameter body: A closure with a pointer parameter
  141. /// that points to a null-terminated platform string.
  142. /// If `body` has a return value,
  143. /// that value is also used as the return value for this method.
  144. /// - Returns: The return value, if any, of the `body` closure parameter.
  145. ///
  146. /// The pointer passed as an argument to `body` is valid
  147. /// only during the execution of this method.
  148. /// Don't try to store the pointer for later use.
  149. public func withPlatformString<Result>(
  150. _ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result
  151. ) rethrows -> Result {
  152. try _withPlatformString(body)
  153. }
  154. }
  155. @available(System 0.0.2, *)
  156. extension CInterop.PlatformChar {
  157. internal var _platformCodeUnit: CInterop.PlatformUnicodeEncoding.CodeUnit {
  158. #if os(Windows)
  159. return self
  160. #else
  161. return CInterop.PlatformUnicodeEncoding.CodeUnit(bitPattern: self)
  162. #endif
  163. }
  164. }
  165. @available(System 0.0.2, *)
  166. extension CInterop.PlatformUnicodeEncoding.CodeUnit {
  167. internal var _platformChar: CInterop.PlatformChar {
  168. #if os(Windows)
  169. return self
  170. #else
  171. return CInterop.PlatformChar(bitPattern: self)
  172. #endif
  173. }
  174. }
  175. internal protocol _PlatformStringable {
  176. func _withPlatformString<Result>(
  177. _ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result
  178. ) rethrows -> Result
  179. init?(_platformString: UnsafePointer<CInterop.PlatformChar>)
  180. }
  181. extension String: _PlatformStringable {}