10
10
11
11
import CoreFoundation
12
12
13
- #if os(macOS) || os(iOS)
13
+ #if _runtime(_ObjC) // if objc_enum works, restore the old names:
14
14
let kCFCharacterSetControl = CFCharacterSetPredefinedSet . control
15
15
let kCFCharacterSetWhitespace = CFCharacterSetPredefinedSet . whitespace
16
16
let kCFCharacterSetWhitespaceAndNewline = CFCharacterSetPredefinedSet . whitespaceAndNewline
@@ -26,10 +26,46 @@ let kCFCharacterSetCapitalizedLetter = CFCharacterSetPredefinedSet.capitalizedLe
26
26
let kCFCharacterSetSymbol = CFCharacterSetPredefinedSet . symbol
27
27
let kCFCharacterSetNewline = CFCharacterSetPredefinedSet . newline
28
28
let kCFCharacterSetIllegal = CFCharacterSetPredefinedSet . illegal
29
+
30
+ let kCFCharacterSetKeyedCodingTypeBitmap = CFCharacterSetKeyedCodingType . bitmap
31
+ let kCFCharacterSetKeyedCodingTypeBuiltin = CFCharacterSetKeyedCodingType . builtin
32
+ let kCFCharacterSetKeyedCodingTypeRange = CFCharacterSetKeyedCodingType . range
33
+ let kCFCharacterSetKeyedCodingTypeString = CFCharacterSetKeyedCodingType . string
34
+ let kCFCharacterSetKeyedCodingTypeBuiltinAndBitmap = CFCharacterSetKeyedCodingType . builtinAndBitmap
35
+ #endif
36
+
37
+ #if _runtime(_ObjC)
38
+ fileprivate let lastKnownPredefinedCharacterSetConstant = kCFCharacterSetNewline. rawValue
39
+ #else
40
+ fileprivate let lastKnownPredefinedCharacterSetConstant = kCFCharacterSetNewline
29
41
#endif
30
42
43
+ fileprivate func knownPredefinedCharacterSet( rawValue: Int ) -> CFCharacterSetPredefinedSet ? {
44
+ if rawValue > 0 && rawValue <= lastKnownPredefinedCharacterSetConstant {
45
+ #if _runtime(_ObjC)
46
+ return CFCharacterSetPredefinedSet ( rawValue: rawValue)
47
+ #else
48
+ return CFCharacterSetPredefinedSet ( rawValue)
49
+ #endif
50
+ } else {
51
+ return nil
52
+ }
53
+ }
54
+
55
+ fileprivate extension String {
56
+ static let characterSetBitmapRepresentationKey = " NSBitmap "
57
+ static let characterSetAltBitmapRepresentationKey = " NSBitmapObject "
58
+ static let characterSetStringKey = " NSString "
59
+ static let characterSetAltStringKey = " NSStringObject "
60
+ static let characterSetRangeKey = " NSRange "
61
+ static let characterSetBuiltinIDKey = " NSBuiltinID "
62
+ static let characterSetNewBuiltinIDKey = " NSBuiltinID2 "
63
+ static let characterSetIsInvertedKey = " NSIsInverted "
64
+ static let characterSetNewIsInvertedKey = " NSIsInverted2 "
65
+ }
31
66
32
- open class NSCharacterSet : NSObject , NSCopying , NSMutableCopying , NSCoding {
67
+
68
+ open class NSCharacterSet : NSObject , NSCopying , NSMutableCopying , NSSecureCoding {
33
69
typealias CFType = CFCharacterSet
34
70
private var _base = _CFInfo ( typeID: CFCharacterSetGetTypeID ( ) )
35
71
private var _hashValue = CFHashCode ( 0 )
@@ -162,9 +198,141 @@ open class NSCharacterSet : NSObject, NSCopying, NSMutableCopying, NSCoding {
162
198
}
163
199
}
164
200
165
- public convenience required init ( coder aDecoder: NSCoder ) {
166
- self . init ( charactersIn: " " )
167
- NSUnimplemented ( )
201
+ open class var supportsSecureCoding : Bool { return true }
202
+
203
+ public required init ? ( coder aDecoder: NSCoder ) {
204
+ guard aDecoder. allowsKeyedCoding else {
205
+ fatalError ( " Decoding requires a NSCoder that allows keyed coding. " )
206
+ }
207
+
208
+ func fail( code: CocoaError . Code = . coderReadCorrupt, _ message: String ) {
209
+ aDecoder. failWithError ( NSError ( domain: NSCocoaErrorDomain, code: code. rawValue, userInfo: [ NSLocalizedDescriptionKey: message ] ) )
210
+ }
211
+
212
+ let finalSet : CFCharacterSet
213
+
214
+ var builtinType = aDecoder. decodeInteger ( forKey: . characterSetBuiltinIDKey)
215
+ if builtinType == 0 {
216
+ builtinType = aDecoder. decodeInteger ( forKey: . characterSetNewBuiltinIDKey)
217
+ }
218
+
219
+ let isInverted = aDecoder. decodeBool ( forKey: . characterSetIsInvertedKey)
220
+
221
+ let keyedUnarchiver = aDecoder as? NSKeyedUnarchiver
222
+ let containsCharacterSetStringKeyName = aDecoder. containsValue ( forKey: . characterSetStringKey)
223
+ let containsCharacterSetStringAltKeyName = aDecoder. containsValue ( forKey: . characterSetAltStringKey)
224
+
225
+ if let predefinedSet = knownPredefinedCharacterSet ( rawValue: builtinType) {
226
+ guard let theSet = CFCharacterSetGetPredefined ( predefinedSet) else {
227
+ fail ( " CFCharacterSetGetPredefined -- Predefined Character Set not found " )
228
+ return nil
229
+ }
230
+
231
+ finalSet = theSet
232
+ } else if aDecoder. containsValue ( forKey: . characterSetRangeKey) {
233
+ let range = UInt64 ( bitPattern: aDecoder. decodeInt64 ( forKey: . characterSetRangeKey) )
234
+ guard let theSet = CFCharacterSetCreateWithCharactersInRange ( kCFAllocatorSystemDefault, CFRangeMake ( CFIndex ( range >> 32 ) , CFIndex ( range & 0xFFFFFFFF ) ) ) else {
235
+ fail ( " CFCharacterSetCreateWithCharactersInRange -- Character Set creation with characters in range failed " )
236
+ return nil
237
+ }
238
+
239
+ finalSet = theSet
240
+ } else if containsCharacterSetStringKeyName || containsCharacterSetStringAltKeyName {
241
+ let maybeResult : NSString ?
242
+
243
+ if let keyedUnarchiver = keyedUnarchiver, containsCharacterSetStringKeyName {
244
+ maybeResult = keyedUnarchiver. _decodePropertyListForKey ( . characterSetStringKey) as? NSString
245
+ } else {
246
+ maybeResult = aDecoder. decodeObject ( of: NSString . self, forKey: . characterSetAltStringKey)
247
+ }
248
+
249
+ guard let result = maybeResult else {
250
+ fail ( code: . coderValueNotFound, " Decoder value not found " )
251
+ return nil
252
+ }
253
+
254
+ guard let theSet = CFCharacterSetCreateWithCharactersInString ( kCFAllocatorSystemDefault, result. _cfObject) else {
255
+ fail ( " CFCharacterSetCreateWithCharactersInString -- Character Set creation with characters in string failed " )
256
+ return nil
257
+ }
258
+
259
+ finalSet = theSet
260
+ } else {
261
+ let maybeResult : NSData ?
262
+
263
+ if let keyedUnarchiver = keyedUnarchiver, keyedUnarchiver. containsValue ( forKey: . characterSetBitmapRepresentationKey) {
264
+ maybeResult = keyedUnarchiver. _decodePropertyListForKey ( . characterSetBitmapRepresentationKey) as? NSData
265
+ } else {
266
+ maybeResult = aDecoder. decodeObject ( of: NSData . self, forKey: . characterSetAltBitmapRepresentationKey)
267
+ }
268
+
269
+ guard let result = maybeResult else {
270
+ fail ( code: . coderValueNotFound, " Decoder value not found " )
271
+ return nil
272
+ }
273
+
274
+ guard let theSet = CFCharacterSetCreateWithBitmapRepresentation ( kCFAllocatorSystemDefault, result. _cfObject) else {
275
+ fail ( " CFCharacterSetCreateWithBitmapRepresentation -- Character Set creation with bitmap representation failed " )
276
+ return nil
277
+ }
278
+
279
+ finalSet = theSet
280
+ }
281
+
282
+ super. init ( )
283
+ _CFCharacterSetInitCopyingSet ( kCFAllocatorSystemDefault, _cfMutableObject, finalSet, type ( of: self ) is NSMutableCharacterSet . Type , false )
284
+ if isInverted {
285
+ _CFCharacterSetSetIsInverted ( _cfMutableObject, isInverted)
286
+ }
287
+ }
288
+
289
+ public func encode( with aCoder: NSCoder ) {
290
+ guard aCoder. allowsKeyedCoding else {
291
+ fatalError ( " Encoding requires a NSCoder that allows keyed coding. " )
292
+ }
293
+
294
+ var isInverted = _CFCharacterSetIsInverted ( _cfObject)
295
+ let keyedArchiver = aCoder as? NSKeyedArchiver
296
+
297
+ switch _CFCharacterSetGetKeyedCodingType ( _cfObject) {
298
+ case kCFCharacterSetKeyedCodingTypeBuiltin:
299
+ aCoder. encode ( CFIndex ( _CFCharacterSetGetKeyedCodingBuiltinType ( _cfObject) . rawValue) , forKey: . characterSetBuiltinIDKey)
300
+
301
+ case kCFCharacterSetKeyedCodingTypeRange:
302
+ let range = _CFCharacterSetGetKeyedCodingRange ( _cfObject)
303
+
304
+ var value = UInt64 ( range. location)
305
+ value <<= 32
306
+ value |= UInt64 ( range. length)
307
+
308
+ aCoder. encode ( Int64 ( bitPattern: value) , forKey: . characterSetRangeKey)
309
+
310
+ case kCFCharacterSetKeyedCodingTypeString:
311
+ let string = _CFCharacterSetCreateKeyedCodingString ( _cfObject) . takeRetainedValue ( )
312
+ if let keyedArchiver = keyedArchiver {
313
+ keyedArchiver. _encodePropertyList ( string. _nsObject, forKey: . characterSetStringKey)
314
+ } else {
315
+ aCoder. encode ( string. _nsObject, forKey: . characterSetAltStringKey)
316
+ }
317
+
318
+ case kCFCharacterSetKeyedCodingTypeBuiltinAndBitmap:
319
+ aCoder. encode ( CFIndex ( _CFCharacterSetGetKeyedCodingBuiltinType ( _cfObject) . rawValue) , forKey: . characterSetNewBuiltinIDKey)
320
+ if isInverted { aCoder. encode ( true , forKey: . characterSetNewIsInvertedKey ) }
321
+
322
+ fallthrough
323
+ default :
324
+ if let keyedArchiver = keyedArchiver {
325
+ keyedArchiver. _encodePropertyList ( bitmapRepresentation. _nsObject, forKey: . characterSetBitmapRepresentationKey)
326
+ } else {
327
+ aCoder. encode ( bitmapRepresentation. _nsObject, forKey: . characterSetAltBitmapRepresentationKey)
328
+ }
329
+
330
+ isInverted = false
331
+ }
332
+
333
+ if isInverted {
334
+ aCoder. encode ( true , forKey: . characterSetIsInvertedKey)
335
+ }
168
336
}
169
337
170
338
open func characterIsMember( _ aCharacter: unichar ) -> Bool {
@@ -226,10 +394,6 @@ open class NSCharacterSet : NSObject, NSCopying, NSMutableCopying, NSCoding {
226
394
NSRequiresConcreteImplementation ( )
227
395
}
228
396
}
229
-
230
- open func encode( with aCoder: NSCoder ) {
231
- NSUnimplemented ( )
232
- }
233
397
}
234
398
235
399
open class NSMutableCharacterSet : NSCharacterSet {
0 commit comments