<commit_before>//
//  main.swift
//  OCToSwift
//
//  Created by MA806P on 2018/12/1.
//  Copyright © 2018 myz. All rights reserved.
//

import Foundation

print("Hello, World!")


// -----------------------------

//UnsafePointer
/*
 Swift 是一门非常安全的语言，所有的引用或者变量的类型都是确定并且正确对应他们得实际类型的，
 应当无法进行任意的类型转换，也不能直接通过指针作出一些出格的事。有助于避免不必要的bug，迅速稳定的
 找出代码错误。在高安全的同时，也丧失了部分的灵活性。
 
 为了与 C 系帝国进行合作，Swift 定义了一套对 C 语言指针的访问和转换方法 UnsafePointer
 “对于使用 C API 时如果遇到接受内存地址作为参数，或者返回是内存地址的情况，在 Swift 里会将它们转为 UnsafePointer<Type> 的类型”
 
 “UnsafePointer，就是 Swift 中专门针对指针的转换。对于其他的 C 中基础类型，在 Swift 中对应的类型都遵循统一的命名规则：
 在前面加上一个字母 C 并将原来的第一个字母大写：比如 int，bool 和 char 的对应类型分别是 CInt，CBool 和 CChar。
 在下面的 C 方法中，我们接受一个 int 的指针，转换到 Swift 里所对应的就是一个 CInt 的 UnsafePointer 类型。
 这里原来的 C API 中已经指明了输入的 num 指针的不可变的 (const)，因此在 Swift 中我们与之对应的是 UnsafePointer 这个不可变版本。
 如果只是一个普通的可变指针的话，我们可以使用 UnsafeMutablePointer 来对应：
 C API           Swift API
 const Type *    UnsafePointer
 Type *          UnsafeMutablePointer”
 
 
 如何在指针的内容和实际的值之间进行转换
 
 */

//C 语言
//void method(const int *num) { printf("%d", *num); }
// int a = 123; method(&a);

//对应的 Swift 方法应该是：
func method(_ num: UnsafePointer<CInt>) {
    print(num.pointee)
}
var a: CInt = 123
method(&a) //123

//func CFArrayGetValueAtIndex(theArray: CFArray!, idx: CFIndex) -> UnsafePointer<Any> { }
//“CFArray 中是可以存放任意对象的，所以这里的返回是一个任意对象的指针，相当于 C 中的 void *。
//这显然不是我们想要的东西。Swift 中为我们提供了一个强制转换的方法 unsafeBitCast，
//通过下面的代码，我们可以看到应当如何使用类似这样的 API，将一个指针强制按位转成所需类型的对象：
let arr = NSArray(object: "meow")
let str = unsafeBitCast(CFArrayGetValueAtIndex(arr, 0), to: CFString.self)
// str = "meow”
//“unsafeBitCast 会将第一个参数的内容按照第二个参数的类型进行转换，而不去关心实际是不是可行，
//这也正是 UnsafePointer 的不安全所在，因为我们不必遵守类型转换的检查，而拥有了在指针层面直接操作内存的机会。”
//“Apple 将直接的指针访问冠以 Unsafe 的前缀，就是提醒我们：这些东西不安全，亲们能不用就别用了吧”




//C 指针内存管理
/*
 C 指针在 Swift 被冠名 unsafe 的另一个原因是无法对其2进行自动的内存管理，需要手动来申请释放内存
 */

class MyClass {
    var a = 1
    deinit {
        print("deinit")
    }
}

var pointer: UnsafeMutablePointer<MyClass>!
pointer = UnsafeMutablePointer<MyClass>.allocate(capacity: 1)
pointer.initialize(to: MyClass())
print(pointer.pointee.a) //1
//pointer = nil //UnsafeMutablePointer 不会自动内存管理，指向的内存没有释放回收，没有调用 deinit
pointer.deinitialize(count: 1)//释放指针指向的内存的对象以及指针自己本身
pointer = nil // deinit

//“手动处理这类指针的内存管理时，我们需要遵循的一个基本原则就是谁创建谁释放。
//deallocate 与 deinitialize 应该要和 allocate 与 initialize 成对出现”
//“如果我们是通过调用了某个方法得到的指针，那么除非文档或者负责这个方法的开发者明确告诉你应该由使用者进行释放，否则都不应该去试图管理它的内存状态：

var x:UnsafeMutablePointer<tm>!
var t = time_t()
time(&t)
x = localtime(&t)
x = nil
//指针的内存申请也可以使用 malloc 或者 calloc 来完成，这种情况下在释放时我们需要对应使用 free 而不是 deallocate。





// -----------------------------

/*

//String 还是 NSString
/*
 像 string 这样的 Swift 类型和 Foundation 的对应的类是可以无缝转换的，使用时怎么选择
 尽可能的使用原生的 string 类型。
 1、虽然有良好的互相转换的特性，但现在 Cocoa所有的API都接受和返回string类型，不必给自己凭空添加麻烦把框架返回的
 字符串做一遍转换
 2、在Swift中String是struct，相比NSString类来说更切合字符串的”不变“这一特性。配合常量赋值let，
 这种不变性在多线程编程就非常重要了。在不触及NSString特有操作和动态特性的时候使用String的方法，在性能上也有所提升。<commit_msg>COpaquePointer<commit_after>//
//  main.swift
//  OCToSwift
//
//  Created by MA806P on 2018/12/1.
//  Copyright © 2018 myz. All rights reserved.
//

import Foundation

print("Hello, World!")



// -----------------------------

/*
 “在 C 中有一类指针，你在头文件中无法找到具体的定义，只能拿到类型的名字，而所有的实现细节都是隐藏的。
 这类指针在 C 或 C++ 中被叫做不透明指针 (Opaque Pointer)，顾名思义，它的实现和表意对使用者来说是不透明的。”

 swift 中对应这类不透明指针的类型是 COpaquePointer 用来表示那些在 Swift 中无法进行类型描述的 C 指针，其他的用
 更准确的 UnsafePointer<T> 来存储
 
 “COpaquePointer 在 Swift 中扮演的是指针转换的中间人的角色，我们可以通过这个类型在不同指针类型间进行转换，除非有十足的把握
 知道自己在干什么，否则不要这么做。
 
 另外一种重要指针指向函数的指针，
 在 C 中的函数
 int cFunction(int (callBack)(int x, int y)) { return callBack(1, 2); }
 如果想要在 Swift 中使用这个函数
 
 let callback: @convention(c) (Int32, Int32) -> Int32 = {
 (x, y) -> Int32 in
 return x + y }
 
 let result = cFunction(callback)
 print(result) // 3”

 let result = cFunction {
 (x, y) -> Int32 in return x + y
 }
 
 
*/





// -----------------------------

/*
//UnsafePointer
/*
 Swift 是一门非常安全的语言，所有的引用或者变量的类型都是确定并且正确对应他们得实际类型的，
 应当无法进行任意的类型转换，也不能直接通过指针作出一些出格的事。有助于避免不必要的bug，迅速稳定的
 找出代码错误。在高安全的同时，也丧失了部分的灵活性。
 
 为了与 C 系帝国进行合作，Swift 定义了一套对 C 语言指针的访问和转换方法 UnsafePointer
 “对于使用 C API 时如果遇到接受内存地址作为参数，或者返回是内存地址的情况，在 Swift 里会将它们转为 UnsafePointer<Type> 的类型”
 
 “UnsafePointer，就是 Swift 中专门针对指针的转换。对于其他的 C 中基础类型，在 Swift 中对应的类型都遵循统一的命名规则：
 在前面加上一个字母 C 并将原来的第一个字母大写：比如 int，bool 和 char 的对应类型分别是 CInt，CBool 和 CChar。
 在下面的 C 方法中，我们接受一个 int 的指针，转换到 Swift 里所对应的就是一个 CInt 的 UnsafePointer 类型。
 这里原来的 C API 中已经指明了输入的 num 指针的不可变的 (const)，因此在 Swift 中我们与之对应的是 UnsafePointer 这个不可变版本。
 如果只是一个普通的可变指针的话，我们可以使用 UnsafeMutablePointer 来对应：
 C API           Swift API
 const Type *    UnsafePointer
 Type *          UnsafeMutablePointer”
 
 
 如何在指针的内容和实际的值之间进行转换
 
 */

//C 语言
//void method(const int *num) { printf("%d", *num); }
// int a = 123; method(&a);

//对应的 Swift 方法应该是：
func method(_ num: UnsafePointer<CInt>) {
    print(num.pointee)
}
var a: CInt = 123
method(&a) //123

//func CFArrayGetValueAtIndex(theArray: CFArray!, idx: CFIndex) -> UnsafePointer<Any> { }
//“CFArray 中是可以存放任意对象的，所以这里的返回是一个任意对象的指针，相当于 C 中的 void *。
//这显然不是我们想要的东西。Swift 中为我们提供了一个强制转换的方法 unsafeBitCast，
//通过下面的代码，我们可以看到应当如何使用类似这样的 API，将一个指针强制按位转成所需类型的对象：
let arr = NSArray(object: "meow")
let str = unsafeBitCast(CFArrayGetValueAtIndex(arr, 0), to: CFString.self)
// str = "meow”
//“unsafeBitCast 会将第一个参数的内容按照第二个参数的类型进行转换，而不去关心实际是不是可行，
//这也正是 UnsafePointer 的不安全所在，因为我们不必遵守类型转换的检查，而拥有了在指针层面直接操作内存的机会。”
//“Apple 将直接的指针访问冠以 Unsafe 的前缀，就是提醒我们：这些东西不安全，亲们能不用就别用了吧”




//C 指针内存管理
/*
 C 指针在 Swift 被冠名 unsafe 的另一个原因是无法对其2进行自动的内存管理，需要手动来申请释放内存
 */

class MyClass {
    var a = 1
    deinit {
        print("deinit")
    }
}

var pointer: UnsafeMutablePointer<MyClass>!
pointer = UnsafeMutablePointer<MyClass>.allocate(capacity: 1)
pointer.initialize(to: MyClass())
print(pointer.pointee.a) //1
//pointer = nil //UnsafeMutablePointer 不会自动内存管理，指向的内存没有释放回收，没有调用 deinit
pointer.deinitialize(count: 1)//释放指针指向的内存的对象以及指针自己本身
pointer = nil // deinit

//“手动处理这类指针的内存管理时，我们需要遵循的一个基本原则就是谁创建谁释放。
//deallocate 与 deinitialize 应该要和 allocate 与 initialize 成对出现”
//“如果我们是通过调用了某个方法得到的指针，那么除非文档或者负责这个方法的开发者明确告诉你应该由使用者进行释放，否则都不应该去试图管理它的内存状态：

var x:UnsafeMutablePointer<tm>!
var t = time_t()
time(&t)
x = localtime(&t)
x = nil
//指针的内存申请也可以使用 malloc 或者 calloc 来完成，这种情况下在释放时我们需要对应使用 free 而不是 deallocate。

*/


// -----------------------------

/*

//String 还是 NSString
/*
 像 string 这样的 Swift 类型和 Foundation 的对应的类是可以无缝转换的，使用时怎么选择
 尽可能的使用原生的 string 类型。
 1、虽然有良好的互相转换的特性，但现在 Cocoa所有的API都接受和返回string类型，不必给自己凭空添加麻烦把框架返回的
 字符串做一遍转换
 2、在Swift中String是struct，相比NSString类来说更切合字符串的”不变“这一特性。配合常量赋值let，
 这种不变性在多线程编程就非常重要了。在不触及NSString特有操作和动态特性的时候使用String的方法，在性能上也有所提升。
{'fraction_non_alphanumeric': 0.1242603550295858, 'fraction_numerical': 0.01137915339098771, 'mean_word_length': 4.354995938261576, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5382219', 'n_tokens_mistral': 4058, 'n_tokens_neox': 4208, 'n_words': 541}