<?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>Ramblings of a Geek - Jeremy Johnstone &#187; github</title>
	<atom:link href="http://www.jeremyjohnstone.com/tag/github/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jeremyjohnstone.com</link>
	<description>Ramblings of a Geek</description>
	<lastBuildDate>Wed, 28 Jul 2010 18:33:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP parser for OS X plist XML files</title>
		<link>http://www.jeremyjohnstone.com/blog/2008-10-26-php-parser-for-os-x-plist-xml-files.html</link>
		<comments>http://www.jeremyjohnstone.com/blog/2008-10-26-php-parser-for-os-x-plist-xml-files.html#comments</comments>
		<pubDate>Mon, 27 Oct 2008 03:42:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[iTunes]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php_class_lib]]></category>
		<category><![CDATA[plist]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.jeremyjohnstone.com/blog/?p=384</guid>
		<description><![CDATA[Digging around today for a PHP parser for OSX plist files, I was surprised to find no good pre-existing solutions. Even Apple&#8217;s own site gives a relatively poor solution to the problem (see here). Normally SimpleXML is enough to handle most XML parsing needs, but the plist XML format is just broken enough to make [...]]]></description>
			<content:encoded><![CDATA[<p>Digging around today for a PHP parser for OSX plist files, I was surprised to find no good pre-existing solutions. Even Apple&#8217;s own site gives a relatively poor solution to the problem (<a href="http://developer.apple.com/internet/opensource/php.html">see here</a>). Normally SimpleXML is enough to handle most XML parsing needs, but the plist XML format is just broken enough to make parsing it with SimpleXML virtually impossible. Since I hadn&#8217;t played with XMLReader much, I thought it would be a good chance to give it a spin. For the anxious types, the code is available on <a href="http://github.com/jsjohnst/php_class_lib/tree/master">github in my php_class_lib project</a>, so dig right in. Read on for a simple example (included in the repos).</p>
<p>The original intent of the parser for me was to parse my iTunes&#8217; library in PHP, so <a href="http://github.com/jsjohnst/php_class_lib/tree/master/classes/parsers/plist/example.php">this example</a> will show doing just that:</p>
<pre class="brush: php">&lt;?php

include("PlistParser.inc");

$parser = new plistParser();
$plist = $parser-&gt;parse(dirname(__FILE__) . "/iTunes.xml");
var_dump($plist);
</pre>
<p>And from that, the output is as follows:</p>
<pre class="brush: php">array(8) {
  ["Major Version"]=&gt;
  int(1)
  ["Minor Version"]=&gt;
  int(1)
  ["Application Version"]=&gt;
  string(5) "8.0.1"
  ["Features"]=&gt;
  int(5)
  ["Show Content Ratings"]=&gt;
  bool(true)
  ["Music Folder"]=&gt;
  string(60) "file://localhost/Users/testUser/Music/iTunes/iTunes%20Music/"
  ["Library Persistent ID"]=&gt;
  string(15) "C39203948AF3D3E"
  ["Tracks"]=&gt;
  array(1) {
    [1]=&gt;
    array(25) {
      ["Track ID"]=&gt;
      int(1)
      ["Name"]=&gt;
      string(8) "My Track"
      ["Artist"]=&gt;
      string(9) "My Artist"
      ["Album"]=&gt;
      string(8) "My Album"
      ["Genre"]=&gt;
      string(8) "My Genre"
      ["Kind"]=&gt;
      string(15) "MPEG audio file"
      ["Size"]=&gt;
      int(123456)
      ["Total Time"]=&gt;
      int(123456)
      ["Track Number"]=&gt;
      int(1)
      ["Year"]=&gt;
      int(2008)
      ["Date Modified"]=&gt;
      string(20) "2008-03-03T03:33:33Z"
      ["Date Added"]=&gt;
      string(20) "2008-03-03T03:33:33Z"
      ["Bit Rate"]=&gt;
      int(128)
      ["Sample Rate"]=&gt;
      int(44100)
      ["Comments"]=&gt;
      string(20) "All Rights Reserved."
      ["Release Date"]=&gt;
      string(20) "2007-03-12T04:01:37Z"
      ["Persistent ID"]=&gt;
      string(14) "C3E339393939E3"
      ["Track Type"]=&gt;
      string(4) "File"
      ["Podcast"]=&gt;
      bool(false)
      ["Unplayed"]=&gt;
      bool(true)
      ["File Type"]=&gt;
      int(123456)
      ["File Creator"]=&gt;
      int(123456)
      ["Location"]=&gt;
      string(66) "file://localhost/Users/testUser/Music/iTunes/iTunes%20Music/my.mp3"
      ["File Folder Count"]=&gt;
      int(4)
      ["Library Folder Count"]=&gt;
      int(1)
    }
  }
}</pre>
<p>As you can see, the PHP parser made short order of that task. From here you now have full access to all the metadata in your iTunes library. Feel free to use the class in your own projects and be sure to let me know what you build with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremyjohnstone.com/blog/2008-10-26-php-parser-for-os-x-plist-xml-files.html/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Enums in PHP</title>
		<link>http://www.jeremyjohnstone.com/blog/2008-10-05-enums-in-php.html</link>
		<comments>http://www.jeremyjohnstone.com/blog/2008-10-05-enums-in-php.html#comments</comments>
		<pubDate>Sun, 05 Oct 2008 12:11:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPClassLib]]></category>
		<category><![CDATA[userland]]></category>

		<guid isPermaLink="false">http://www.jeremyjohnstone.com/blog/?p=383</guid>
		<description><![CDATA[I&#8217;m not sure what lead me to it, but I stumbled across a blog post on how to implement Enums in PHP via userland code written by Jonathan Hohle. I liked the concept he had, but the implementation was a bit unappealing because it used eval() among other more minor issues. You shouldn&#8217;t need to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not sure what lead me to it, but I stumbled across a blog post on <a href="http://it.toolbox.com/blogs/macsploitation/enums-in-php-a-native-implementation-25228">how to implement Enums in PHP via userland code</a> written by Jonathan Hohle. I liked the concept he had, but the implementation was a bit unappealing because it used eval() among other more minor issues. You shouldn&#8217;t need to generate Enums at runtime, so I took that as a challenge to find a way to do it at compile time, thus making the code much more efficient. Like Jonathan, I also wanted to maintain support for PHP&#8217;s type hinting and it should obviously support the semantics one expects from an enum if feasible. I wasn&#8217;t sure of the real value to having the Enums iterable as well like he did, but I figured if possible I should keep support for that too.</p>
<p>First off, we need the Enum base class as follows:</p>
<pre class="brush: php">
abstract class Enum {
	final public function __toString() {
		return get_class($this);
	}
}
</pre>
<p>From that miniscule amount of code we have the beginnings of Enum support simply by extending that class as follows:</p>
<pre class="brush: php">
abstract class DNSRecordType extends Enum {}

class A extends DNSRecordType {}
class CNAME extends DNSRecordType {}
class MX extends DNSRecordType {}

function printDnsRecord(DNSRecordType $type, ...) {
       // We can now be sure $type is a DNSRecordType
}
</pre>
<p>There are of course a few issues, one of the biggest being that <code>(new A) !== (new A)</code> in the above example code. Here we modify the Enum base class to add support for fixing the equality comparison:</p>
<pre class="brush: php">
abstract class Enum {
	protected static $instances = array();

	final private function __construct() {}

	final public function __toString() {
		return get_class($this);
	}

	final public static function get($name) {
		if(is_subclass_of($name, "Enum")) {
			if(array_key_exists($name, self::$instances)) {
				return self::$instances[$name];
			} else {
				return self::$instances[$name] = new $name();
			}
		} else {
			throw Exception();
		}
	}

	final public static function __callStatic($name, $args) {
		return self::get($name);
	}
}
</pre>
<p>Now if we want to use an enum, instead of instantiating the CNAME class directly, we use <code>DNSRecordType::get("CNAME");</code> on versions of PHP older than 5.3 and in PHP 5.3 we can save a few keystrokes and instead use <code>DNSRecordType::CNAME()</code> to get a CNAME. Obviously in the case of older versions of PHP we are adding a few extra keystrokes, but unfortunately that is required to avoid having to define custom methods for each Enum type due to the lack of the __callStatic() magic method before PHP 5.3.</p>
<p>Ok, so what&#8217;s next? Well, I guess our next issue would be that Enums, in the case of languages based on C style semantics, by default don&#8217;t have the value of a member as the the name of the member, but rather an integer which increments from zero for each member. Furthermore, in C style enums you can set the value too if you like to any integer of your choice and then each member after that which doesn&#8217;t have a specified value will be incremented one higher from it consecutively. To support this style behavior, it forces us partly out of being able to do this at compile time (thus a performance hit). Because of the performance hit, I decided you have to enable this mode before using it, otherwise you get the previous behavior we defined above.</p>
<p>The now updated code is as follows:</p>
<pre class="brush: php">
abstract class Enum {
	protected static $instances = array();
	protected $value = null;

	protected static $pureMode = false;
	protected static $classesWalked = false;
	protected static $typeCounters = array();
	protected static $classIntValues = array();

	final private function __construct() {}

	final public static function enablePureMode() {
		self::$pureMode = true;
	}

	final protected static function walkClasses() {
		if(self::$pureMode &#038;&#038; !self::$classesWalked) {
			foreach(get_declared_classes() as $class) {
				if(is_subclass_of($class, "Enum") &#038;&#038; $class !== "Enum") {
					$parent = get_parent_class($class);
					if($parent == "Enum") continue;
					if(!array_key_exists($parent, self::$typeCounters)) {
						self::$typeCounters[$parent] = 0;
					}
					$obj = new $class;
					$objval = $obj->value;
					if(!is_null($objval)) {
						if(!is_numeric($objval)) {
							$nextval = ord($objval) + 1;
						} else {
							$nextval = $objval + 1;
						}
						if($nextval <= self::$typeCounters[$parent]) {
							throw new Exception("Specified enum member value is impossible");
						}
						self::$classIntValues[$class] = $objval;
						self::$typeCounters[$parent] = $nextval;
					} else {
						self::$classIntValues[$class] = self::$typeCounters[$parent]++;
					}
				}
			}
			self::$classesWalked = true;
		}
	}

	final public function __toString() {
		if(self::$pureMode) {
			// delay the performance hit until we actually need the value of one of the enums
			self::walkClasses();
			return (string) self::$classIntValues[get_class($this)];
		} else {
			return get_class($this);
		}
	}

	final public static function get($name) {
		if(is_subclass_of($name, "Enum")) {
			if(array_key_exists($name, self::$instances)) {
				return self::$instances[$name];
			} else {
				return self::$instances[$name] = new $name();
			}
		} else {
			throw new Exception();
		}
	}

	final public static function __callStatic($name, $args) {
		return self::get($name);
	}
}
</pre>
<p>With the above change, we can now have an enums for months with January's value being 1 for example, like the following:</p>
<pre class="brush: php">
Enum::enablePureMode();
abstract class Month extends Enum {}
class JAN extends Month { var $value = 1; }
class FEB extends Month {}
class MAR extends Month {}
... etc
</pre>
<p>We can also do things like the following too:</p>
<pre class="brush: php">
Enum::enablePureMode();
abstract class Whitespace extends Enum {}
class Newline extends Whitespace { var $value = "\n"; }
class Space extends Whitespace { var $value = " "; }
class Tab extends Whitespace { var $value = "\t"; }
... etc
</pre>
<p>Pretty nifty eh? Please do note, once you enablePureMode it's enabled for all instances of any Enum because you have already incurred the performance loss. Also, due to the nature of how enablePureMode works, you need to make sure you always have all your Enums defined before you try to use one of their values. This shouldn't be an issue in most cases, but just something to keep in mind. Doing quick tests showed the performance hit from having enablePureMode turned on was pretty trivial (less than a millisecond in some cases), but since you might not need the behavior, no point in taking the performance hit if you don't need to.</p>
<p>The last thing left is to make an iterator of all the members of an Enum. This part is really quick and easy and requires us to add the following method to our Enum class:</p>
<pre class="brush: php">
final public static function iterator($enum_type) {
	return new EnumIterator($enum_type);
}
</pre>
<p>As well as also define the following additional class:</p>
<pre class="brush: php">
class EnumIterator implements Iterator {
	protected $classes = array();
	protected $enum_type;

	public function __construct($enum_type) {
		if(!class_exists($enum_type) || !is_subclass_of($enum_type, "Enum")) throw new Exception("Specified Enum type doesn't exist or is not an Enum!");
		$this->enum_type = $enum_type;
		foreach(get_declared_classes() as $class) {
			if(is_subclass_of($class, $this->enum_type)) {
				$this->classes[] = $class;
			}
		}
	}

	public function current() {
		return current($this->classes);
	}

	public function key() {
		return key($this->classes);
	}

	public function next() {
		next($this->classes);
		return $this->current();
	}

	public function rewind() {
		return reset($this->classes);
	}

	public function valid() {
		return (bool) $this->current();
	}
}
</pre>
<p>An example of using the iterator is as follows:</p>
<pre class="brush: php">
echo "DNSRecordType:\n";
foreach(Enum::iterator("DNSRecordType") as $type) {
	echo "\t" . $type . " has value " . (Enum::get($type)) . "\n";
}
</pre>
<p>To get a copy of the code including several example usage demonstrations, please visit the following URL: <a href="http://github.com/jsjohnst/php_class_lib/tree/master/classes/types/enum">http://github.com/jsjohnst/php_class_lib/tree/master/classes/types/enum</a></p>
<p>If you find this useful, please let me know!</p>
<p>-Jeremy</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeremyjohnstone.com/blog/2008-10-05-enums-in-php.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
