Created
December 7, 2018 17:42
-
-
Save jckarter/b79cd96619979a24ef251eebf1aee08e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Darwin | |
struct FormatString: ExpressibleByStringInterpolation { | |
final class StringInterpolation: StringInterpolationProtocol { | |
var formatString = "" | |
var args: [CVarArg] = [] | |
var buffers: [UnsafeMutableRawPointer] = [] | |
init() {} | |
init(literalCapacity: Int, interpolationCount: Int) {} | |
deinit { | |
for buffer in buffers { free(buffer) } | |
} | |
func appendLiteral(_ literal: String) { | |
formatString += literal.replacingOccurrences(of: "%", with: "%%") | |
} | |
func appendInterpolation(_ string: String) { | |
formatString += "%s" | |
string.withCString { | |
let buffer = strdup($0)! | |
buffers += [UnsafeMutableRawPointer(buffer)] | |
args += [buffer] | |
} | |
} | |
func appendInterpolation(_ integer: Int) { | |
formatString += "%zd" | |
args += [integer] | |
} | |
func appendInterpolation(hex integer: Int) { | |
formatString += "0x%zx" | |
args += [integer] | |
} | |
func appendInterpolation(_ bool: Bool) { | |
appendInterpolation(bool ? "true" : "false") | |
} | |
} | |
var interpolation: StringInterpolation | |
init(stringInterpolation: StringInterpolation) { | |
self.interpolation = stringInterpolation | |
} | |
init(stringLiteral: String) { | |
let interpolation = StringInterpolation() | |
interpolation.appendLiteral(stringLiteral) | |
self.interpolation = interpolation | |
} | |
} | |
func withFormatStringAndArgs(_ string: FormatString, | |
call body: (UnsafePointer<CChar>, CVaListPointer) -> ()) { | |
string.interpolation.formatString.withCString { stringPtr in | |
withVaList(string.interpolation.args) { vaList in | |
body(stringPtr, vaList) | |
} | |
} | |
} | |
withFormatStringAndArgs("%hello% \("world"). it's \(true). \(123) \(hex: 0x123)\n") { | |
vprintf($0, $1) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment