{"id":2377,"date":"2016-01-01T17:17:46","date_gmt":"2016-01-01T23:17:46","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=2377"},"modified":"2016-01-01T17:17:46","modified_gmt":"2016-01-01T23:17:46","slug":"swift-substring-on-a-c-string","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/swift-substring-on-a-c-string\/","title":{"rendered":"Swift Substring on a C String"},"content":{"rendered":"<p>String handling in Swift has been a moving target.  While following the evolution of performing certain string operations in Swift, I&#8217;ve been reminded of the <a href=\"http:\/\/www.joelonsoftware.com\/articles\/Unicode.html\">post<\/a> Joel Spolsky wrote over a decade ago admonishing all of us to get with the program and support <a href=\"https:\/\/en.wikipedia.org\/wiki\/Unicode\">Unicode<\/a> in our applications from day one.  While Swift 1.0 didn&#8217;t ignore the request, it certainly did make it easier to use &#8220;natural&#8221; expressions to extract substrings with ranges.  Swift 2.0 tossed that out the window, and a top-rated <a href=\"http:\/\/stackoverflow.com\/questions\/24044851\/how-do-you-use-string-substringwithrange-or-how-do-ranges-work-in-swift\">answer<\/a> on Stackoverflow becomes useless.  <\/p>\n<p>Don&#8217;t try this at home, it won&#8217;t work, but it sure would be nice if it did:<\/p>\n<pre class:swift>\r\nvar helloWorld = \"Hello, world!\"\r\nlet hello      = helloWorld[0...4]\r\nprint(hello)\r\n<\/pre>\n<p>I mean, it works for Python with `hello = helloWorld[0:5]`, why can&#8217;t it work in Swift?<\/p>\n<p>Like we said, Swift 2 is taking Joel&#8217;s 2003 plea to heart, and working to make us all (painfully) more aware that these aren&#8217;t your father&#8217;s strings.  There is a great summary as to the rationale at <a href=\"https:\/\/www.mikeash.com\/pyblog\/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html\">mikeash.com<\/a> so there&#8217;s no reason for me to rehash characters vs. graphemes here.  And while I &#8220;get it&#8221;, there&#8217;s no doubt its an aggravation trying to remember what magic I need to invoke to get a substring out of what I know is going to be a `const char*` C-style ASCII-based string.  So, I won&#8217;t bother trying to remember, I&#8217;ll just write it here for you and for me.<\/p>\n<h3>A Simple Substring<\/h3>\n<p>I&#8217;ve been looking at ways to blend more Swift programming in my day-to-day Linux tasks.  I really think it has an opportunity to displace <a href=\"https:\/\/www.perl.org\/\">some<\/a> <a href=\"https:\/\/www.python.org\/\">other<\/a> <a href=\"https:\/\/www.ruby-lang.org\/en\/\">languages<\/a> for quick scripts and &#8220;devops&#8221;-oriented tasks.  In this case I wanted a quick way to print out the `git` revisions of the projects that make up an open source Swift build.  Here&#8217;s what I came up with:<\/p>\n<pre class=\"lang:swift\">\r\nimport Glibc\r\n\r\nfunc getGitRevision(dirname:String) -> String {\r\n  let BUFSIZE = 128\r\n  let cwd     = String.fromCString(getcwd(nil, 0))!\r\n  var rc      = chdir(dirname)\r\n  \r\n  guard rc == 0 else {\r\n    return \"ERROR\"\r\n  }\r\n  \r\n  var rev  = \"\"\r\n  let pipe = popen(\"\/usr\/bin\/git rev-parse HEAD\", \"r\")\r\n  var buf  = [CChar](count:BUFSIZE, repeatedValue:CChar(0))\r\n  while fgets(&buf, Int32(BUFSIZE), pipe) != nil {\r\n    rev = String.fromCString(buf)!\r\n  }\r\n  rev = rev[rev.startIndex...rev.startIndex.advancedBy(9)]\r\n\r\n  chdir(cwd)\r\n\r\n  return rev\r\n}\r\n\r\nlet dirs = [\"swift\", \"llvm\", \"clang\", \"lldb\", \"cmark\", \"llbuild\", \"swiftpm\", \"swift-corelibs-xctest\", \"swift-corelibs-foundation\", \"swift-integration-tests\"]\r\n\r\nfor dir in dirs {\r\n  let rev = getGitRevision(dir)\r\n  print(\"\\(dir):\\(rev)\")\r\n}\r\n<\/pre>\n<p>Getting the first 10 characters of the `git` revision hash with `rev = rev[rev.startIndex&#8230;rev.startIndex.advancedBy(9)]` is a little more verbose than it should be, but if you are dealing with what you know to be a C-style string, it gets the job done.<\/p>\n<h3>Extend It<\/h3>\n<p>Fortunately for us, Swift supports <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/Swift\/Conceptual\/Swift_Programming_Language\/Extensions.html\">extensions<\/a>, that awesome feature that allows you to tack on some methods to a class you didn&#8217;t write and don&#8217;t have source access to.  Many folks have posted <a href=\"https:\/\/help.github.com\/articles\/about-gists\/\">gists<\/a> of this particular extension which provides a little syntactic sugar for accessing substrings:<\/p>\n<pre class=\"lang:swift\">\r\nextension String {\r\n  subscript (r: Range<Int>) -> String {\r\n    get {\r\n      let startIndex = self.startIndex.advancedBy(r.startIndex)\r\n      let endIndex   = self.startIndex.advancedBy(r.endIndex)\r\n            \r\n      return self[Range(start: startIndex, end: endIndex)]\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>With our extension we can indeed write:<\/p>\n<pre class=\"lang:swift\">\r\nlet helloWorld = \"Hello, world!\"\r\nvar hello      = helloWorld[0...4]\r\n\r\nprint(hello)\r\n<\/pre>\n<p>Life is good.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>String handling in Swift has been a moving target. While following the evolution of performing certain string operations in Swift, I&#8217;ve been reminded of the post Joel Spolsky wrote over a decade ago admonishing all of us to get with the program and support Unicode in our applications from day one. While Swift 1.0 didn&#8217;t [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-2377","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2377"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=2377"}],"version-history":[{"count":10,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2377\/revisions"}],"predecessor-version":[{"id":2387,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2377\/revisions\/2387"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=2377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=2377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=2377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}