<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" ><channel><title>Jon&#039;s Blog &#187; Jon</title> <atom:link href="http://jonshier.com/author/admin/feed/" rel="self" type="application/rss+xml" /><link>http://jonshier.com</link> <description>From my mind to your eyes</description> <lastBuildDate>Mon, 16 May 2011 04:16:36 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator> <item><title>Pixen: Out with old, in with the nu</title><link>http://jonshier.com/2011/05/16/pixen-out-with-old-in-with-the-nu/</link> <comments>http://jonshier.com/2011/05/16/pixen-out-with-old-in-with-the-nu/#comments</comments> <pubDate>Mon, 16 May 2011 04:16:36 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Cocoa]]></category> <category><![CDATA[Jon's Life]]></category> <category><![CDATA[Pixen]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://jonshier.com/?p=57</guid> <description><![CDATA[I&#8217;d been planning a Pixen update explaining my continued lack of progress for quite a while. That I was busy in my new role as an iOS developer for the company I&#8217;d been working at for over year. How I &#8230; <a href="http://jonshier.com/2011/05/16/pixen-out-with-old-in-with-the-nu/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>I&#8217;d been planning a Pixen update explaining my continued lack of progress for quite a while. That I was busy in my new role as an iOS developer for the company I&#8217;d been working at for over year. How I would surely make progress on Pixen by leveraging the skills I developed on the job. But then they decided to downsize their iOS team from 3 developers to 2 and I suddenly found myself unemployed. Luckily my night classes at the local community college have paid off and I&#8217;ve been admitted to the local university&#8217;s computer science program. So now instead of being to busy working to work on Pixen I&#8217;ll be too busy studying to work on Pixen. But fear not! I&#8217;ve found a solution: <strong>rewrite it</strong>. Yes, I know rewrites are usually a foolish waste of time and money, but fortunately being unpaid, all I&#8217;ll waste is time! Turns out that it&#8217;s much easier, at least for me, to create a pixel editor from scratch than it is to shoehorn Pixen&#8217;s current code into modern APIs. I call it nuPixen. It&#8217;s still in the prototype phase but it does enough to be worthy of a screenshot.<br /><div id="attachment_58" class="wp-caption aligncenter" style="width: 1013px"><a href="http://jonshier.com/wp-content/uploads/2011/05/nuPixenPrototype.png?cda6c1"><img src="http://jonshier.com/wp-content/uploads/2011/05/nuPixenPrototype.png?cda6c1" alt="A bit simplistic?" title="nuPixenPrototype" width="1003" height="852" class="size-full wp-image-58" /></a><p class="wp-caption-text">It can edit pixels, I swear!</p></div><br /> You may have noticed by the window controls that I am, in fact, developing on 10.7. This will eliminate any version specific code I need to write and allow me to take advantage of all of the Lion APIs without worrying about compatibility. nuPixen will be open source on my GitHub page but will not be available until sometime after Lion&#8217;s release. In the mean time I&#8217;ll be posting updates on my progress and questions for users of Pixen and Mac developers in general about how I should move forward. Like I said, I&#8217;m still in the prototype phase, so that means I&#8217;m still trying to grok the OS X imaging APIs and how to fundamentally write a pixel editor. As you can see from the screenshot though, I do have basic image input, editing, and output working, along with the ability to set your fill color and switch the pixel grid on and off.</p><p>This is where I&#8217;ve hit my first issue: my pixel grid is uneven. Here&#8217;s my current code:</p><div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRect</span><span style="color: #002200;">&#41;</span>dirtyRect
<span style="color: #002200;">&#123;</span>
    context <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSGraphicsContext</span> currentContext<span style="color: #002200;">&#93;</span> graphicsPort<span style="color: #002200;">&#93;</span>;
    CGContextAddRect<span style="color: #002200;">&#40;</span>context, NSRectToCGRect<span style="color: #002200;">&#40;</span>self.bounds<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
	CGContextSetRGBStrokeColor<span style="color: #002200;">&#40;</span>context, 1.0f, 0.0f, 0.0f, 1.0f<span style="color: #002200;">&#41;</span>;
	CGContextStrokePath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
    CGContextSetInterpolationQuality<span style="color: #002200;">&#40;</span>context, kCGInterpolationNone<span style="color: #002200;">&#41;</span>;
    CGContextSetShouldAntialias<span style="color: #002200;">&#40;</span>context, <span style="color: #a61390;">NO</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>image<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
&nbsp;
        <span style="color: #a61390;">NSRect</span> imageRect <span style="color: #002200;">=</span> NSZeroRect;
        imageRect.size <span style="color: #002200;">=</span> CGImageGetSize<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>image CGImage<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
        drawRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self bounds<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">NSRect</span> viewRect <span style="color: #002200;">=</span> drawRect;
        CGFloat aspectRatio <span style="color: #002200;">=</span> imageRect.size.width <span style="color: #002200;">/</span> imageRect.size.height;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>viewRect.size.width <span style="color: #002200;">/</span> viewRect.size.height &lt;<span style="color: #002200;">=</span> aspectRatio<span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            drawRect.size.width <span style="color: #002200;">=</span> viewRect.size.width;
            drawRect.size.height <span style="color: #002200;">=</span> imageRect.size.height <span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span>viewRect.size.width <span style="color: #002200;">/</span> imageRect.size.width<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">else</span>
        <span style="color: #002200;">&#123;</span>
            drawRect.size.height <span style="color: #002200;">=</span> viewRect.size.height;
            drawRect.size.width <span style="color: #002200;">=</span> imageRect.size.width <span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span>viewRect.size.height <span style="color: #002200;">/</span> imageRect.size.height<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        drawRect.origin.x <span style="color: #002200;">+=</span> <span style="color: #002200;">&#40;</span>viewRect.size.width <span style="color: #002200;">-</span> drawRect.size.width<span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> <span style="color: #2400d9;">2.0</span>;
        drawRect.origin.y <span style="color: #002200;">+=</span> <span style="color: #002200;">&#40;</span>viewRect.size.height <span style="color: #002200;">-</span> drawRect.size.height<span style="color: #002200;">&#41;</span> <span style="color: #002200;">/</span> <span style="color: #2400d9;">2.0</span>;
&nbsp;
        CGContextDrawImage<span style="color: #002200;">&#40;</span>context, drawRect, <span style="color: #002200;">&#91;</span>image CGImage<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>showPixelGrid<span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">//Draw grid by creating start and end points for vertical and horizontal lines.</span>
            <span style="color: #11740a; font-style: italic;">//FIXME: Grid is uneven, especially at smaller sizes. </span>
            CGContextSetStrokeColorWithColor<span style="color: #002200;">&#40;</span>context, CGColorGetConstantColor<span style="color: #002200;">&#40;</span>kCGColorBlack<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
            CGContextAddRect<span style="color: #002200;">&#40;</span>context, drawRect<span style="color: #002200;">&#41;</span>;
            CGContextStrokePath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
            NSUInteger numXPoints <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>imageRect.size.width <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span>;
            NSUInteger numYPoints <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>imageRect.size.height <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span>;
            CGPoint xPoints<span style="color: #002200;">&#91;</span>numXPoints<span style="color: #002200;">&#93;</span>;
            CGPoint yPoints<span style="color: #002200;">&#91;</span>numYPoints<span style="color: #002200;">&#93;</span>;
            CGPoint startPoint;
            CGPoint endPoint;
            CGFloat widthRatio <span style="color: #002200;">=</span> drawRect.size.width <span style="color: #002200;">/</span> imageRect.size.width;
            CGFloat heightRatio <span style="color: #002200;">=</span> drawRect.size.height <span style="color: #002200;">/</span> imageRect.size.height;
            startPoint.x  <span style="color: #002200;">=</span> drawRect.origin.x;
            startPoint.y <span style="color: #002200;">=</span> drawRect.origin.y;
            endPoint.x <span style="color: #002200;">=</span> drawRect.origin.x;
            endPoint.y <span style="color: #002200;">=</span> drawRect.size.height <span style="color: #002200;">+</span> drawRect.origin.y;
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; numXPoints; i <span style="color: #002200;">+=</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                startPoint.x <span style="color: #002200;">+=</span> widthRatio;
                endPoint.x <span style="color: #002200;">+=</span> widthRatio;
                xPoints<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> startPoint;
                xPoints<span style="color: #002200;">&#91;</span>i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> endPoint;
            <span style="color: #002200;">&#125;</span>
            startPoint.x  <span style="color: #002200;">=</span> drawRect.origin.x;
            startPoint.y <span style="color: #002200;">=</span> drawRect.origin.y;
            endPoint.x <span style="color: #002200;">=</span> drawRect.size.width <span style="color: #002200;">+</span> drawRect.origin.x;
            endPoint.y <span style="color: #002200;">=</span> drawRect.origin.y;
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; numYPoints; i <span style="color: #002200;">+=</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                startPoint.y <span style="color: #002200;">+=</span> heightRatio;
                endPoint.y <span style="color: #002200;">+=</span> heightRatio;
                yPoints<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> startPoint;
                yPoints<span style="color: #002200;">&#91;</span>i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> endPoint;
            <span style="color: #002200;">&#125;</span>
            CGContextStrokeLineSegments<span style="color: #002200;">&#40;</span>context, xPoints, numXPoints<span style="color: #002200;">&#41;</span>;
            CGContextStrokeLineSegments<span style="color: #002200;">&#40;</span>context, yPoints, numYPoints<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></div></div><p>This method both resizes the image (currently stored as an NSBitmapImageRep) while maintaining the aspect ratio and draws the pixel grid when when it&#8217;s turned on. As you may be able to tell from the screenshot, the pixel grid is uneven, or at least appears to be. So my question is this, Mac developers: what would be a better way to draw the grid? As well, I currently access the image data by using NSBitmapImageReps&#8217; setColor:atX:y: and it seems to work fine, but is it the best way? I ask you so I can code and not worry that what I&#8217;m writing is stupidly wrong. I look forward to your input.</p><p>P.S. Does anyone know a good, free, code-friendly WordPress theme? Carrington is just too damn narrow.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2011/05/16/pixen-out-with-old-in-with-the-nu/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Secret Lion Feature Revealed!</title><link>http://jonshier.com/2010/11/19/secret-lion-feature-revealed/</link> <comments>http://jonshier.com/2010/11/19/secret-lion-feature-revealed/#comments</comments> <pubDate>Sat, 20 Nov 2010 04:41:21 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Cocoa]]></category> <category><![CDATA[Computing]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://jonshier.com/?p=42</guid> <description><![CDATA[For whatever reason, I&#8217;m subscribed to the WebKit project commit feed. So I can see whenever a new change in pushed into the project. Sometimes those commits reveal things. Like one from yesterday. Commit 72356 simply states &#8220;Enable compaction support.&#8221; &#8230; <a href="http://jonshier.com/2010/11/19/secret-lion-feature-revealed/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>For whatever reason, I&#8217;m subscribed to the WebKit project commit feed. So I can see whenever a new change in pushed into the project. Sometimes those commits reveal things. Like one from yesterday. Commit<a href="http://trac.webkit.org/changeset/72356" target="_blank"> 72356</a> simply states &#8220;Enable compaction support.&#8221; And it sets a single linker flag for the Mac parts of the project.</p><div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">OTHER_LDFLAGS_macosx_1070 = <span style="color: #660033;">-Xlinker</span> -objc_gc_compaction;</pre></div></div><p>Stunning, isn&#8217;t it? It may seem insignificant, but the addition of heap compaction to the Objective-C garbage collector is likely a prerequisite for its addition to the iOS SDK. You read about heap compaction in a great answer to this <a href="http://stackoverflow.com/questions/2663292/how-does-heap-compaction-work-quickly" target="_blank">StackOverflow question</a>. Why would it lead to garbage collection on iOS? Given that all iOS devices are vastly more memory constrained than their Mac OS X counterparts and lack on-disk virtual memory, anything can optimize memory use, especially for &#8220;free&#8221; from a developer&#8217;s perspective, is a big win. Reducing memory fragmentation, and more importantly, being able to reuse the same memory addresses during the common alloc/dealloc cycle that most objects go through will likely allow the Objective-C garbage collector to have the performance needed for Apple to enable it in iOS. As well, it&#8217;s continued evidence of Apple&#8217;s investment in Objective-C as the Mac OS X and iOS language of choice. It&#8217;s likely more details of this feature will be uncovered in the open source Objective-C runtime Apple produces, as well as the clang compiler project. A small but important feature we&#8217;ll see in Lion next year.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2010/11/19/secret-lion-feature-revealed/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Pixen: Where am I?</title><link>http://jonshier.com/2010/08/21/pixen-where-am-i/</link> <comments>http://jonshier.com/2010/08/21/pixen-where-am-i/#comments</comments> <pubDate>Sat, 21 Aug 2010 23:43:06 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Cocoa]]></category> <category><![CDATA[Pixen]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://jonshier.com/?p=39</guid> <description><![CDATA[Well, it has been almost a year since I posted about my adoption of Pixen. While I haven&#8217;t made the progress I had hoped in that time, there is some to report. My current GitHub repository builds on 10.6 only &#8230; <a href="http://jonshier.com/2010/08/21/pixen-where-am-i/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>Well, it has been almost a year since I posted about my adoption of Pixen. While I haven&#8217;t made the progress I had hoped in that time, there is some to report. My current <a href="http://github.com/jshier/Pixen" target="_blank">GitHub repository</a> builds on 10.6 only and only with the 32-bit Intel architecture. I&#8217;ve gotten the build down to 3 warnings with all of the options I&#8217;ve enabled but the clang static analyzer still finds over a hundred issues with the code. There are also several bugs still present that I&#8217;ve been trying to narrow down. And, unfortunately, several major parts of Pixen must be rewritten nearly from scratch to build against the 64-bit APIs. Overall, this has turned out to be a much more complicated project that I&#8217;d hoped. Pixen consists of over 25,000 lines of custom code, and that doesn&#8217;t count 3rd party libraries, of which there are several. There are an assortment of custom classes used throughout the program, including custom UI elements and even the basic image type is custom. Combine this with very little in the way of documentation or comments and my new job, and I just haven&#8217;t had the time (or expertise) to delve as far into the code as necessary. So I apologize to anyone hoping for some Pixen progress.</p><p>There is still hope however. Pixen: we can rebuild it, we have the technology. Over the coming weeks, time allowing, I&#8217;ll be adding a list of several major issues that need to be addressed for Pixen to move into 2010. These will be posted on my GitHub page, so feel free to comment with any suggestions. I always welcome additional insight into the Pixen code. Even if you don&#8217;t implement features or fix bugs, pointing me in the right direction so I can try to do so myself would be great. I&#8217;ll be focusing on any bugs that pop up (I already have at least one) and the transition to the 64-bit APIs. One of the biggest changes I&#8217;d like to see, even if I don&#8217;t do much with the foundation of the program, is a refreshed UI. I am not a designer by any stretch of the imagination, so if anyone is interested in submitting UI ideas or artwork, especially the UI icons, I would greatly appreciate it.</p><p>Thanks for reading.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2010/08/21/pixen-where-am-i/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>I&#8217;ve adopted a Pixen!</title><link>http://jonshier.com/2009/09/15/ive-adopted-a-pixen/</link> <comments>http://jonshier.com/2009/09/15/ive-adopted-a-pixen/#comments</comments> <pubDate>Wed, 16 Sep 2009 03:20:55 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Cocoa]]></category> <category><![CDATA[Pixen]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://jonshier.com/?p=31</guid> <description><![CDATA[Just over a week ago, Andy Matuschak, of Sparkle fame, asked for volunteers to adopt his Pixen project. It&#8217;s a pixel-based image editor for Mac OS X, and Andy just doesn&#8217;t have the time to maintain it or add features &#8230; <a href="http://jonshier.com/2009/09/15/ive-adopted-a-pixen/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>Just over a week ago, <a title="Andy Matsuchak" href="http://andymatuschak.org/" target="_blank">Andy Matuschak</a>, of <a title="Sparkle" href="http://sparkle.andymatuschak.org/" target="_blank">Sparkle</a> fame, asked for volunteers to <a title="adopt his Pixen project" href="http://blog.andymatuschak.org/post/179455697/adopt-a-pixen" target="_blank">adopt his Pixen project</a>. It&#8217;s a pixel-based image editor for Mac OS X, and Andy just doesn&#8217;t have the time to maintain it or add features for the upcoming 4.0 release. So I offered my services. I figured I may be more successful working on an already established project rather than creating my own from scratch. You can follow <a title="my progress at GitHub" href="http://github.com/jshier/Pixen/" target="_blank">my progress at GitHub</a> and some of my code has already been integrated into the <a title="main Pixen repository" href="http://github.com/philippec/Pixen" target="_blank">main Pixen repository</a> there.</p><p>So far my efforts have been limited to project cleanup, modernization, and house keeping. I expect this to be a great learning experience for me going forward and I&#8217;ll be posting code updates as I understand more of the Pixen code. Right now my priorities are fixing all of the warnings I created with new compiler options, updating the Obj-C syntax and Cocoa API&#8217;s used, and taking a look at the performance. Plus we&#8217;ll all be discussing exactly what new features to add for version 4.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2009/09/15/ive-adopted-a-pixen/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>BitMaster &#8211; Yet another Mac torrent client&#8230;</title><link>http://jonshier.com/2009/01/27/bitmaster-yet-another-mac-torrent-client/</link> <comments>http://jonshier.com/2009/01/27/bitmaster-yet-another-mac-torrent-client/#comments</comments> <pubDate>Tue, 27 Jan 2009 19:59:31 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[BitMaster]]></category> <category><![CDATA[Cocoa]]></category> <category><![CDATA[Computing]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://jonshier.com/?p=18</guid> <description><![CDATA[Over the last few years I&#8217;ve been teaching myself how to program. Little programs like ultrawar were my first complete programs, but I&#8217;ve read and learned a lot since then. I&#8217;ve been working on a BitTorrent client for the last &#8230; <a href="http://jonshier.com/2009/01/27/bitmaster-yet-another-mac-torrent-client/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>Over the last few years I&#8217;ve been teaching myself how to program. Little programs like ultrawar were my first complete programs, but I&#8217;ve read and learned a lot since then. I&#8217;ve been working on a BitTorrent client for the last few years, mostly as a learning exercise but also with the goal of a real client at the end. I know Mac OS X doesn&#8217;t really need another torrent client, since Transmission rules and even the mighty uTorrent has a Mac version now. But I wondered what a client that focused solely on Mac technologies would look like, whether it could be any better than those that strive to live across platforms. So I&#8217;ve created BitMaster. Eventually it will be open source from this site, but it&#8217;s still in a very prototype stage (I can only read and parse torrent files, hash downloads, and create torrent files), so I&#8217;ll be posting code excerpts for now. It&#8217;s my hope that having public eyes on the project will help me learn to code and to actually release something, rather than playing with it whenever I&#8217;m in the mood. So here&#8217;s my first bit of code for public scrutiny: my torrent file parsing code.</p><p>Obviously, when I first sat down to develop BitMaster I had to determine what functionality I needed first. I chose torrent file parsing, since it seemed like a simple and ubiquitous part of torrent client development. You can see my first attempt a this code in my previous entry &#8220;Learning through doing&#8230;&#8221; which is quite rough. After feedback from various people online, it now looks like this:</p><div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">//</span>
<span style="color: #11740a; font-style: italic;">//  JSbdecoder.m</span>
<span style="color: #11740a; font-style: italic;">//  BitMaster</span>
<span style="color: #11740a; font-style: italic;">//</span>
<span style="color: #11740a; font-style: italic;">//  Created by Jon Shier on 4/9/07.</span>
<span style="color: #11740a; font-style: italic;">//  Copyright 2007 __MyCompanyName__. All rights reserved.</span>
<span style="color: #11740a; font-style: italic;">//</span>
<span style="color: #6e371a;">#import &quot;JSbdecoder.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> JSbdecoder
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeTorrentFile<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> pathToTorrentFile <span style="color: #002200;">&#123;</span>
    torrentData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithContentsOfFile<span style="color: #002200;">:</span> pathToTorrentFile options<span style="color: #002200;">:</span> NSUncachedRead error<span style="color: #002200;">:</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    rawTorrentData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>torrentData bytes<span style="color: #002200;">&#93;</span>;
    position <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self convertObjectDataToStrings<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self bdecodeData<span style="color: #002200;">&#93;</span> objectAtIndex<span style="color: #002200;">:</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> bdecodeData <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>methodArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">do</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'i'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            position<span style="color: #002200;">++</span>;
            <span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self decodeInt<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'l'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            position<span style="color: #002200;">++</span>;
            <span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self decodeList<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'d'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            position<span style="color: #002200;">++</span>;
            <span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self decodeDictionary<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">isdigit</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self decodeBytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'e'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            position<span style="color: #002200;">++</span>;
            <span style="color: #11740a; font-style: italic;">//Should only hit this when at the end of lists, dictionaries, or integers.</span>
            <span style="color: #a61390;">break</span>;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error decoding torrent. Unexpected character '%c' at position %d.&quot;</span>, rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span>, position<span style="color: #002200;">&#41;</span>;
            <span style="color: #a61390;">return</span> methodArray;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span>position &lt; <span style="color: #002200;">&#91;</span>torrentData length<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> methodArray;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSNumber</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeInt <span style="color: #002200;">&#123;</span>
    NSUInteger methodPosition <span style="color: #002200;">=</span> position;
    <span style="color: #a61390;">while</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span> <span style="color: #002200;">!=</span> <span style="color: #bf1d1a;">'e'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
       position<span style="color: #002200;">++</span>;
    <span style="color: #002200;">&#125;</span>
    position<span style="color: #002200;">++</span>;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInteger<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>torrentData subdataWithRange<span style="color: #002200;">:</span> NSMakeRange<span style="color: #002200;">&#40;</span>methodPosition, <span style="color: #002200;">&#40;</span>position <span style="color: #002200;">-</span> methodPosition<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> integerValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeBytes <span style="color: #002200;">&#123;</span>
    NSUInteger methodPosition <span style="color: #002200;">=</span> position;
    <span style="color: #a61390;">while</span><span style="color: #002200;">&#40;</span>rawTorrentData<span style="color: #002200;">&#91;</span>position<span style="color: #002200;">&#93;</span> <span style="color: #002200;">!=</span> <span style="color: #bf1d1a;">':'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        position<span style="color: #002200;">++</span>;
    <span style="color: #002200;">&#125;</span>
    NSUInteger bytesLength <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>torrentData subdataWithRange<span style="color: #002200;">:</span> NSMakeRange<span style="color: #002200;">&#40;</span>methodPosition, <span style="color: #002200;">&#40;</span>position <span style="color: #002200;">-</span> methodPosition<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> integerValue<span style="color: #002200;">&#93;</span>;
    position<span style="color: #002200;">++</span>;
    methodPosition <span style="color: #002200;">=</span> position;
    position <span style="color: #002200;">+=</span> bytesLength;
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>torrentData subdataWithRange<span style="color: #002200;">:</span> NSMakeRange<span style="color: #002200;">&#40;</span>methodPosition, bytesLength<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeList <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span>self bdecodeData<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeDictionary <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>methodDictionary <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> dictionary<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>methodArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithArray<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self bdecodeData<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">for</span><span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; <span style="color: #002200;">&#91;</span>methodArray count<span style="color: #002200;">&#93;</span>; i <span style="color: #002200;">+=</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>methodDictionary setObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> methodDictionary;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> convertObjectDataToStrings<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> object <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>object conformsToProtocol<span style="color: #002200;">:</span> <span style="color: #a61390;">@protocol</span><span style="color: #002200;">&#40;</span><span style="color: #2a6f76;">NSFastEnumeration</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>valueArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>object isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> enumeratedObject <span style="color: #a61390;">in</span> object<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>valueArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self convertObjectDataToStrings<span style="color: #002200;">:</span> enumeratedObject<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
            <span style="color: #a61390;">return</span> valueArray;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>object isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            valueArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>object allValues<span style="color: #002200;">&#93;</span> mutableCopy<span style="color: #002200;">&#93;</span>;
            <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>keyArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> arrayWithArray<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>object allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; <span style="color: #002200;">&#91;</span>keyArray count<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>keyArray replaceObjectAtIndex<span style="color: #002200;">:</span> i withObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self convertObjectDataToStrings<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>keyArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
            <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>NSUInteger i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i &lt; <span style="color: #002200;">&#91;</span>valueArray count<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>keyArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pieces&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
                    <span style="color: #002200;">&#91;</span>valueArray replaceObjectAtIndex<span style="color: #002200;">:</span> i withObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self convertObjectDataToStrings<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#125;</span>
            <span style="color: #002200;">&#125;</span>
            <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjects<span style="color: #002200;">:</span> valueArray forKeys<span style="color: #002200;">:</span> keyArray<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>object isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> object;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>object isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> alloc<span style="color: #002200;">&#93;</span> initWithBytes<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>object bytes<span style="color: #002200;">&#93;</span> length<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>object length<span style="color: #002200;">&#93;</span> encoding<span style="color: #002200;">:</span> NSUTF8StringEncoding<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unexpected object %@ of class %@&quot;</span>, object, <span style="color: #002200;">&#91;</span>object class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> object;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div><p>This code is much faster, cleaner, and accurate than the previous attempt. But it&#8217;s still inelegant in a lot of ways. For example, I store the torrent file data within both an NSData object (for the subdata* methods) and a char array (so I can access individual characters to iterate over). Surely there must be a better way, I just haven&#8217;t found it. For a few of my methods, there must be a better way of converting to an NSNumber object than getting a subdata, making it a string, and making the string a number. Seems quite obtuse compared to the conversions I&#8217;ve seen in other languages.</p><p>Well, that&#8217;s all for now. I&#8217;ll try to get this post out and around so I can get feed back, so feel free to leave comments.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2009/01/27/bitmaster-yet-another-mac-torrent-client/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Now on DreamHost</title><link>http://jonshier.com/2009/01/23/hello-world/</link> <comments>http://jonshier.com/2009/01/23/hello-world/#comments</comments> <pubDate>Fri, 23 Jan 2009 16:15:29 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Jon's Life]]></category><guid isPermaLink="false">http://www.jonshier.com/?p=1</guid> <description><![CDATA[I&#8217;ve switched from my own server to using DreamHost, which is faster and has better features. More to come later.]]></description> <content:encoded><![CDATA[<p>I&#8217;ve switched from my own server to using DreamHost, which is faster and has better features. More to come later.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2009/01/23/hello-world/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Even stiller alive&#8230;</title><link>http://jonshier.com/2008/12/31/even-stiller-alive/</link> <comments>http://jonshier.com/2008/12/31/even-stiller-alive/#comments</comments> <pubDate>Wed, 31 Dec 2008 23:40:58 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Jon's Life]]></category><guid isPermaLink="false">http://www.jonshier.com/?p=12</guid> <description><![CDATA[I&#8217;m finally free. Once AT&#38;T installs my Uverse service (mmm, fiber) Jan. 6, I&#8217;ll be able to start posting. And hopefully customizing this site. I have a lot to catch up on.]]></description> <content:encoded><![CDATA[<p>I&#8217;m finally free. Once AT&amp;T installs my Uverse service (mmm, fiber) Jan. 6, I&#8217;ll be able to start posting. And hopefully customizing this site. I have a lot to catch up on.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2008/12/31/even-stiller-alive/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>I&#8217;m still alive&#8230;</title><link>http://jonshier.com/2007/11/12/im-still-alive/</link> <comments>http://jonshier.com/2007/11/12/im-still-alive/#comments</comments> <pubDate>Mon, 12 Nov 2007 20:51:03 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Computing]]></category> <category><![CDATA[Jon's Life]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://www.jonshier.com/?p=9</guid> <description><![CDATA[Yes, I&#8217;m still alive and kicking, just off the grid for a while. I was able to implement my previous Objective-C code using the new Obj-C2 @property syntax and a better algorithm, so it is much shorter and works better. &#8230; <a href="http://jonshier.com/2007/11/12/im-still-alive/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>Yes, I&#8217;m still alive and kicking, just off the grid for a while. I was able to implement my previous Objective-C code using the new Obj-C2 @property syntax and a better algorithm, so it is much shorter and works better. However, I still seem to have trouble converting all of the strings I need to from NSData to NSString objects. I don&#8217;t have access to my Quad right now, so I haven&#8217;t been able to work on it in a while, but that&#8217;s the last thing I need to fix before torrent file parsing should work.</p><p>In other news, I&#8217;ve been reading a lot about computer architecture and design, as well as Unix programming on Mac OS X. Once I get my Quad back and upgraded to Leopard, I should be able to start experimenting.</p><p>I&#8217;ve also updated my wish list, so family members seeking gift ideas should check it out.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2007/11/12/im-still-alive/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Learning Through Doing</title><link>http://jonshier.com/2007/04/05/learning-through-doing/</link> <comments>http://jonshier.com/2007/04/05/learning-through-doing/#comments</comments> <pubDate>Fri, 06 Apr 2007 00:22:40 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Computing]]></category> <category><![CDATA[Programming]]></category><guid isPermaLink="false">http://www.jonshier.com/?p=8</guid> <description><![CDATA[In an effort to teach myself Objective-C and the Cocoa framework, I&#8217;ve decided to create a Cocoa BitTorrent client. So far I&#8217;m able to parse torrent files (most of the time), hash the file to be downloaded (if it&#8217;s already &#8230; <a href="http://jonshier.com/2007/04/05/learning-through-doing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>In an effort to teach myself Objective-C and the Cocoa framework, I&#8217;ve decided to create a Cocoa BitTorrent client. So far I&#8217;m able to parse torrent files (most of the time), hash the file to be downloaded (if it&#8217;s already downloaded) and the info dictionary string (big hack), and both scrape and get torrent specific data from trackers. Once this program can actually download a file from a torrent I&#8217;ll release the source code under an open source license (likely the Apache license). In the meantime, I&#8217;m going to be using whatever resources I can find. That includes IRC channels frequented by various Mac projects (#webkit, #transmission, etc) on irc.freenode.net (which may be how you got here). From time to time I&#8217;m going to post some of my code on this blog so I can get feedback from various parties on fixing bugs or implementing features. That&#8217;s what this post in about.</p><p>Currently, I can parse .torrent files pretty successfully. By turning them into NSDictionary&#8217;s I can access their contents very easily. However, I&#8217;m not 100% successful yet. Strangely, some torrents, like <a href="http://www.bt-chat.com/download.php?info_hash=5d649e2225930dfd4eac54e7410e462e63fbb3ae">this one</a>, don&#8217;t parse successfully, breaking my later code. It seems as if the contents of the comment and name keys in the file aren&#8217;t decoding correctly as UTF8 strings, so the data put into those keys is incorrect. I can&#8217;t figure out why that is. I suspect it has something to do with the findBlockRangeAtIndex: method. Here&#8217;s the code:</p><div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">//</span>
<span style="color: #11740a; font-style: italic;">//  JSbcoder.m</span>
<span style="color: #11740a; font-style: italic;">//</span>
<span style="color: #11740a; font-style: italic;">//  Created by Jon Shier on 3/4/05.</span>
<span style="color: #11740a; font-style: italic;">//&lt;/code&gt;</span>
&nbsp;
&lt;code&gt;<span style="color: #6e371a;">#import &quot;JSbcoder.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> JSbcoder
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeTorrentFileData<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData <span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">//Need error checking. Check that the data starts with d.</span>
&nbsp;
<span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span>torrentFileBytes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>torrentData bytes<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>self setDataLength<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>torrentData length<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithDictionary<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self decodeDictionaryFromBytes<span style="color: #002200;">:</span> torrentFileBytes withRange<span style="color: #002200;">:</span> NSMakeRange<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1</span>, dataLength <span style="color: #002200;">-</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> convertDictionaryDataToStrings<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentDictionary <span style="color: #002200;">&#123;</span>
<span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>keyArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> arrayWithArray<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>torrentDictionary allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>valueArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> arrayWithArray<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>torrentDictionary allValues<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>keyArray count<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>keyArray replaceObjectAtIndex<span style="color: #002200;">:</span> i withObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>keyArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>valueArray count<span style="color: #002200;">&#93;</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&amp;</span>amp; <span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>keyArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> isEqualToString<span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pieces&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>IsEmpty<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;A value is nil, value array is: %@ nil value at index %i which is %@ string of which is %@<span style="color: #2400d9;">\n</span>&quot;</span>, valueArray, i, <span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#91;</span>valueArray replaceObjectAtIndex<span style="color: #002200;">:</span> i withObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>valueArray replaceObjectAtIndex<span style="color: #002200;">:</span> i withObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self convertDictionaryDataToStrings<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>valueArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjects<span style="color: #002200;">:</span> valueArray forKeys<span style="color: #002200;">:</span> keyArray<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSNumber</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeIntegerFromBytes<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData withRange<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRange</span><span style="color: #002200;">&#41;</span> range <span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> alloc<span style="color: #002200;">&#93;</span> initWithBytes<span style="color: #002200;">:</span>torrentData <span style="color: #002200;">+</span> range.location length<span style="color: #002200;">:</span>range.length encoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span> intValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeStringAndReturnDataFromBytes<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData withRange<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRange</span><span style="color: #002200;">&#41;</span> range <span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithBytes<span style="color: #002200;">:</span> torrentData length<span style="color: #002200;">:</span> dataLength<span style="color: #002200;">&#93;</span> subdataWithRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> findBlockRangeAtIndex<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> index inBytes<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">int</span> j <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
<span style="color: #a61390;">int</span> blockLength <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">//Need error checking</span>
&nbsp;
<span style="color: #a61390;">while</span> <span style="color: #002200;">&#40;</span>index <span style="color: #002200;">+</span> blockLength <span style="color: #002200;">&amp;</span>lt; dataLength<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
blockLength<span style="color: #002200;">++</span>;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'i'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>j <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>; j <span style="color: #002200;">&amp;</span>lt; dataLength; j<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>index <span style="color: #002200;">+</span> j <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'e'</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">break</span>;
<span style="color: #002200;">&#125;</span>
blockLength <span style="color: #002200;">+=</span> j;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">isdigit</span><span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">NSRange</span> range;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>j <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; j <span style="color: #002200;">&amp;</span>lt; dataLength; j<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">isdigit</span><span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>j <span style="color: #002200;">+</span> index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&amp;</span>amp; torrentData<span style="color: #002200;">&#91;</span>j <span style="color: #002200;">+</span> index <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span> <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">':'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
range.location <span style="color: #002200;">=</span> index <span style="color: #002200;">+</span> blockLength;
range.length <span style="color: #002200;">=</span> j <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
<span style="color: #a61390;">break</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
blockLength <span style="color: #002200;">+=</span> j <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
j <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> alloc<span style="color: #002200;">&#93;</span> initWithBytes<span style="color: #002200;">:</span>torrentData <span style="color: #002200;">+</span> range.location length<span style="color: #002200;">:</span>range.length encoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span> intValue<span style="color: #002200;">&#93;</span>;
blockLength <span style="color: #002200;">+=</span> j;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'l'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
blockLength <span style="color: #002200;">+=</span> <span style="color: #002200;">&#91;</span>self findBlockRangeAtIndex<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#41;</span> inBytes<span style="color: #002200;">:</span> torrentData<span style="color: #002200;">&#93;</span> <span style="color: #002200;">-</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'d'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
blockLength <span style="color: #002200;">+=</span> <span style="color: #002200;">&#91;</span>self findBlockRangeAtIndex<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#41;</span> inBytes<span style="color: #002200;">:</span> torrentData<span style="color: #002200;">&#93;</span> <span style="color: #002200;">-</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>index <span style="color: #002200;">+</span> blockLength<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'e'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">break</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">return</span> blockLength <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeListFromBytes<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData withRange<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRange</span><span style="color: #002200;">&#41;</span> range <span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">//Insert error checking</span>
&nbsp;
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithArray<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self createArrayFromData<span style="color: #002200;">:</span> torrentData withRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> decodeDictionaryFromBytes<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData withRange<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRange</span><span style="color: #002200;">&#41;</span> range <span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">//Need error checking</span>
&nbsp;
<span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>methodArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithArray<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self createArrayFromData<span style="color: #002200;">:</span> torrentData withRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>keyArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
<span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>valueArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
<span style="color: #a61390;">for</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>methodArray count<span style="color: #002200;">&#93;</span>; i <span style="color: #002200;">+=</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>IsEmpty<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>keyArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#91;</span>keyArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>keyArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">for</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>; i <span style="color: #002200;">&amp;</span>lt; <span style="color: #002200;">&#91;</span>methodArray count<span style="color: #002200;">&#93;</span>; i <span style="color: #002200;">+=</span> <span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> isKindOfClass<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> class<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>IsEmpty<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>valueArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#91;</span>valueArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithUTF8String<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span> bytes<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
<span style="color: #002200;">&#91;</span>valueArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>methodArray objectAtIndex<span style="color: #002200;">:</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjects<span style="color: #002200;">:</span> valueArray forKeys<span style="color: #002200;">:</span> keyArray<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> setDataLength<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> torrentFileDataLength <span style="color: #002200;">&#123;</span>
dataLength <span style="color: #002200;">=</span> torrentFileDataLength;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> createArrayFromData<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span> torrentData withRange<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRange</span><span style="color: #002200;">&#41;</span> range <span style="color: #002200;">&#123;</span>
<span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>methodArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> array<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span> j <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
<span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span> k <span style="color: #002200;">=</span> range.length <span style="color: #002200;">+</span> range.location;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i <span style="color: #002200;">=</span> range.location; i <span style="color: #002200;">&amp;</span>lt;<span style="color: #002200;">=</span> k; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'i'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>j <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>; j <span style="color: #002200;">&amp;</span>lt; dataLength; j<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>i <span style="color: #002200;">+</span> j<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'e'</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">break</span>;
<span style="color: #002200;">&#125;</span>
range.location <span style="color: #002200;">=</span> i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
range.length <span style="color: #002200;">=</span> j <span style="color: #002200;">-</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self decodeIntegerFromBytes<span style="color: #002200;">:</span> torrentData withRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
i <span style="color: #002200;">+=</span> j;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">isdigit</span><span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>j <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; j <span style="color: #002200;">&amp;</span>lt; dataLength; j<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">isdigit</span><span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>j <span style="color: #002200;">+</span> i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&amp;</span>amp;<span style="color: #002200;">&amp;</span>amp; torrentData<span style="color: #002200;">&#91;</span>j <span style="color: #002200;">+</span> i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">':'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
range.location <span style="color: #002200;">=</span> i;
range.length <span style="color: #002200;">=</span> j <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
<span style="color: #a61390;">break</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
i <span style="color: #002200;">+=</span> range.length;
j <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> alloc<span style="color: #002200;">&#93;</span> initWithBytes<span style="color: #002200;">:</span>torrentData <span style="color: #002200;">+</span> range.location length<span style="color: #002200;">:</span>range.length encoding<span style="color: #002200;">:</span>NSUTF8StringEncoding<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span> intValue<span style="color: #002200;">&#93;</span>;
range.location <span style="color: #002200;">+=</span> range.length <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
range.length <span style="color: #002200;">=</span> j;
<span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self decodeStringAndReturnDataFromBytes<span style="color: #002200;">:</span> torrentData withRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
i <span style="color: #002200;">+=</span> range.length;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'l'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
range.location <span style="color: #002200;">=</span> i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
range.length <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self findBlockRangeAtIndex<span style="color: #002200;">:</span> i inBytes<span style="color: #002200;">:</span> torrentData<span style="color: #002200;">&#93;</span> <span style="color: #002200;">-</span> <span style="color: #2400d9;">2</span>;
<span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self decodeListFromBytes<span style="color: #002200;">:</span> torrentData withRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
i <span style="color: #002200;">+=</span> range.length <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>torrentData<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> <span style="color: #bf1d1a;">'d'</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
range.location <span style="color: #002200;">=</span> i <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
range.length <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self findBlockRangeAtIndex<span style="color: #002200;">:</span> i inBytes<span style="color: #002200;">:</span> torrentData<span style="color: #002200;">&#93;</span> <span style="color: #002200;">-</span> <span style="color: #2400d9;">2</span>;
<span style="color: #002200;">&#91;</span>methodArray addObject<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span>self decodeDictionaryFromBytes<span style="color: #002200;">:</span> torrentData withRange<span style="color: #002200;">:</span> range<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
i <span style="color: #002200;">+=</span> range.length <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">return</span> methodArray;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div><p>I know it&#8217;s rough and fragile, but anything you can suggest will help. If you want more info on the BitTorrent specification <a href="http://wiki.theory.org/BitTorrentSpecification">this</a> is the best resource I could find.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2007/04/05/learning-through-doing/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>I&#8217;m back&#8230;</title><link>http://jonshier.com/2006/08/01/im-back/</link> <comments>http://jonshier.com/2006/08/01/im-back/#comments</comments> <pubDate>Wed, 02 Aug 2006 00:38:44 +0000</pubDate> <dc:creator>Jon</dc:creator> <category><![CDATA[Jon's Life]]></category><guid isPermaLink="false">http://www.jonshier.com/?p=4</guid> <description><![CDATA[After months of downtime due to dual hard drive failure in the server, I&#8217;m back online. Much new content will be forthcoming, including Leopard rumors and news.]]></description> <content:encoded><![CDATA[<p>After months of downtime due to dual hard drive failure in the server, I&#8217;m back online. Much new content will be forthcoming, including Leopard rumors and news.</p> ]]></content:encoded> <wfw:commentRss>http://jonshier.com/2006/08/01/im-back/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
<!-- Served from: jonshier.com @ 2012-05-19 17:14:18 by W3 Total Cache -->
