File: NSKeyedCoderOldStyleArray.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (109 lines) | stat: -rw-r--r-- 3,478 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//

@_implementationOnly import CoreFoundation

internal final class _NSKeyedCoderOldStyleArray : NSObject, NSCopying, NSSecureCoding, NSCoding {

    private var _addr : UnsafeMutableRawPointer // free if decoding
    private var _count : Int
    private var _size : Int
    private var _type : _NSSimpleObjCType
    private var _decoded : Bool = false
    
    static func sizeForObjCType(_ type: _NSSimpleObjCType) -> Int? {
        var size : Int = 0
        var align : Int = 0
        
        return _NSGetSizeAndAlignment(type, &size, &align) ? size : nil
    }

    // TODO: Why isn't `addr` passed as a mutable pointer?
    init?(objCType type: _NSSimpleObjCType, count: Int, at addr: UnsafeRawPointer) {
        self._addr = UnsafeMutableRawPointer(mutating: addr)
        self._count = count        

        guard let size = _NSKeyedCoderOldStyleArray.sizeForObjCType(type) else {
            return nil
        }

        self._size = size
        self._type = type
        self._decoded = false
    }

    deinit {
        if self._decoded {
            // Cannot deinitialize memory without knowing the element type.
            self._addr.deallocate()
        }
    }
    
    init?(coder aDecoder: NSCoder) {
        assert(aDecoder.allowsKeyedCoding)
        
        guard let type = _NSSimpleObjCType(UInt8(aDecoder.decodeInteger(forKey: "NS.type"))) else {
            return nil
        }
        
        self._count = aDecoder.decodeInteger(forKey: "NS.count")
        self._size = aDecoder.decodeInteger(forKey: "NS.size")
        self._type = type
        self._decoded = true

        if self._size != _NSKeyedCoderOldStyleArray.sizeForObjCType(type) {
            return nil
        }
        
        self._addr = UnsafeMutableRawPointer.allocate(byteCount: self._count * self._size, alignment: 1)
        
        super.init()
        
        for idx in 0..<self._count {
            var type = Int8(self._type)
            
            withUnsafePointer(to: &type) { typep in
                let addr = self._addr.advanced(by: idx * self._size)
                aDecoder.decodeValue(ofObjCType: typep, at: addr)
            }
        }
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(self._count, forKey: "NS.count")
        aCoder.encode(self._size, forKey: "NS.size")
        aCoder.encode(Int(self._type), forKey: "NS.type")
        
        for idx in 0..<self._count {
            var type = Int8(self._type)

            withUnsafePointer(to: &type) { typep in
                aCoder.encodeValue(ofObjCType: typep, at: self._addr + (idx * self._size))
            }
        }
    }
    
    static var supportsSecureCoding: Bool {
        return true
    }
    
    func fillObjCType(_ type: _NSSimpleObjCType, count: Int, at addr: UnsafeMutableRawPointer) {
        if type == self._type && count <= self._count {
            addr.copyMemory(from: self._addr, byteCount: count * self._size)
        }
    }
    
    override func copy() -> Any {
        return copy(with: nil)
    }
    
    func copy(with zone: NSZone? = nil) -> Any {
        return self
    }
}