Swiftgram/Postbox/DeferredString.swift
2015-07-29 18:02:56 +03:00

125 lines
3.6 KiB
Swift

import Foundation
public protocol DeferredString {
var data: NSData { get }
var string: String { get }
}
private final class DeferredStringImpl {
var string: String!
var data: NSData!
var lock: OSSpinLock = 0
init(string: String!, data: NSData!) {
self.string = string
self.data = data
}
}
public final class DeferredStringValue: DeferredString, CustomStringConvertible, StringLiteralConvertible {
private var impl: DeferredStringImpl
public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
public typealias UnicodeScalarLiteralType = StringLiteralType
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.impl = DeferredStringImpl(string: "\(value)", data: nil)
}
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.impl = DeferredStringImpl(string: value, data: nil)
}
public init(stringLiteral value: StringLiteralType) {
self.impl = DeferredStringImpl(string: value, data: nil)
}
public init(_ string: String) {
self.impl = DeferredStringImpl(string: string, data: nil)
}
public init(_ data: NSData) {
self.impl = DeferredStringImpl(string: nil, data: data)
}
public var description: String {
return self.string
}
public var data: NSData {
if isUniquelyReferencedNonObjC(&self.impl) {
let value: NSData
if impl.data != nil {
value = impl.data
} else if impl.string != nil {
value = impl.string.dataUsingEncoding(NSUTF8StringEncoding) ?? NSData()
impl.data = value
} else {
value = NSData()
}
return value
} else {
let value: NSData
OSSpinLockLock(&impl.lock)
if impl.data != nil {
value = impl.data
} else if impl.string != nil {
value = impl.string.dataUsingEncoding(NSUTF8StringEncoding) ?? NSData()
impl.data = value
} else {
value = NSData()
}
OSSpinLockUnlock(&impl.lock)
return value
}
}
public var string: String {
if isUniquelyReferencedNonObjC(&self.impl) {
let value: String
if impl.string != nil {
value = impl.string
} else if impl.data != nil {
let fromData = NSString(data: impl.data, encoding: NSUTF8StringEncoding)
if fromData == nil {
value = ""
impl.string = value
} else {
value = fromData as! String
impl.string = value
}
} else {
value = ""
}
return value
} else {
let value: String
OSSpinLockLock(&impl.lock)
if impl.string != nil {
value = impl.string
} else if impl.data != nil {
let fromData = NSString(data: impl.data, encoding: NSUTF8StringEncoding)
if fromData == nil {
value = ""
impl.string = value
} else {
value = fromData as! String
impl.string = value
}
} else {
value = ""
}
OSSpinLockUnlock(&impl.lock)
return value
}
}
}