Convert c string into string sqlite swift [duplicate] - ios

We are implementing SQLite in iOS, in Swift, without using wrappers or Objective-C bridging. Everything works fine, except when doing a query and extracting the result. The issue is with the UnsafePointer<UInt8> that is returned from SQLite in Swift as follows:
var querySQL = "SELECT address, phone FROM CONTACTS WHERE NAME = 'myName'"
var cQuery = querySQL.cStringUsingEncoding(NSUTF8StringEncoding)
var statement: COpaquePointer = nil
if sqlite3_prepare_v2(contactsDB, cQuery!, -1, &statement, nil) == SQLITE_OK {
if sqlite3_step(statement) == SQLITE_ROW {
var address : UnsafePointer<UInt8> = sqlite3_column_text(statement, 0)
var data = NSData(bytes: address, length: 10)
var string = NSString(data: data, encoding: NSUTF8StringEncoding)
println(string)
As you can see, we can convert the pointer to String if we know the length of the object (in this case 10)
To dig into this issue, I have the following example
let pointerFromString: UnsafePointer<Int8> = "xyz".cStringUsingEncoding(NSUTF8StringEncoding)
let stringFromPointer = String.fromCString(anotherPointerFromString_Int8) println(stringFromPointer!)
Given that CChar is an alias of Int8, I can convert a String to UnsafePointer<Int8> using .cStringUsingEncoding(), and then back to String using .fromCString(<UnsafePointer_CChar>)
The problem is that my SQLite result is a UnsafePointer_UInt8, that can´t be used with .fromCString()
The bottom line question is: Is it possible to convert or cast a UnsafePointer_UInt8 to UnsafePointer_Int8

This should work:
let address = sqlite3_column_text(statement, 0)
let string = String.fromCString(UnsafePointer<CChar>(address))
Update for Swift 3 (Xcode 8), compare Swift 3: convert a null-terminated UnsafePointer<UInt8> to a string:
let string = String(cString: sqlite3_column_text(statement, 0))
Update:
sqlite3_column_text() returns an implicitly unwrapped optional, and that is why you can pass it to String(cString:) directly.
But according to Column methods, error and NULL handling #41, the return value can be null (in an out-of-memory situation, or if called with a NULL column type). Therefore it is safer to do
if let text = sqlite3_column_text(statement, 0) {
let string = String(cString: text)
// ...
} else {
// sqlite3_column_text() returned NULL
}

Related

Swift 3 UnsafePointer sqlite [duplicate]

We are implementing SQLite in iOS, in Swift, without using wrappers or Objective-C bridging. Everything works fine, except when doing a query and extracting the result. The issue is with the UnsafePointer<UInt8> that is returned from SQLite in Swift as follows:
var querySQL = "SELECT address, phone FROM CONTACTS WHERE NAME = 'myName'"
var cQuery = querySQL.cStringUsingEncoding(NSUTF8StringEncoding)
var statement: COpaquePointer = nil
if sqlite3_prepare_v2(contactsDB, cQuery!, -1, &statement, nil) == SQLITE_OK {
if sqlite3_step(statement) == SQLITE_ROW {
var address : UnsafePointer<UInt8> = sqlite3_column_text(statement, 0)
var data = NSData(bytes: address, length: 10)
var string = NSString(data: data, encoding: NSUTF8StringEncoding)
println(string)
As you can see, we can convert the pointer to String if we know the length of the object (in this case 10)
To dig into this issue, I have the following example
let pointerFromString: UnsafePointer<Int8> = "xyz".cStringUsingEncoding(NSUTF8StringEncoding)
let stringFromPointer = String.fromCString(anotherPointerFromString_Int8) println(stringFromPointer!)
Given that CChar is an alias of Int8, I can convert a String to UnsafePointer<Int8> using .cStringUsingEncoding(), and then back to String using .fromCString(<UnsafePointer_CChar>)
The problem is that my SQLite result is a UnsafePointer_UInt8, that can´t be used with .fromCString()
The bottom line question is: Is it possible to convert or cast a UnsafePointer_UInt8 to UnsafePointer_Int8
This should work:
let address = sqlite3_column_text(statement, 0)
let string = String.fromCString(UnsafePointer<CChar>(address))
Update for Swift 3 (Xcode 8), compare Swift 3: convert a null-terminated UnsafePointer<UInt8> to a string:
let string = String(cString: sqlite3_column_text(statement, 0))
Update:
sqlite3_column_text() returns an implicitly unwrapped optional, and that is why you can pass it to String(cString:) directly.
But according to Column methods, error and NULL handling #41, the return value can be null (in an out-of-memory situation, or if called with a NULL column type). Therefore it is safer to do
if let text = sqlite3_column_text(statement, 0) {
let string = String(cString: text)
// ...
} else {
// sqlite3_column_text() returned NULL
}

iOS: Convert UnsafeMutablePointer<Int8> to String in swift?

As the title says, what is the correct way to convert UnsafeMutablePointer to String in swift?
//lets say x = UnsafeMutablePointer<Int8>
var str = x.memory.????
I tried using x.memory.description obviously it is wrong, giving me a wrong string value.
If the pointer points to a NUL-terminated C string of UTF-8 bytes, you can do this:
import Foundation
let x: UnsafeMutablePointer<Int8> = ...
// or UnsafePointer<Int8>
// or UnsafePointer<UInt8>
// or UnsafeMutablePointer<UInt8>
let str = String(cString: x)
Times have changed. In Swift 3+ you would do it like this:
If you want the utf-8 to be validated:
let str: String? = String(validatingUTF8: c_str)
If you want utf-8 errors to be converted to the unicode error symbol: �
let str: String = String(cString: c_str)
Assuming c_str is of type UnsafePointer<UInt8> or UnsafePointer<CChar> which is the same type and what most C functions return.
this:
let str: String? = String(validatingUTF8: c_str)
doesn't appear to work with UnsafeMutablePointer<UInt8>
(which is what appears to be in my data).
This is me trivially figuring out how to do something like the C/Perl system function:
let task = Process()
task.launchPath = "/bin/ls"
task.arguments = ["-lh"]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
var unsafePointer = UnsafeMutablePointer<Int8>.allocate(capacity: data.count)
data.copyBytes(to: unsafePointer, count: data.count)
let output : String = String(cString: unsafePointer)
print(output)
//let output : String? = String(validatingUTF8: unsafePointer)
//print(output!)
if I switch to validatingUTF8 (with optional) instead of cString, I get this error:
./ls.swift:19:37: error: cannot convert value of type 'UnsafeMutablePointer<UInt8>' to expected argument type 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>')
let output : String? = String(validatingUTF8: unsafePointer)
^~~~~~~~~~~~~
Thoughts on how to validateUTF8 on the output of the pipe (so I don't get the unicode error symbol anywhere)?
(yes, I'm not doing proper checking of my optional for the print(), that's not the problem I'm currently solving ;-) ).

Properly used NSGetExecutablePath

I try to get the path to my application at runtime. I found some old sources from C and converted it accordingly to the functions parameter type definition:
var path = [Int8] (count:1024, repeatedValue: 0)
var bufsize : UInt32 = 1024
if _NSGetExecutablePath(&path, &bufsize) == 0 {
println("executable path is \(path)")
}
It runs, but I need an Int8 array, not a string. So I have to search for the end of the character chain and convert it back to a string. What is the correct way to use this function in SWIFT?
You need to create a Swift String from a C String
let executablePath = String(CString: path, encoding: NSASCIIStringEncoding)!
println("executable path is \(executablePath)")
But there is an easier way to get the path to the executable
let executablePath = Bundle.main.executablePath!
In Swift 4
let executablePath = Bundle.main.executablePath!
print(executablePath)

use fscanf() function in swift code

In objective c, I use fscanf to read stream from file and assign the value to variables:
int count;
char type[5];
fscanf(myFile, “count is %d, type is %4s ”, &count, type)
I want to do the same thing in swift code, I tried:
//ERROR: Type annotation missing in pattern
//What type should I use for `count`?
var count
//ERROR: consecutive statement on a line must be separated by ‘;’
var type[5] : char
fscanf(myFile, “count is %d, type is %4s ”, &count, type)
But I got compiler errors showing above. What is the correct way to use fscanf in swift ?
If you know any swift way to achieve the same thing (without using fscanf), it would be great too!
I recommend you use Foundation framework solution for reading/writing file data. A sample code to read contents of files which I used in my app to stream file into NSData:
if let fileHandle = NSFileHandle(forReadingAtPath: "path/to/file") {
fileHandle.seekToFileOffset(0)
var data = fileHandle.readDataOfLength(5)
var chars = [UInt8](count: 5, repeatedValue: 0)
data.getBytes(&chars, length: 5)
fileHandle.closeFile()
}
In case you need read Int64 data from file at a specific location:
if let fileHandle = NSFileHandle(forReadingAtPath: "path/to/file") {
fileHandle.seekToFileOffset(0)
var data = fileHandle.readDataOfLength(500)
var intFetched: Int64 = 0
let location = 100 // start at 101st character of file
data.getBytes(&intFetched, range: NSMakeRange(location, 8))
println(intFetched.littleEndian)
fileHandle.closeFile()
}

Issue with UnsafePointer<Uint8> in SQLite project in Swift

We are implementing SQLite in iOS, in Swift, without using wrappers or Objective-C bridging. Everything works fine, except when doing a query and extracting the result. The issue is with the UnsafePointer<UInt8> that is returned from SQLite in Swift as follows:
var querySQL = "SELECT address, phone FROM CONTACTS WHERE NAME = 'myName'"
var cQuery = querySQL.cStringUsingEncoding(NSUTF8StringEncoding)
var statement: COpaquePointer = nil
if sqlite3_prepare_v2(contactsDB, cQuery!, -1, &statement, nil) == SQLITE_OK {
if sqlite3_step(statement) == SQLITE_ROW {
var address : UnsafePointer<UInt8> = sqlite3_column_text(statement, 0)
var data = NSData(bytes: address, length: 10)
var string = NSString(data: data, encoding: NSUTF8StringEncoding)
println(string)
As you can see, we can convert the pointer to String if we know the length of the object (in this case 10)
To dig into this issue, I have the following example
let pointerFromString: UnsafePointer<Int8> = "xyz".cStringUsingEncoding(NSUTF8StringEncoding)
let stringFromPointer = String.fromCString(anotherPointerFromString_Int8) println(stringFromPointer!)
Given that CChar is an alias of Int8, I can convert a String to UnsafePointer<Int8> using .cStringUsingEncoding(), and then back to String using .fromCString(<UnsafePointer_CChar>)
The problem is that my SQLite result is a UnsafePointer_UInt8, that can´t be used with .fromCString()
The bottom line question is: Is it possible to convert or cast a UnsafePointer_UInt8 to UnsafePointer_Int8
This should work:
let address = sqlite3_column_text(statement, 0)
let string = String.fromCString(UnsafePointer<CChar>(address))
Update for Swift 3 (Xcode 8), compare Swift 3: convert a null-terminated UnsafePointer<UInt8> to a string:
let string = String(cString: sqlite3_column_text(statement, 0))
Update:
sqlite3_column_text() returns an implicitly unwrapped optional, and that is why you can pass it to String(cString:) directly.
But according to Column methods, error and NULL handling #41, the return value can be null (in an out-of-memory situation, or if called with a NULL column type). Therefore it is safer to do
if let text = sqlite3_column_text(statement, 0) {
let string = String(cString: text)
// ...
} else {
// sqlite3_column_text() returned NULL
}

Resources