@@ -78,11 +78,30 @@ extension MachOFile.UnicodeStrings {
7878extension MachOFile . UnicodeStrings {
7979 public func string( at offset: Int ) -> Element ? {
8080 guard 0 <= offset, offset < fileSlice. size else { return nil }
81- let string = String (
82- cString: fileSlice. ptr
83- . advanced ( by: offset)
84- . assumingMemoryBound ( to: CChar . self)
81+
82+ guard let ( _string, length) = fileSlice. _readString (
83+ offset: numericCast ( offset) ,
84+ as: Encoding . self
85+ ) else {
86+ return nil
87+ }
88+ var string = _string
89+
90+ let char = try ! fileSlice. read (
91+ offset: offset,
92+ as: Encoding . CodeUnit. self
8593 )
94+
95+ if isSwapped || Iterator . shouldSwap ( char) {
96+ handleSwap (
97+ string: & string,
98+ at: offset,
99+ length: length,
100+ fileHandle: fileSlice,
101+ hasBOM: Iterator . shouldSwap ( char) ,
102+ encoding: Encoding . self
103+ )
104+ }
86105 return . init( string: string, offset: offset)
87106 }
88107}
@@ -107,26 +126,30 @@ extension MachOFile.UnicodeStrings {
107126 public mutating func next( ) -> Element ? {
108127 guard nextOffset < tableSize else { return nil }
109128
110- let ptr = UnsafeRawPointer ( fileSlice. ptr)
111- . advanced ( by: nextOffset)
112- . assumingMemoryBound ( to: Encoding . CodeUnit. self)
113- var ( string, offset) = ptr. readString ( as: Encoding . self)
129+ guard let ( _string, length) = fileSlice. _readString (
130+ offset: nextOffset,
131+ as: Encoding . self
132+ ) else { return nil }
133+ var string = _string
114134
115135 defer {
116- nextOffset += offset
136+ nextOffset += length
117137 }
118138
119- if isSwapped || shouldSwap ( ptr) {
120- let data = Data ( bytes: ptr, count: offset)
121- . byteSwapped ( Encoding . CodeUnit. self)
122- string = data. withUnsafeBytes {
123- let baseAddress = $0. baseAddress!
124- . assumingMemoryBound ( to: Encoding . CodeUnit. self)
125- return . init(
126- decodingCString: baseAddress,
127- as: Encoding . self
128- )
129- }
139+ let char = try ! fileSlice. read (
140+ offset: nextOffset,
141+ as: Encoding . CodeUnit. self
142+ )
143+
144+ if isSwapped || Self . shouldSwap ( char) {
145+ handleSwap (
146+ string: & string,
147+ at: nextOffset,
148+ length: length,
149+ fileHandle: fileSlice,
150+ hasBOM: Self . shouldSwap ( char) ,
151+ encoding: Encoding . self
152+ )
130153 }
131154
132155 return . init(
@@ -139,17 +162,53 @@ extension MachOFile.UnicodeStrings {
139162
140163extension MachOFile . UnicodeStrings . Iterator {
141164 // https://github.com/swiftlang/swift-corelibs-foundation/blob/4a9694d396b34fb198f4c6dd865702f7dc0b0dcf/Sources/Foundation/NSString.swift#L1390
142- func shouldSwap( _ ptr: UnsafePointer < Encoding . CodeUnit > ) -> Bool {
165+ static func shouldSwap(
166+ _ char: Encoding . CodeUnit
167+ ) -> Bool {
143168 let size = MemoryLayout< Encoding . CodeUnit> . size
169+ var char = char
170+ if Endian . current == . little {
171+ char = char. byteSwapped
172+ }
144173 switch size {
145174 case 1 :
146175 return false
147176 case 2 :
148- return ptr . pointee == 0xFFFE /* ZERO WIDTH NO-BREAK SPACE (swapped) */
177+ return char == 0xFFFE /* ZERO WIDTH NO-BREAK SPACE */
149178 case 4 :
150- return ptr . pointee == UInt32 ( 0xFFFE0000 ) // avoid overflows in 32bit env
179+ return char == UInt32 ( 0xFFFE0000 ) // avoid overflows in 32bit env
151180 default :
152181 return false
153182 }
154183 }
155184}
185+
186+ fileprivate func handleSwap< Encoding: _UnicodeEncoding > (
187+ string: inout String ,
188+ at offset: Int ,
189+ length: Int ,
190+ fileHandle: some _FileIOProtocol ,
191+ hasBOM: Bool ,
192+ encoding: Encoding . Type
193+ ) {
194+ var data = try ! fileHandle. readData (
195+ offset: offset,
196+ length: length
197+ )
198+
199+ // strip BOM
200+ if hasBOM {
201+ data. removeFirst ( MemoryLayout< Encoding . CodeUnit> . size)
202+ }
203+
204+ data = data. byteSwapped ( Encoding . CodeUnit. self)
205+
206+ string = data. withUnsafeBytes {
207+ let baseAddress = $0. baseAddress!
208+ . assumingMemoryBound ( to: Encoding . CodeUnit. self)
209+ return . init(
210+ decodingCString: baseAddress,
211+ as: Encoding . self
212+ )
213+ }
214+ }
0 commit comments