Brian M. Coyner

Excellence in Software Development

Counting Characters

A few days ago I read a STL Lambda Lounge post about Counting DNA Nucleotides. After solving the Nucleotides problem in Objective-C, I decided to solve a slightly different problem. I decided to count and print the number of times each character (assume ASCII text) appears in Moby Dick. I used the same data structure to solve both problems: an array of unsigned int values, where the array index represents the ASCII character and the value is the count.

Reading Moby Dick using Grand Central Dispatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// This function blocks until all characters are counted.
void CBRCountCharactersInFileAtPath(NSString *path, unsigned int *characters)
{
    // The dispatch_io_read is an asynchronous call. We use a semaphore to provide synthetic synchronization.
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    dispatch_queue_t readQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_io_t channel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, [path UTF8String], 0, O_RDONLY, readQueue, NULL);

    // SIZE_MAX means keep going until we reach EOF. 
    dispatch_io_read(channel, 0, SIZE_MAX, readQueue, ^(bool done, dispatch_data_t data, int error) {
        if (done) {
            // All bytes have been read. Let's notify that we are done.
            dispatch_semaphore_signal(semaphore);
        } else if (data != NULL) {

            // As we read, we count.
            NSString *string = CBRStringFromDispatchData(data);
            CBRCountCharactersInString(string, characters);
        }
    });

    // Block the calling queue/ thread until the IO read completes (i.e. the channel is "done")
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    // What we open, we must close. 
    dispatch_io_close(channel, 0);
}

The above code sets up and executes streaming file IO using Grand Central Dispatch. Now let’s look at the two functions named CBRStringFromDispatchData and CBRCountCharactersInString.

Here is the code used to create a NSString from a dispatch_data_t.

1
2
3
4
5
6
7
8
9
10
NSString *CBRStringFromDispatchData(dispatch_data_t data)
{
    size_t dataSize = dispatch_data_get_size(data);
    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:dataSize];
    dispatch_data_apply(data, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
        [string appendFormat:@"%.*s", (unsigned int)size, buffer];
        return true;
    });
    return string;
}

Here is the code that tracks the character counts.

1
2
3
4
5
6
void CBRCountCharactersInString(NSString *string, unsigned int *characters)
{
    for (unsigned int index = 0; index < [string length]; index++) {
        characters[[string characterAtIndex:index]]++;
    }
}

Sample Program

1
2
3
4
5
6
7
8
9
10
11
#import "CBRCounter.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        unsigned int characters[256] = {0};
        CBRCountCharactersInFileAtPath(@"/path/to/mobydick.txt", characters);
        CBRPrintCharacterCount(characters);
    }
    return 0;
}

Printing the Character Counts

1
2
3
4
5
6
7
void CBRPrintCharacterCount(unsigned int *characters)
{
    // This example only prints the "printable" characters. 
    for (unsigned int character = ' '; character <= '~'; character++) {
        NSLog(@"%c: %d", (char)character, characters[character]);
    }
}

Example Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
A: 2725
B: 1466
C: 1184
D: 802
E: 1361
F: 864
G: 751
H: 1497
I: 3641
J: 261
K: 185
L: 959
M: 782
N: 1241
O: 1050
P: 1158
Q: 323
R: 895
S: 2277
T: 2568
U: 284
V: 181
W: 1326
X: 25
Y: 360
Z: 38

Verify the Counts

I verified my program’s results using TextEdit.

  1. Open “Moby Dick” in TextEdit
  2. Type Command+F
  3. Deselect “Ignore Case”
  4. Select “Contains”
  5. Enter Character
  6. View TextEdit’s Result

Using Git Sparse Checkout

There are times when all I want or need from a Git repo are a handful files. For example, I use the awesome git-completion and git-prompt scripts included in the Git project. Thus, I don’t need the entire Git repo taking up space.

This is exactly what sparse checkouts enable.

Here are the steps to create a “sparse” Git local repository that only includes the “Completion” scripts.

Step 1: Create a directory.

I named mine git-completion. You can name the directory whatever you want.

1
2
mkdir git-completion
cd git-completion

Step 2: Initialize a Git repository

1
git init

Step 3: Enable Sparse Checkouts

1
git config core.sparsecheckout true

Step 4: Tell Git which directories you want

1
echo contrib/completion/ >> .git/info/sparse-checkout

Or you can modify the .git/info/sparse-checkout file directly. Either way is fine.

Step 5: Add the remote

1
git remote add -f origin https://github.com/git/git.git

Final Step: Fetch the files

1
git pull origin master

You should now have the contrib/completion directory. No other Git source files exist in your local copy.

Sourcing the files

Update your .bashrc file.

1
2
source ~/Development/git-completion/contrib/completion/git-completion.bash
source ~/Development/git-completion/contrib/completion/git-prompt.sh

West St. Louis CocoaHeads, May 28, 2013

Bluetooth LE: Using iOS CoreBluetooth to communicate with “the Internet of Things”

By Jason Graves

BLE or Bluetooth ‘Low Energy’ is a fairly new wireless spec designed to connect us to world around us. This includes gathering data from embedded sensors like a thermostat or heart rate monitor, or controlling the lights in your house or unlocking the front door without a key. Apple’s CoreBluetooth framework has been around since iOS 5, but we are only now starting to see many new BLE enabled devices become available. We will cover some of the interesting uses of BLE and how to use CoreBluetooth to create your own apps that can communicate with these devices.

  • 6:00pm - Meet/Greet
  • 6:15pm - Bluetooth LE
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).

West St. Louis CocoaHeads, April 30, 2013

iOS Tool Talks

Why I Bought AppCode

By Jason Hanson

AppCode, by JetBrains, is what an IDE should be. All the tools I have come to know and love in a ‘grown-up’ IDE for the Objective-C and iOS platform. My productivity, and more importantly, my confidence to refactor, skyrocketed when I started using AppCode. Come learn about some of the powerful features, tips, tricks, and shortcuts AppCode has to offer the iOS developer.

Lighten the load on your teams with Jenkins

By JP Revel

If you’ve ever been part of a software project with a team, it often falls to one person to compile the project when it comes time to deliver. There are lots of problems with this approach. One solution is to set up a CI server, such as Jenkins (formerly Hudson). I will talk about the concept of CI, go over a sample setup, show some configuration and (hopefully) have Jenkins build a project for us.

  • 6:00pm - Meet/Greet
  • 6:15pm - iOS Tools Talk
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).

West St. Louis CocoaHeads, March 26, 2013

UIStoryBoards

By Rick Aurbach

While apps with straightforward UI designs can often be implemented effectively using a single storyboard and GUI-based segues, this approach is less effective for large complex UI designs. This talk will discuss techniques for dividing an application’s UI into multiple storyboards and implementing programmatically-generated segues. We will discuss tab bar controllers, embedding sub-controllers into views, popover controllers, and navigation controllers. The talk will hopefully appeal to newbies and veterans alike.

  • 6:00pm - Meet/Greet
  • 6:15pm - UIStoryboards by Rick Aurbach
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).

West St. Louis CocoaHeads, February 26, 2013

Unit Testing Objective-C Applications

By Jeff Roberts

The vast majority of developers don’t write unit tests against their applications. The typical design of many iOS applications and the iOS SDK can make it challenging to write tests. We will learn about some basic unit testing principles, mocking with OCMock, asserting with OCHamcrest, swizzling and even cheating with KVO, while keeping score with some helpful utilities like OCUnit2JUnit and code coverage with gcov.

  • 6:00pm - Meet/Greet
  • 6:15pm - Unit Testing Objective-C Applications by Jeff Roberts
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).

West St. Louis CocoaHeads, January 29, 2013

LLDB

By Brian Coyner

LLDB is the default debugger in Xcode on OS X. LLDB supports debugging Objective-C, C, and C++. We will discuss various aspects of the debugger, as well as look at how to utilize LLDB to effectively debug apps.

  • LLDB architecture
  • Various LLDB commands (setting breakpoints, setting watchpoints, thread control, etc.)
  • Using the LLDB Python bridge to “script” a debug session
  • 6:00pm - Meet/Greet
  • 6:15pm - LLDB by Brian Coyner
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).

West St. Louis CocoaHeads, December 27, 2012

5 Things Every iOS Developer Should Know

By Brian Coyner

Brian will discuss 5 things every iOS developer should know. Plus a few bonus items.

  • 6:00pm - Meet/Greet
  • 6:15pm - 5 Things Every iOS Developer Should Know by Brian Coyner
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).

West St. Louis CocoaHeads, October 25, 2012

Tonight’s Session is Canceled. Presenter is sick!!!

5 Things Every iOS Developer Should Know

By Brian Coyner

Brian will discuss 5 things every iOS developer should know. Plus a few bonus items.

  • 6:00pm - Meet/Greet
  • 6:15pm - 5 Things Every iOS Developer Should Know by Brian Coyner
  • 7:30pm - Next Meeting Details, Questions / Discussions

St. Louis County Library Headquarters (East Room); (314) 994-3300; (1640 S. Lindbergh Blvd).