ApacheCon: reinvigorating

gnat on 2003-11-19T07:05:50

I'd forgotten how much fun it is to code. Somehow, hanging around the PHP folks, as they sit around and casually program while chatting, reawakens the dormant hacker in me. I don't know why, but the same thing happened last year.

So this evening, while those who had money were off seeing Zumanity (Cirque du Soleil, n3kk1d), I started hacking again. I have about 1/3 of a POP3 server written in Perl. I got sidetracked halfway through and started playing with Apple's AddressBook API in C.

What I learned is that I really like Perl. Perl hides a lot of stuff that you really shouldn't have to think about. Like strings, for example. I can't believe how amazingly painful it is to just print a list of the names of people in your address book. This is, I suspect, a byproduct of using the CoreFoundation classes for strings, but I'm forced to because that's what AddressBook does.

Check it out:


  for (i=0; i < count; i++) {
    ABPersonRef thisPerson;
    CFStringRef firstNameCF, lastNameCF;
    CFDataRef   firstNameDR, lastNameDR;
    CFIndex     firstNameLength, lastNameLength;

    thisPerson = (ABPersonRef) CFArrayGetValueAtIndex(array, i);
    firstNameCF = ABRecordCopyValue(thisPerson, kABFirstNameProperty);
    if (firstNameCF) {
      firstNameLength = CFStringGetLength(firstNameCF);
      firstNameDR = CFStringCreateExternalRepresentation(NULL, firstNameCF, CFStringGetSystemEncoding(), '?');
      printf("%.*s ",
             (int)CFDataGetLength(firstNameDR), CFDataGetBytePtr(firstNameDR));
      CFRelease(firstNameDR);
      CFRelease(firstNameCF);
    }

    lastNameCF = ABRecordCopyValue(thisPerson, kABLastNameProperty);
    if (lastNameCF) {
      lastNameLength = CFStringGetLength(lastNameCF);
      lastNameDR = CFStringCreateExternalRepresentation(NULL, lastNameCF, CFStringGetSystemEncoding(), '?');
      printf("%.*s", 
             (int)CFDataGetLength(lastNameDR), CFDataGetBytePtr(lastNameDR));
      CFRelease(lastNameDR);
      CFRelease(lastNameCF);
    }
    printf("\n");
  }
All that, just to do the equivalent of:
  foreach my $thisPerson (@array) {
    $firstName = $thisPerson->{firstName} || "";
    $lastName = $thisPerson->{lastName} || "";
    print "$firstName $lastName\n";
  }
How can anyone program in this ridiculous quagmire of strings, C strings, data references, ... ? I seriously hope there's an easier way that I'm missing.

--Nat


Avoid the CoreFoundation

ziggy on 2003-11-19T23:33:50

Why would you ever code against the CF* APIs? It's for masochists, foot-draggers, and hackers working at a low level. For anything serious, you really should be using the ObjC frameworks. If you're into that much pain, go buy the new Brittany album instead.

Here's the same code using the AddressBook framework. Note how it's almost Perl-like in a perverse kind of way:

#import <Foundation/Foundation.h>
#import <AddressBook/AddressBook.h>

void dump_ab_people() {
    NSArray *people = [[ABAddressBook sharedAddressBook] people];
    NSEnumerator *iter = [people objectEnumerator];
    ABPerson *person;

    while (person = [iter nextObject]) {
        NSLog(@"%@ %@\n",[person valueForProperty:kABFirstNameProperty],
                         [person valueForProperty:kABLastNameProperty]);
    }
}

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...
    dump_ab_people();

    [pool release];
    return 0;
}
Not as easy as Perl, but not as fugly as the CF* version. Throw this into a "Foundation Tool", add the framework, and you're good to go.

Re:Avoid the CoreFoundation

gnat on 2003-11-20T01:15:23

I was thinking about turning it into a Perl XS module, and I was trying to start with what I know (C) instead of taking the risk of discovering problems with XS and Objective C.

So the CoreFoundation is just a cunning plot to make Objective C seem attractive? Got it. :-)

--Nat

Re:Avoid the CoreFoundation

ziggy on 2003-11-20T02:08:45

No, CoreFoundation does have its uses. IBM's SWT is a high level abstraction of a modern GUI. It translates to CoreFoundation on the MacOSX side and the Win32 C API on the Windows side. But apps like that are rare.

Building...

jonasbn on 2004-01-15T10:17:40

I was looking at your very nice example, can you guide me on getting started building?

I have followed some guidelines from the 'OS X for Unix Geeks' and ADC documentation, but without any luck.

I am on 10.3 and I have the developer tools installed.

Re:Building...

ziggy on 2004-01-15T13:49:27

If you've got the developer tools installed, take a spin around /Developer/Documentation. Apple has lots of reference documentation and tutorials to get you started. They really want to help you write Cocoa apps. Most of the topics in the references contain overviews and introductions to get you started.

You may want to get a copy of one of the Cocoa programming books from O'Reilly. I've got Simson Garfinkel's (mostly because he wrote the NeXTSTEP version, from which the O'Reilly title is derived). I looked at the TOC for James Duncan Davidson's book, and I'd probably buy that one today if I were looking for my first book.

pop3 server

jcavanaugh on 2003-11-20T07:50:24

Is this from the ground up, or is it leveraging any of the previous perl pop3 server attempts??

I hope your little coding hack takes off, frankly I would love to see a basic pop3 & imap server implementation in perl. Extending a basic framework like that to create dynamic virtual folders etc, could be wicked cool.

-- John Cavanaugh

Re:pop3 server

gnat on 2003-11-20T15:19:35

It's from the ground up, just proving to myself that it can be done without a zillion CPAN modules. I was excited about dynamic virtual folders, but when Casey asked me what I'd use it for, I struggled to come up with much more than "uh, turn your mail client into an RSS aggregator?". Either I'm not thinking hard enough about what I could do with it, or I thought the idea was cooler than it actually is ...

--Nat

Re:pop3 server

stas on 2003-11-20T19:04:52

Nat, why don't you write the first practical mod_perl 2.0 protocol module. It should be a trivial thing once you have the basic code working by itself. On my mod_perl 2.0 I keep on saying that you can now implement protocols in mod_perl, like imap, pop3, etc. But it'd be much better if I could say. Nat implemented an imap protocol for mod_perl 2.0 in N hours, here is the URL.

Re:pop3 server

jimw on 2003-11-21T17:33:46

like qpsmtpd, i think a pop3/imap server written in perl would simply be accessible for hacking and experimentation.

mandrill was my start at writing something like an imap server. (not really a true server, but something meant to be run using mutt's tunnel feature.)

but the imap spec bites. you really don't want to write an imap server.