Strange behavior of UnsafeMutablePointer - swift

I've built a little structure which holds a pseudo-C-String UnsafeMutablePointer. Now I wanted to add a way to get the length of the String, but something behaved very strange:
struct Char {
let value: CChar
init(_ char: CChar) {
self.value = char
}
}
extension Char: CustomStringConvertible {
var description: String {
return String(UnicodeScalar(UInt8(bitPattern: self.value)))
}
}
extension Char: Equatable {
public static func ==(lhs: Char, rhs: Char) -> Bool {
return lhs.value == rhs.value
}
}
struct CharPointer {
let pointer: UnsafeMutablePointer<Char>
init(_ string: String) {
let chars = string.cString(using: .utf8)!.map { Char($0) }
self.pointer = UnsafeMutablePointer(mutating: chars)
}
subscript(_ offset: Int) -> Char {
get { return self.pointer[offset] }
set { self.pointer[offset] = newValue }
}
var length: Int {
var ptr = self.pointer
while ptr.pointee != Char(0) {
ptr += 1
}
return ptr - self.pointer
}
}
let pointer = CharPointer("Hello World!")
print(pointer[0])
// print(pointer.length)
If I don't use the length property, everything works just fine and the print statement prints an "H". But if I try to access pointer.length, it prints a newline, although I use the property after the print statement, and the length is 0. Is this a bug or have I made a mistake?

Thanks to #Hamish I found a solution, I just initialize a second pointer with the pointer from the array:
init(_ string: String) {
let chars = string.cString(using: .utf8)!.map { Char($0) }
let pointer = UnsafeMutablePointer(mutating: chars)
let pointer2 = UnsafeMutablePointer<Char>.allocate(capacity: chars.count)
pointer2.initialize(from: pointer, count: chars.count)
self.pointer = pointer2
}

Related

Save random alphanumeric string in Userdefaults

i'm new to swift and i have a problem. How i can save randomly generated for each user alphanumeric string in user defaults?
func randomString(of length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var s = ""
for _ in 0 ..< length {
s.append(letters.randomElement()!)
}
return s
}
static var keyS: Bool {
get {
return ((UserDefaults.standard.integer(forKey: randomString(of: 16)) != 0))
}
set {
UserDefaults.standard.set(1, forKey: randomString(of: 16))
}
}
i tried this, but it didn't work. hope somebody can help me
Here "1" is your key for storing the random string. You can set it anything you want. Try this-
func randomString(of length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var s = ""
for _ in 0 ..< length {
s.append(letters.randomElement()!)
}
return s
}
static var keyS: Bool {
get {
return ((UserDefaults.standard.integer(forKey: "1") != 0))
}
set {
UserDefaults.standard.set(randomString(of: 16), forKey: "1")
}
}

How Swift Vars automatically convert to My Any Type

I was doing some research on AnyXXX struct like AnyHashable, then I write a similar container named MyAnyHashable.
There's some issues
when I using the original AnyHashalbe is Swift, it works fine:
func usingAppleAnyHashable() {
var dict = Dictionary<AnyHashable, Any>()
// using literal as key always works
dict[1] = 1
dict["efg"] = "efg_value"
// using some var as key still works
let any1 = 100
let any2 = "abc"
dict[any1] = 100
dict[any2] = "abc_value"
print(dict)
}
it can automatically convert Int's var into AnyHashable, what a Magic!
let any1 = 100
let any2 = "abc"
dict[any1] = 100
dict[any2] = "abc_value"
Then, I using MyAnyHashable as the Key's Type
func usingMyAnyHashable() {
var dict = Dictionary<MyAnyHashable, Any>()
// using literal as key always works
dict[1] = 1
dict["efg"] = "efg_value"
// it show errors: Cannot convert value of type 'Int' to expected argument type 'MyAnyHashable'...
let any1 = 100
let any2 = "abc"
dict[any1] = 100
dict[any2] = "abc_value"
print(dict)
}
I must write like this to manually create a MyAnyHashable instance
dict[MyAnyHashable(any1)] = 100
What is the Magic in Apple's AnyHashable?
How to make it automatically convert non-Literal var into MyAnyHashable?
Here is MyAnyHashable implementation, I even wrote a ExpressibleByXXXXLiteral which can automatically transform literalType to MyAnyHashable.
struct MyAnyHashable : Hashable, Equatable {
private let baseHash: Int
private let base: Any
init<H: Hashable>(_ base: H) {
self.base = base
self.baseHash = base.hashValue
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.baseHash)
}
static func == (lhs: MyAnyHashable, rhs: MyAnyHashable) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
extension MyAnyHashable : ExpressibleByStringLiteral, ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral {
typealias StringLiteralType = String
init(stringLiteral value: StringLiteralType) {
self.init(value)
}
typealias IntegerLiteralType = Int
init(integerLiteral value: IntegerLiteralType) {
self.init(value)
}
typealias FloatLiteralType = Float
init(floatLiteral value: FloatLiteralType) {
self.init(value)
}
}
screenshots

Can Swift structs self-delete?

Consider the following:
struct MiniString {
private(set) var value: String
init(_ value: String) {
if value.count < 17 {
self.value = value
} else {
selfDeleteSomehow()
}
}
}
Elsewhere this could be instantiated thus:
var ms: MiniString? = MiniString("This string is too long to be accepted")
print(ms) // prints 'nil'
Context: my specific use-case is for a func declaration in a protocol that would return a Double between 0.0 and 1.0, but no higher or lower, something like:
protocol DoubleBetweenZeroAndOneProtocol {
func getResult() -> DoubleBetweenZeroAndOne
}
You could use a failable initializer:
struct MiniString {
var value: String { return value_ }
private let value_: String
init?(_ seedValue: String) {
if seedValue.count < 17 {
value_ = seedValue
} else {
return nil
}
}
}

Generate random String without repeating in swift

I want the function to generate random String without repeating.
For example this function maybe will print: ABCC
func randomString(length:Int) -> String {
let charSet = "ABCDEF"
var c = charSet.characters.map { String($0) }
var s:String = ""
for _ in (1...length) {
s.append(c[Int(arc4random()) % c.count])
}
return s
} print(randomString(length: 4))
and i want print random unique string only, E.g : ABCD
import GameplayKit
func randomString(length : Int) -> String {
let charSet = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: charSet) as! [Character]
let array = shuffled.prefix(length)
return String(array)
}
print(randomString(length: 4))
func randomString(length: Int) -> String {
let charSet = "ABCDEF"
var charSetArray = charSet.characters.map { String($0) }
var randArray: [String] = []
while charSetArray.count > 0 {
let i = Int(arc4random_uniform(UInt32(charSetArray.count)))
randArray.append(charSetArray[i])
charSetArray.remove(at: i)
}
var output: String = ""
for i in 0..<length {
output.append(randArray[i])
}
return output
}
How to use:
let randomString = "ABCDEF".random(length: 3)!
The return value is optional because the length might exceed the length of provided string.
Check out the full implementation:
import UIKit
import PlaygroundSupport
extension MutableCollection where Indices.Iterator.Element == Index {
mutating func shuffle() {
let c = count
guard c > 1 else { return }
for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
swap(&self[firstUnshuffled], &self[i])
}
}
}
extension Sequence {
func shuffled() -> [Iterator.Element] {
var result = Array(self)
result.shuffle()
return result
}
}
extension String {
func random(length: Int) -> String? {
let uniqueCharacters = Array(Set(characters.map({ String($0) })))
guard length <= uniqueCharacters.count else { return nil }
guard length > 0 else { return nil }
return uniqueCharacters[0..<length].shuffled().joined()
}
}

Insertion-Order Dictionary (like Java's LinkedHashMap) in Swift?

Is there a standard swift class that is a Dictionary, but keeps keys in insertion-order like Java's LinkedHashMap? If not, how would one be implemented?
Didn't know of one and it was an interesting problem to solve (already put it in my standard library of stuff) Mostly it's just a matter of maintaining a dictionary and an array of the keys side-by-side. But standard operations like for (key, value) in od and for key in od.keys will iterate in insertion order rather than a semi random fashion.
// OrderedDictionary behaves like a Dictionary except that it maintains
// the insertion order of the keys, so iteration order matches insertion
// order.
struct OrderedDictionary<KeyType:Hashable, ValueType> {
private var _dictionary:Dictionary<KeyType, ValueType>
private var _keys:Array<KeyType>
init() {
_dictionary = [:]
_keys = []
}
init(minimumCapacity:Int) {
_dictionary = Dictionary<KeyType, ValueType>(minimumCapacity:minimumCapacity)
_keys = Array<KeyType>()
}
init(_ dictionary:Dictionary<KeyType, ValueType>) {
_dictionary = dictionary
_keys = map(dictionary.keys) { $0 }
}
subscript(key:KeyType) -> ValueType? {
get {
return _dictionary[key]
}
set {
if newValue == nil {
self.removeValueForKey(key)
}
else {
self.updateValue(newValue!, forKey: key)
}
}
}
mutating func updateValue(value:ValueType, forKey key:KeyType) -> ValueType? {
let oldValue = _dictionary.updateValue(value, forKey: key)
if oldValue == nil {
_keys.append(key)
}
return oldValue
}
mutating func removeValueForKey(key:KeyType) {
_keys = _keys.filter { $0 != key }
_dictionary.removeValueForKey(key)
}
mutating func removeAll(keepCapacity:Int) {
_keys = []
_dictionary = Dictionary<KeyType,ValueType>(minimumCapacity: keepCapacity)
}
var count: Int { get { return _dictionary.count } }
// keys isn't lazy evaluated because it's just an array anyway
var keys:[KeyType] { get { return _keys } }
// values is lazy evaluated because of the dictionary lookup and creating a new array
var values:GeneratorOf<ValueType> {
get {
var index = 0
return GeneratorOf<ValueType> {
if index >= self._keys.count {
return nil
}
else {
let key = self._keys[index]
index++
return self._dictionary[key]
}
}
}
}
}
extension OrderedDictionary : SequenceType {
func generate() -> GeneratorOf<(KeyType, ValueType)> {
var index = 0
return GeneratorOf<(KeyType, ValueType)> {
if index >= self._keys.count {
return nil
}
else {
let key = self._keys[index]
index++
return (key, self._dictionary[key]!)
}
}
}
}
func ==<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
return lhs._keys == rhs._keys && lhs._dictionary == rhs._dictionary
}
func !=<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
return lhs._keys != rhs._keys || lhs._dictionary != rhs._dictionary
}
Swift 5 version:
// OrderedDictionary behaves like a Dictionary except that it maintains
// the insertion order of the keys, so iteration order matches insertion
// order.
struct OrderedDictionary<KeyType: Hashable, ValueType> {
private var _dictionary: Dictionary<KeyType, ValueType>
private var _keys: Array<KeyType>
init() {
_dictionary = [:]
_keys = []
}
init(minimumCapacity: Int) {
_dictionary = Dictionary<KeyType, ValueType>(minimumCapacity: minimumCapacity)
_keys = Array<KeyType>()
}
init(_ dictionary: Dictionary<KeyType, ValueType>) {
_dictionary = dictionary
_keys = dictionary.keys.map { $0 }
}
subscript(key: KeyType) -> ValueType? {
get {
_dictionary[key]
}
set {
if newValue == nil {
self.removeValueForKey(key: key)
} else {
_ = self.updateValue(value: newValue!, forKey: key)
}
}
}
mutating func updateValue(value: ValueType, forKey key: KeyType) -> ValueType? {
let oldValue = _dictionary.updateValue(value, forKey: key)
if oldValue == nil {
_keys.append(key)
}
return oldValue
}
mutating func removeValueForKey(key: KeyType) {
_keys = _keys.filter {
$0 != key
}
_dictionary.removeValue(forKey: key)
}
mutating func removeAll(keepCapacity: Int) {
_keys = []
_dictionary = Dictionary<KeyType, ValueType>(minimumCapacity: keepCapacity)
}
var count: Int {
get {
_dictionary.count
}
}
// keys isn't lazy evaluated because it's just an array anyway
var keys: [KeyType] {
get {
_keys
}
}
var values: Array<ValueType> {
get {
_keys.map { _dictionary[$0]! }
}
}
static func ==<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
lhs._keys == rhs._keys && lhs._dictionary == rhs._dictionary
}
static func !=<Key: Equatable, Value: Equatable>(lhs: OrderedDictionary<Key, Value>, rhs: OrderedDictionary<Key, Value>) -> Bool {
lhs._keys != rhs._keys || lhs._dictionary != rhs._dictionary
}
}
extension OrderedDictionary: Sequence {
public func makeIterator() -> OrderedDictionaryIterator<KeyType, ValueType> {
OrderedDictionaryIterator<KeyType, ValueType>(sequence: _dictionary, keys: _keys, current: 0)
}
}
struct OrderedDictionaryIterator<KeyType: Hashable, ValueType>: IteratorProtocol {
let sequence: Dictionary<KeyType, ValueType>
let keys: Array<KeyType>
var current = 0
mutating func next() -> (KeyType, ValueType)? {
defer { current += 1 }
guard sequence.count > current else {
return nil
}
let key = keys[current]
guard let value = sequence[key] else {
return nil
}
return (key, value)
}
}
I didn't found way to make values 'lazy'.. need more research