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