<?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>tdistler.com &#187; Code Monkey</title>
	<atom:link href="http://tdistler.com/category/code-monkey/feed" rel="self" type="application/rss+xml" />
	<link>http://tdistler.com</link>
	<description>&#34;To err is human, but to really foul things up you need a computer.”</description>
	<lastBuildDate>Wed, 16 May 2012 03:00:31 +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>Linux: How to Detect Dropped Network Packets</title>
		<link>http://tdistler.com/2012/05/15/linux-detecting-dropped-network-packets</link>
		<comments>http://tdistler.com/2012/05/15/linux-detecting-dropped-network-packets#comments</comments>
		<pubDate>Wed, 16 May 2012 03:00:31 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1174</guid>
		<description><![CDATA[There are a few ways on linux to see if the network stack is dropping packets, or just having problems in general: 1. ifconfig ... RX packets:522 errors:0 dropped:0 overruns:0 frame:0 TX packets:406 errors:0 dropped:0 overruns:0 frame:0 ... 2. cat /proc/net/dev Inter-&#124; Receive ... face &#124; bytes packets errs drop fifo frame ... eth0: 87689 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2012/05/netcable.jpg"><img class="alignright size-full wp-image-1188" title="netcable" src="http://tdistler.com/wp-content/uploads/2012/05/netcable.jpg" alt="" width="134" height="76" /></a>There are a few ways on linux to see if the network stack is dropping packets, or just having problems in general:</p>
<p>1. <strong><code>ifconfig</code></strong></p>
<blockquote>
<pre><code> ...
 RX packets:522 errors:0 dropped:0 overruns:0 frame:0
 TX packets:406 errors:0 dropped:0 overruns:0 frame:0
 ...</code></pre>
</blockquote>
<p>2. <strong><code>cat /proc/net/dev</code></strong></p>
<blockquote>
<pre><code>Inter-| Receive ...
 face | bytes packets errs drop fifo frame ...
 eth0:  87689 785 0 0 0 0 ...
 ...</code></pre>
</blockquote>
<p>3. <strong><code>cat /proc/net/udp</code></strong></p>
<blockquote>
<pre><code> so local_address rem_address ... drops
 277: 00000000:0044 00000000:0000 ... 0
 ...</code></pre>
</blockquote>
<p>4. <strong><code>cat /proc/net/snmp</code></strong></p>
<blockquote>
<pre><code>...
Tcp: ...
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 453 0 0 452 0 0
...</code></pre>
</blockquote>
<p>You can also see this on a per-process basis using <code>cat /proc/&lt;pid&gt;/net/{udp,dev,snmp}</code></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2012/05/15/linux-detecting-dropped-network-packets/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ebonicode++: Hackin C++ Gangsta Style</title>
		<link>http://tdistler.com/2011/12/03/eubonicode-hackin-c-gangsta-style</link>
		<comments>http://tdistler.com/2011/12/03/eubonicode-hackin-c-gangsta-style#comments</comments>
		<pubDate>Sat, 03 Dec 2011 16:00:02 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[funny]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1077</guid>
		<description><![CDATA["Foshizzle" is a modified version of the Clang compiler which supports Eubonicode++ (an alternate C++ syntax). Foshizzle supports all the existing features of Clang, but with extensions to more fully express your gansta style. All the regular C++ syntax still works, but you can now substitute Eubonicode++ keywords and operators.]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/12/Bjarne_foshizzle.jpg"><img class="alignright size-thumbnail wp-image-1078" title="A small part of me died doing this to Bjarne, but I couldn't resist." src="http://tdistler.com/wp-content/uploads/2011/12/Bjarne_foshizzle-150x150.jpg" alt="A little part of me died doing this to Bjarne, but I couldn't resist." width="150" height="150" /></a></p>
<p>&#8220;Foshizzle&#8221; is a modified version of the <a title="Clang Compiler" href="http://clang.llvm.org/" target="_blank">Clang</a> compiler which supports Ebonicode++ (an alternate C++ syntax). Foshizzle supports all the existing features of Clang, but with extensions to more fully express your gansta style. All the regular C++ syntax still works, but you can now substitute Ebonicode++ keywords and operators (see below).</p>
<p>Here&#8217;s a sample method that calculates factorials (Note: the semicolons can be replaced with a certain expletive):</p>
<pre>int factorialz(int n)
{
    int rezult be 1;
    slongas (n bepimpin 0)
    {
        rezult be rezult dimes n;
        dissin n;
    }
    putou rezult;
}</pre>
<p>&nbsp;</p>
<p>I can&#8217;t take all the credit. I was inspired by the Iowa State students that first created Ebonicode (webpage no longer available).</p>
<p>Here are my Clang modifications:<a title="Eubonicode++ Clang modifications" href="http://tdistler.com/media/code/eubonicode/ebpp-clang30rc4.patch" target="_blank"> ebpp-clang30rc4.patch</a></p>
<p>Build instructions are near the end of this post.<span id="more-1077"></span></p>
<h2>How It Happened</h2>
<p>I periodically venture off into the h4x0r wilderness and pour myself into some random project. It always starts out innocently enough, but the project soon takes on a life of it’s own. This time was no different&#8230; except it happened over Thanksgiving (much to my wife’s chagrin).</p>
<p>Being the charismatic socialite that I am (sarcasm), I was digging through the C++11 spec on Thanksgiving. What struck me was how much of my language design course I had forgotten, and it really bugged me. It&#8217;s one of those required courses in the CompSci graduate program that I loathed having to take, but turned out to be invaluable (don’t get me started on the database and UI design courses&#8230; blah).</p>
<p>Long story less long, I started refreshing on compilers (<a title="Rich Programmer Food" href="http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html" target="_blank">read this</a> for inspiration). I’d heard about Clang and <a title="LLVM" href="http://llvm.org/" target="_blank">LLVM</a> awhile ago, and I remembered their focus on modularity, maintainability, and all sorts of other *ability’s. I figured it&#8217;d be a good place to start, so I download the source code and dug through it (watch <a title="Clang Video" href="http://clang.llvm.org/clang_video-05-25-2007.html" target="_blank">this video</a> for background on Clang).</p>
<p>Stepping through Clang in a debugger sounded like a great way to start, but I quickly had mental stack overflow through the recursive parsing code. Okay, time for plan B. Common wisdom says that a good way to learn a piece of code is to try and fix a bug. So I went to the Clang bug list looking for a starter task, but all the “interesting” tasks were way too large in scope for a Clang newb like me.</p>
<p>Time to invent plan C: make a small tweak to the language and see if I can get it working. I remembered a few years ago that some students from Iowa State built an Ebonicode compiler for a language class they had. It got quite a few laughs around the office and was always wishing for a working compiler. So I decided take their idea and replace ‘<code>while</code>’ with ‘<code>slongas</code>’&#8230; and an hour later I had it working (which is testament to the readability of the Clang code&#8230; it’s very well commented).</p>
<p>Not satisfied to stop there, I moved on to other keywords&#8230; simple, once you get comfortable with how the code’s laid out. &#8220;What about operators and punctuators?&#8221;, I wondered. After a few failed attempts, it dawned on me that C++ has aliases for operators (‘<code>and_eq</code>’ can be used in place of ‘<code>&amp;=</code>’, etc). Instead of heavily modifying the parser/lexer, I started looking for how Clang handled these aliases&#8230; maybe I could just add some more. Turns out, it fairly simple to add new aliases, so ‘<code>==</code>’ got overloaded with ‘<code>sameas</code>’, ‘<code>!=</code>’ got overloaded with ‘<code>aint</code>’, etc&#8230; and it worked! Sweet!</p>
<p>After all that, I dug a little into the preprocessor and figured out how to support ‘<code>#mahomie</code>’ in place of ‘<code>#include</code>’. Simple enough. I dug a little into the build stuff and changed the name from ‘clang’ to ‘foshizzle’&#8230; cool. I little bit of frustration later, and I had it recognizing ‘*.opp’ and ‘*.ho’ as source and header files, respectively.</p>
<p>Three days after I started, I had a fully functional Ebonicode++ compiler and a lot deeper understanding of how a production C++ compiler works. I can’t stress enough that this project would never have happened if the Clang code wasn’t written so well. Kudos to the Clang team.</p>
<p>I really enjoyed this project, and I hope you get half the fun out of it I did. Next time you have a coding task, consider adding a litta gansta sizzle <img src='http://tdistler.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2>C++ To Ebonicode++ Mapping</h2>
<p>&nbsp;</p>
<table style="text-align: center;" width="400" border="0">
<tbody>
<tr>
<th>C++</th>
<th>Ebonicode++</th>
<th>|</th>
<th>C++</th>
<th>Ebonicode++</th>
</tr>
<tr>
<td><code>#include</code></td>
<td><code>#mahomie</code></td>
<td>|</td>
<td><code>switch</code></td>
<td><code>whatchugondo</code></td>
</tr>
<tr>
<td><code>break</code></td>
<td><code>bustanut</code></td>
<td>|</td>
<td><code>this</code></td>
<td><code>dis</code></td>
</tr>
<tr>
<td><code>case</code></td>
<td><code>ifa</code></td>
<td>|</td>
<td><code>throw</code></td>
<td><code>throz</code></td>
</tr>
<tr>
<td><code>catch</code></td>
<td><code>wrekdit</code></td>
<td>|</td>
<td><code>true</code></td>
<td><code>tru</code></td>
</tr>
<tr>
<td><code>char</code></td>
<td><code>alphabizzle</code></td>
<td>|</td>
<td><code>try</code></td>
<td><code>checkit</code></td>
</tr>
<tr>
<td><code>class</code></td>
<td><code>claz</code></td>
<td>|</td>
<td><code>typedef</code></td>
<td><code>reprezentin</code></td>
</tr>
<tr>
<td><code>const</code></td>
<td><code>foodonchange</code></td>
<td>|</td>
<td><code>using</code></td>
<td><code>uzin</code></td>
</tr>
<tr>
<td><code>continue</code></td>
<td><code>mo</code></td>
<td>|</td>
<td><code>virtual</code></td>
<td><code>frontin</code></td>
</tr>
<tr>
<td><code>delete</code></td>
<td><code>cap</code></td>
<td>|</td>
<td><code>void</code></td>
<td><code>shiznit</code></td>
</tr>
<tr>
<td><code>else</code></td>
<td><code>elz</code></td>
<td>|</td>
<td><code>volatile</code></td>
<td><code>trippin</code></td>
</tr>
<tr>
<td><code>export</code></td>
<td><code>bounce</code></td>
<td>|</td>
<td><code>while</code></td>
<td><code>slongas</code></td>
</tr>
<tr>
<td><code>extern</code></td>
<td><code>othahood</code></td>
<td>|</td>
<td><code>;</code></td>
<td><code>bitch</code> or <code>biatch</code></td>
</tr>
<tr>
<td><code>false</code></td>
<td><code>falz</code></td>
<td>|</td>
<td><code>=</code></td>
<td><code>be</code></td>
</tr>
<tr>
<td><code>float</code></td>
<td><code>flo</code></td>
<td>|</td>
<td><code>==</code></td>
<td><code>sameas</code></td>
</tr>
<tr>
<td><code>for</code></td>
<td><code>fo</code></td>
<td>|</td>
<td><code>!=</code></td>
<td><code>aint</code></td>
</tr>
<tr>
<td><code>friend</code></td>
<td><code>homie</code></td>
<td>|</td>
<td><code>+</code></td>
<td><code>an</code></td>
</tr>
<tr>
<td><code>long</code></td>
<td><code>shlong</code></td>
<td>|</td>
<td><code>-</code></td>
<td><code>widout</code></td>
</tr>
<tr>
<td><code>namespace</code></td>
<td><code>namespaze</code></td>
<td>|</td>
<td><code>*</code></td>
<td><code>dimes</code></td>
</tr>
<tr>
<td><code>new</code></td>
<td><code>makea</code></td>
<td>|</td>
<td><code>/</code></td>
<td><code>videdby</code></td>
</tr>
<tr>
<td><code>private</code></td>
<td><code>nonyobiz</code></td>
<td>|</td>
<td><code>&gt;</code></td>
<td><code>bepimpin</code></td>
</tr>
<tr>
<td><code>protected</code></td>
<td><code>indafamily</code></td>
<td>|</td>
<td><code>&lt;</code></td>
<td><code>fearin</code></td>
</tr>
<tr>
<td><code>public</code></td>
<td><code>tweetdat</code></td>
<td>|</td>
<td><code>++</code></td>
<td><code>propsta</code></td>
</tr>
<tr>
<td><code>return</code></td>
<td><code>putou</code></td>
<td>|</td>
<td><code>--</code></td>
<td><code>dissin</code></td>
</tr>
</tbody>
</table>
<ul>
<li> *.cpp -&gt; *.opp</li>
<li>*.h -&gt; *.ho</li>
</ul>
<p>Many thanks to <a href="https://plus.google.com/s/sean%20tegtmeyer" target="_blank">Sean Tegtmeyer</a> for helping with the syntax definition.</p>
<h2>Building Foshizzle</h2>
<p>I <em>highly</em> suggest building Clang <strong>without</strong> my changes first and verify that you have it working correctly. Then it should be simple to apply my patch and rebuild. I did all my work on Fedora 16, so your mileage may vary on other distros or OSes.</p>
<p><strong>Note</strong>: If you have any problems building LLVM or Clang, please refer to their build page: <a title="Clang: Getting Started" href="http://clang.llvm.org/get_started.html" target="_blank">Getting Started</a></p>
<ol>
<li>Create a new directory (e.g. &#8220;foshizzle&#8221;).</li>
<li>Within the &#8220;foshizzle&#8221; directory, create the following directories: &#8220;build&#8221;, &#8220;src&#8221;, &#8220;install&#8221;</li>
<li>Checkout the LLVM source code into the &#8220;src&#8221; directory:</li>
<ul>
<li><code>svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_30/rc4 ./src</code></li>
</ul>
<li>Create a new directory for the Clang source within the LLVM &#8220;tools&#8221; directory:</li>
<ul>
<li><code>mkdir src/tools/clang</code></li>
</ul>
<li>Checkout the Clang source code into the &#8220;src/tools/clang&#8221; directoy:</li>
<ul>
<li><code>svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_30/rc4 ./src/tools/clang</code></li>
</ul>
<li>Change directories into the &#8220;build&#8221; directory.</li>
<li>Configure the Clang/LLVM build and point it to the &#8220;install&#8221; directory you created earlier:</li>
<ul>
<li><code>../src/configure --prefix=&lt;path&gt;/&lt;to&gt;/&lt;foshizzle&gt;/install</code></li>
</ul>
<li>Build (takes quite a while): <code>make</code></li>
<li>Install: <code>make install</code></li>
<li>Compile some test code to make sure it works: <code>install/bin/clang++ yourtestcode.cpp</code></li>
</ol>
<p><strong>Only</strong> continue on once the unmodified version of Clang is working.</p>
<ol>
<li>Download my patch file: <a href="http://tdistler.com/media/code/eubonicode/ebpp-clang30rc4.patch" target="_blank">ebpp-clang30rc4.patch</a></li>
<li>Change directories to where the Clang source is (src/tools/clang).</li>
<li>Apply the patch: <code>patch -p0 -i ebpp-clang30rc4.patch</code></li>
<li>Change back to the &#8220;build&#8221; directory.</li>
<li>Build: <code>make</code></li>
<li>Install: <code>make install</code></li>
<li>Test: <code>install/bin/foshizzle++ yordopecodez.opp</code></li>
</ol>
<p>You can also build the sample code below.</p>
<h2>Sample Code</h2>
<p><a href="http://tdistler.com/media/code/eubonicode/baseclaz.ho" target="_blank">baseclaz.ho</a>, <a href="http://tdistler.com/media/code/eubonicode/friendclaz.ho" target="_blank">friendclaz.ho</a>, <a href="http://tdistler.com/media/code/eubonicode/main.opp" target="_blank">main.opp</a></p>
<p><strong>Building</strong></p>
<pre>install/bin/foshizzle++ main.opp</pre>
<p>&nbsp;</p>
<p><strong>Program Output</strong></p>
<pre>baseclaz: protected = 1, private = 1
derivedclaz: protected = 0, private = 1
friendclaz: friend private = 0

Factorial(7) = 5040</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/12/03/eubonicode-hackin-c-gangsta-style/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adding stdint.h to Visual Studio</title>
		<link>http://tdistler.com/2011/11/13/adding-stdint-h-to-visual-studio</link>
		<comments>http://tdistler.com/2011/11/13/adding-stdint-h-to-visual-studio#comments</comments>
		<pubDate>Sun, 13 Nov 2011 13:00:51 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1066</guid>
		<description><![CDATA[Yes, stdint.h and inttypes.h are missing from Microsoft Visual Studio. As a result, anyone who&#8217;s written cross-platform C\C++ code for Windows has probably seen this error: error C2146: syntax error : missing ';' before identifier 'foo' error C4430: missing type specifier - int assumed. Note: C++ does not support default-int The fact is that Visual [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, <code>stdint.h</code> and <code>inttypes.h</code> are missing from Microsoft Visual Studio. As a result, anyone who&#8217;s written cross-platform C\C++ code for Windows has probably seen this error:</p>
<p><code>error C2146: syntax error : missing ';' before identifier 'foo'<br />
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int</code></p>
<p>The fact is that Visual Studio doesn&#8217;t implement C99&#8230; it implements C89 (for compatibility reasons). So, you don&#8217;t have access to familiar types like:</p>
<ul>
<li><code>int8_t, int16_t, int32_t, int64_t</code></li>
<li><code>uint8_t, uint16_t, uint32_t, uint64_t</code></li>
<li><code>INT8_MIN</code>, <code>INT8_MAX</code>, etc</li>
<li>The <code>fprintf</code> macros <code>PRId32</code>, <code>PRIu32</code>, etc</li>
<li><code>strtoimax()</code>, etc</li>
</ul>
<p>Fortunately, <a href="http://www.chemeris.ru/" target="_blank">Alexander Chemeris</a> has written <a title="Google Code" href="http://code.google.com/p/msinttypes/" target="_blank">msinttypes</a>: an implementation of <code>stdint.h</code> and <code>inttypes.h</code> for Microsoft Visual Studio. It is licensed under the BSD license, so the headers are actually usable commercially (no viral GPL). This following quote probably goes without saying (emphasis mine):</p>
<blockquote><p>Note though, that just adding these headers does <strong>not</strong> make Visual Studio compiler fully C99 compliant.</p></blockquote>
<p>This project has saved me a bunch of unwanted coding. Thanks Alex!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/11/13/adding-stdint-h-to-visual-studio/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Inside the .NET CLR Garbage Collector</title>
		<link>http://tdistler.com/2011/09/09/inside-the-net-clr-garbage-collector</link>
		<comments>http://tdistler.com/2011/09/09/inside-the-net-clr-garbage-collector#comments</comments>
		<pubDate>Fri, 09 Sep 2011 15:00:29 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1049</guid>
		<description><![CDATA[Here&#8217;s a great interview with Microsoft Technical Fellow and author of the CLR garbage collector, Patrick Dussud. How does GC, work, generally? Why is it important? The GC inside of the CLR is of a specfic type &#8211; ephemeral, concurrent (the server version has always been concuurent and now with Background GC on the client [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a great interview with Microsoft Technical Fellow and author of the CLR garbage collector, <a title="Profile: Patrick Dussud" href="http://www.microsoft.com/presspass/exec/techfellow/dussud/default.mspx" target="_blank">Patrick Dussud</a>.</p>
<blockquote><p>How does GC, work, generally? Why is it important? The GC inside of the CLR is of a specfic type &#8211; ephemeral, concurrent (the server version has always been concuurent and now with Background GC on the client in CLR 4, GC is concurrent on the client as well, but there are differences&#8230;)</p></blockquote>
<p><iframe style="height: 288px; width: 512px;" src="http://channel9.msdn.com/Shows/Going+Deep/E2E-Erik-Meijer-and-Patrick-Dussud-Inside-Garbage-Collection/player?w=512&amp;h=288" frameborder="0" scrolling="no" width="320" height="240"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/09/09/inside-the-net-clr-garbage-collector/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++11: Move Semantics and Rvalue References</title>
		<link>http://tdistler.com/2011/08/18/c11-move-semantics-and-rvalue-references</link>
		<comments>http://tdistler.com/2011/08/18/c11-move-semantics-and-rvalue-references#comments</comments>
		<pubDate>Thu, 18 Aug 2011 15:00:36 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1017</guid>
		<description><![CDATA[Thomas Becker has a great article explaining C++11&#8242;s rvalue references and how they allow move semantics and perfect forwarding. I particularly liked his summary of the 3 things you need to remember about rvalue references: By overloading a function like this: void foo(X&#38; x); // lvalue reference overload void foo(X&#38;&#38; x); // rvalue reference overload [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Thomas Becker: C++ Rvalue References Explained" href="http://thbecker.net/articles/rvalue_references/section_01.html" target="_blank">Thomas Becker has a great article</a> explaining C++11&#8242;s rvalue references and how they allow move semantics and perfect forwarding.</p>
<p>I particularly liked his summary of the 3 things you need to remember about rvalue references:</p>
<ol>
<li>By overloading a function like this:<br />
<code>
<pre>

void foo(X&amp; x); // lvalue reference overload
void foo(X&amp;&amp; x); // rvalue reference overload
</pre>
<p></code><br />
you can branch at compile time on the condition &#8220;is foo being called on an lvalue or an rvalue?&#8221; The primary (and for all practical purposes, the only) application of that is to overload the copy constructor and copy assignment operator of a class for the sake of implementing move semantics. If and when you do that, make sure to pay attention to exception handling, and use the new noexcept keyword as much as you can.</li>
<li><code>std::move</code> turns its argument into an rvalue.</li>
<li><code>std::forward</code> allows you to achieve perfect forwarding if you use it exactly as shown:<br />
<code>
<pre>

template&lt;typename T, typename Arg&gt;
shared_ptr&lt;T&gt; factory(Arg&amp;&amp; arg)
{
    return shared_ptr&lt;T&gt;(new T(std::forward&lt;Arg&gt;(arg));
}</pre>
<p></code>
</li>
</ol>
<p>I also like his definition of lvalues and rvalues in the <a title="Thomas Becker: Introduction" href="http://thbecker.net/articles/rvalue_references/section_01.html" target="_blank">introduction</a>:</p>
<blockquote><p>The original definition of lvalues and rvalues from the earliest days of C is as follows: An <em>lvalue</em> is an expression <code>e</code> that may appear on the left or on the right hand side of an assignment, whereas an<em>rvalue</em> is an expression that can only appear on the right hand side of an assignment.</p>
<p>In C++, this is still useful as a first, intuitive approach to lvalues and rvalues. <strong>However</strong>, C++ with its user-defined types has introduced some subtleties regarding modifiability and assignability that cause this definition to be incorrect. There is no need for us to go further into this. Here is an alternate definition which, although it can still be argued with, will put you in a position to tackle rvalue references: <em><strong>An lvalue is an expression that refers to a memory location and allows us to take the address of that memory location via the <code>&amp;</code> operator. An rvalue is an expression that is not an lvalue. </strong></em></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/08/18/c11-move-semantics-and-rvalue-references/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to connect Linux to a Cisco VPN using a PCF file</title>
		<link>http://tdistler.com/2011/07/07/how-to-connect-linux-to-a-cisco-vpn-using-a-pcf-file</link>
		<comments>http://tdistler.com/2011/07/07/how-to-connect-linux-to-a-cisco-vpn-using-a-pcf-file#comments</comments>
		<pubDate>Thu, 07 Jul 2011 15:10:19 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1007</guid>
		<description><![CDATA[Connecting Linux to a Cisco VPN server using a PCF file is easy (even from within a VirtualBox virtual machine). First, I wouldn&#8217;t bother with Cisco&#8217;s Linux client&#8230; especially if you are running 64bit. You have to patch a source file and mod the Makefile. Using VPNC is so much easier. NOTE: I only had [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/11/tux_cisco.jpg"><img class="alignright size-thumbnail wp-image-1011" title="tux_cisco" src="http://tdistler.com/wp-content/uploads/2011/11/tux_cisco-150x150.jpg" alt="" width="150" height="150" /></a>Connecting Linux to a Cisco VPN server using a PCF file is easy (even from within a <a title="VirtualBox" href="https://www.virtualbox.org/" target="_blank">VirtualBox</a> virtual machine). First, I wouldn&#8217;t bother with Cisco&#8217;s Linux client&#8230; especially if you are running 64bit. You have to patch a source file and mod the Makefile. Using <a title="VPNC" href="http://www.unix-ag.uni-kl.de/~massar/vpnc/" target="_blank">VPNC</a> is so much easier.</p>
<p><em>NOTE: I only had the PCF file provided by work, and the group password was encrypted. If you know your group password, then you can just run VPNC directly or write a conf file yourself.</em></p>
<p>My setup:</p>
<ul>
<li>Fedora 12 x86_64</li>
<li>Running in VirtualBox 4.1.6 with <em><strong>bridged networking</strong></em> (I didn&#8217;t try it with NAT)</li>
<li>Connecting to a Cisco VPN server at work</li>
</ul>
<p>Connecting:</p>
<ol>
<li>Install VPNC (`<code>sudo yum install vpnc</code>` in Fedora)</li>
<li>Download the <a title="pcf2vpnc" href="http://svn.unix-ag.uni-kl.de/vpnc/trunk/pcf2vpnc" target="_blank">pcf2vpnc</a> Perl script (<a title="cached pcf2vpnc" href="http://www.tdistler.com/media/code/pcf2vpnc" target="_blank">cached</a>)</li>
<li>Convert your Cisco PCF file to VPNC conf format: `<code>perl pcf2vpnc company.pcf vpnc.conf</code>`</li>
<li>Connect to the VPN server: `<code>sudo vpnc ./vpnc.conf</code>` (you will be prompted for you username and password)</li>
<li>(optional) Run <code>`ifconfig</code>` to see the tunnel interface that was created</li>
</ol>
<blockquote>
<pre><code>eth0     Link encap:Ethernet  HWaddr 08:00:DE:AD:BE:EF
         inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
         ...

lo       Link encap:Local Loopback
         inet addr:127.0.0.1  Mask:255.0.0.0
         ...

<strong>tun0     Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
         inet addr:10.200.100.1  P-t-P:10.220.116.219  Mask:255.255.255.255</strong>
         ...</code></pre>
</blockquote>
<p>Disconnecting:</p>
<ol>
<li>Run `<code>sudo vpnc-disconnect</code>` (don&#8217;t forget the `<code>sudo</code>`)</li>
</ol>
<p>That&#8217;s it. Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/07/07/how-to-connect-linux-to-a-cisco-vpn-using-a-pcf-file/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CRC32: A Simple C++ Class</title>
		<link>http://tdistler.com/2011/06/22/crc32-a-simple-c-class</link>
		<comments>http://tdistler.com/2011/06/22/crc32-a-simple-c-class#comments</comments>
		<pubDate>Wed, 22 Jun 2011 17:32:51 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=993</guid>
		<description><![CDATA[A simple C++ class for calculating CRC32.]]></description>
			<content:encoded><![CDATA[<p><a title="Wikipedia: Cyclic Redundancy Check" href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check" target="_blank">Cyclic Redundancy Checks</a> are a quick and convenient way to verify if a data set has changed. They are not meant to be &#8220;secure&#8221; like a MD5 or SHA-1, but they offer a very practical solution to most problems. CRC&#8217;s are also useful for verifying if 2 data sets are equal. Here&#8217;s a simple class I use that&#8217;s efficient. Honestly, I don&#8217;t remember what flavor of CRC32 it implements (sorry), but it has always worked for what I&#8217;ve needed. Cheers!</p>
<pre><code>static const uint32_t kCrc32Table[256] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,<span id="more-993"></span>
    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
}; // kCrc32Table

class Crc32
{
public:
    Crc32() { Reset(); }
    ~Crc32() throw() {}
    void Reset() { _crc = (uint32_t)~0; }
    void AddData(const uint8_t* pData, const uint32_t length)
    {
        uint8_t* pCur = (uint8_t*)pData;
        uint32_t remaining = length;
        for (; remaining--; ++pCur)
            _crc = ( _crc &gt;&gt; 8 ) ^ kCrc32Table[(_crc ^ *pCur) &amp; 0xff];
    }
    const uint32_t GetCrc32() { return ~_crc; }

private:
    uint32_t _crc;
};

</code></pre>
<p><strong>Note</strong>: I always have <code>uint32_t</code> defined in Windows, so you may have to define it yourself or use the Microsoft intrinsic <code>unsigned __int32</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/06/22/crc32-a-simple-c-class/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Live555: Compiling with VS2008</title>
		<link>http://tdistler.com/2011/05/14/live555-compiling-with-vs2008</link>
		<comments>http://tdistler.com/2011/05/14/live555-compiling-with-vs2008#comments</comments>
		<pubDate>Sat, 14 May 2011 18:30:49 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[live555]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=959</guid>
		<description><![CDATA[4 easy steps to compile Live555 using VS2008. Fixes link error: LNK1181: cannot open input file 'msvcirt.lib'.]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/02/network.jpg"><img class="alignright size-thumbnail wp-image-795" title="network" src="http://tdistler.com/wp-content/uploads/2011/02/network-150x150.jpg" alt="" width="100" height="100" /></a>Compiling <a title="Live555 Streaming Media" href="http://www.live555.com/liveMedia/" target="_blank">Live555 Streaming Media</a> with Visual Studio 2008 isn&#8217;t obvious. Using Cygwin or MinGW is just a pain and frankly unnecessary. There is no built-in support for VS solution files, because Windows support is a low priority for the Live555 community. This is evidenced by <a title="Live555 Forum" href="http://lists.live555.com/pipermail/live-devel/2008-January/008022.html" target="_blank">this forum response</a> from Ross Finlayson:</p>
<blockquote><p><em>&gt;4.  Is it possible to include a Visual Studio solution in the</em><br />
<em> &gt;distrubution to make it more convenient for Windows developers to</em><br />
<em> &gt;use live555?</em><br />
<em> &gt;5.  Is it possible for live555 to generate adequate makefiles for</em><br />
<em> &gt;Windows systems with development environments newer than Visual</em><br />
<em> &gt;Studio 2003?</em></p>
<p><strong>I have no current plans to change this.  (These days, fewer and fewer</strong> <strong>people seem to be using Windows for development of system software.)</strong></p></blockquote>
<p>Regardless, Live555 works fine on Windows and is actually quite easy to build. Simply do the following:</p>
<ol>
<li>Open the &#8216;win32config&#8217; file and change the <code>TOOLS32=... </code>variable to your VS2008 install directory. For me, it&#8217;s <code>TOOLS32=C:\Program Files\Microsoft Visual Studio 9.0\VC</code></li>
<li>In &#8216;win32config&#8217;, modify the <code>LINK_OPTS_0=...</code> line from <code>msvcirt.lib</code> to <code>msvcrt.lib</code>. This fixes the link error:<br />
<code>LINK : fatal error LNK1181: cannot open input file 'msvcirt.lib'</code></li>
<li>Open the Visual Studio command prompt.</li>
<li>From the &#8216;live&#8217; source directory, run <code>genWindowsMakefiles</code></li>
<li>Now you&#8217;re ready to build. Simply run the following commands:
<pre><code>cd liveMedia
nmake /B -f liveMedia.mak
cd ..\groupsock
nmake /B -f groupsock.mak
cd ..\UsageEnvironment
nmake /B -f UsageEnvironment.mak
cd ..\BasicUsageEnvironment
nmake /B -f BasicUsageEnvironment.mak
cd ..\testProgs
nmake /B -f testProgs.mak
cd ..\mediaServer
nmake /B -f mediaServer.mak</code></pre>
</li>
</ol>
<p>That&#8217;s it. You should be good to go.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/05/14/live555-compiling-with-vs2008/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Lua: Get CPU Load on Linux</title>
		<link>http://tdistler.com/2011/05/02/lua-get-cpu-load-on-linux</link>
		<comments>http://tdistler.com/2011/05/02/lua-get-cpu-load-on-linux#comments</comments>
		<pubDate>Tue, 03 May 2011 00:07:01 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=951</guid>
		<description><![CDATA[Here's a Lua function that returns the percentage of CPU used on Linux. The load includes time in user space and system space. ]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a Lua function that returns the percentage of CPU used on Linux. The load includes time in user space and system space. In case you&#8217;re curious, I used `<code>top</code>` to get the load for a couple reasons:</p>
<ol>
<li>It&#8217;s installed by default on most distros (as opposed to the <code>sysstat</code> tools).</li>
<li>It gives the idle time in percentage normalized to 100% (as opposed to <code>/proc/stat</code> which requires knowledge of the jiffy&#8217;s interval, which can vary).</li>
</ol>
<pre><code>function cpu_load(interval)
   interval = interval or 1
   local f = io.popen('top -bp$$ -d ' .. interval .. ' -n 2')
   local s = f:read('*all')

   -- Find the idle times in the stdout output
   local tokens = s:gmatch(',%s*([%d%.]+)%%%s*id')

   -- We're interested in the 2nd 'top' idle time
   local ii = 1
   for idle in tokens do
      if ii == 2 then
         return 100.0 - tonumber(idle)
      end
      ii = ii + 1
   end
end

</code></pre>
<p>You can call it from the Lua shell as:</p>
<pre><code>&gt; load = cpu_load()
&gt; print(load)
43.7

</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/05/02/lua-get-cpu-load-on-linux/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rendering Video with GDI (Example)</title>
		<link>http://tdistler.com/2011/04/20/rendering-video-with-gdi-example</link>
		<comments>http://tdistler.com/2011/04/20/rendering-video-with-gdi-example#comments</comments>
		<pubDate>Wed, 20 Apr 2011 18:04:25 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=932</guid>
		<description><![CDATA[Example C++ GDI video window class with text overlay.]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/04/video-icon.jpg"><img class="alignright size-thumbnail wp-image-948" title="video-icon" src="http://tdistler.com/wp-content/uploads/2011/04/video-icon-150x150.jpg" alt="" width="150" height="150" /></a>In this post, I outline a basic GDI video window class. GDI is inefficient for rendering video, but it&#8217;s also very convinient when writing simple tools on Windows. I find myself doing it often enough that it makes sense to do a brain-dump here. This is only an outline, but it should get you over the biggest hurdles.</p>
<h4>Outline</h4>
<ol>
<li>Video Window Class Definition</li>
<li>Creating and Destroying the Window</li>
<li>The Window Thread</li>
<li>The Message Pump</li>
<li>Rendering a Video Frame</li>
</ol>
<p>Things to note:</p>
<ul>
<li>You will need a thread in your window class to &#8220;pump&#8221; window events.</li>
<li>GDI does NOT do any color conversion, so you will need to convert each frame into the same format as the display (always RGB, usually 24 or 32 bits).</li>
</ul>
<h4>Video Window Class Definition</h4>
<pre><code>class VideoWindow
{
public:
    ...
private:
    static DWORD _ThreadMain(void*);
    static LRESULT WINAPI _MsgProc(HWND, UINT, WPARAM, LPARAM);

    CRITICAL_SECTION _lok;
    HANDLE _thread;
    HWND _hWnd;
    HDC _hDC;
    HDC _hFrameDC;
    HFONT _hFont;
    int _bpp;   // bit depth
    volatile bool _exit;
    int _x, _y, _w, _h; // Window dimensions
    int _imgWidth, _imgHeight, _imgLength; // Frame dimensions
    unsigned char *_imgBits;
};

</code></pre>
<h4>Creating and Destroying the Window</h4>
<pre><code>void VideoWindow::Create(int x, int y, int w, int h)
{
    EnterCriticalSection(&amp;_lok);
    _x = x;
    _y = y;
    _w = w;
    _h = h;
    _hWnd = 0;
    _exit = false;
    _thread = CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)_ThreadMain,
        this, NULL, 0 );
    LeaveCriticalSection(&amp;_lok);

    // Wait for window to be created. Cheap, but it works.
    while (!_hWnd) {
        ::Sleep(100);
    }
}
<span id="more-932"></span>
void VideoWindow::Destroy()
{
    // Safe to call from the destructor.

    EnterCriticalSection(&amp;_lok);
    if(_hWnd)
    {
        _exit = true;
        LeaveCriticalSection(&amp;_lok);
        WaitForSingleObject( _thread, INFINITE );
        CloseHandle(_thread);
        EnterCriticalSection(&amp;_lok);
        DestroyWindow(_hWnd);
        _hWnd = 0;
    }
    if (_hFont) ::DeleteObject(_hFont);
    if (_hFrameDC) ::DeleteDC(_hFrameDC);
    if (_hDC) ::DeleteDC(_hDC);
    LeaveCriticalSection(&amp;_lok);
}

</code></pre>
<h4>The Window Thread</h4>
<pre><code>DWORD VideoWindow::_ThreadMain(void* ctx)
{
    VideoWindow *p = (VideoWindow*)ctx;
    EnterCriticalSection(&amp;p-&gt;_lok);

    LPCSTR className = "VideoWndClass";
    LPCSTR windowName = "MyWindowText";
    WNDCLASSEX wcex = {
        sizeof(WNDCLASSEX),
        CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
        _MsgProc,
        0L,
        0L,
        NULL,
        NULL,
        NULL,
        (HBRUSH)GetStockObject(BLACK_BRUSH),
        NULL,
        className,
        NULL
    };

    RegisterClassEx(&amp;wcex);   

    p-&gt;_hWnd = CreateWindow(className, windowName, WS_OVERLAPPEDWINDOW,
        p-&gt;_x, p-&gt;_y, p-&gt;_w, p-&gt;_h, ::GetDesktopWindow(), NULL, NULL, NULL);

    p-&gt;_hDC = ::GetDC(p-&gt;_hWnd);
    p-&gt;_bpp = ::GetDeviceCaps(p-&gt;_hDC, BITSPIXEL);
    p-&gt;_hFrameDC = ::CreateCompatibleDC(p-&gt;_hDC);

    p-&gt;_hFont = ::CreateFont(18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");

    ShowWindow(p-&gt;_hWnd,SW_SHOW);
    UpdateWindow(p-&gt;_hWnd);

    while( !p-&gt;_exit )
    {
        MSG msg;
        if(PeekMessage(&amp;msg,p-&gt;_hWnd,0,0,PM_REMOVE))
        {
            TranslateMessage(&amp;msg);
            DispatchMessage(&amp;msg);
        }

        LeaveCriticalSection(&amp;p-&gt;_lok);
        Sleep(50); // A better way to do this is to use a message
        EnterCriticalSection(&amp;p-&gt;_lok);
    }
    LeaveCriticalSection(&amp;p-&gt;_lok);
    return 0;
}

</code></pre>
<h4>The Message Pump</h4>
<pre><code>LRESULT WINAPI VideoWindow::_MsgProc(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
{
    if (msg == WM_PAINT &amp;&amp; l)
    {
        VideoWindow *p = (VideoWindow*)l;
        EnterCriticalSection(&amp;p-&gt;_lok);

        HGDIOBJ  oldFont  = ::SelectObject(p-&gt;_hDC, p-&gt;_hFont);
        COLORREF oldFtColor = ::SetTextColor(p-&gt;_hDC, RGB(255,255,255));
        COLORREF oldBkColor = ::SetBkColor(p-&gt;_hDC, RGB(64,64,64));

        // Render image
        //
        // NOTE: This assumes you've already coverted the image to the proper
        // RGB bit-depth (_bpp) and copied the data into _imageBits.
        //
        HBITMAP hBMP = ::CreateCompatibleBitmap(p-&gt;_hDC, p-&gt;_imgWidth,
            p-&gt;_imgHeight);
        ::SetBitmapBits(hBMP, p-&gt;_imgLength, p-&gt;_imgBits);
        HGDIOBJ oldBMP = ::SelectObject(p-&gt;_hFrameDC, hBMP);
        ::BitBlt(p-&gt;_hDC, 0, 0, p-&gt;_imgWidth, p-&gt;_imgHeight, p-&gt;_hFrameDC,
            0, 0, SRCCOPY);
        ::SelectObject(p-&gt;_hFrameDC, oldBMP);

        // Draw some text over the image
        RECT rect;
        ::SetRectEmpty(&amp;rect);
        ::DrawText(p-&gt;_hDC, p-&gt;_imageText, -1, &amp;rect, DT_CALCRECT);
        ::DrawText(p-&gt;_hDC, p-&gt;_imageText, -1, &amp;rect, DT_CENTER | DT_VCENTER);

        if (hBMP) ::DeleteObject(hBMP);

        LeaveCriticalSection(&amp;p-&gt;_lok);
    }
    return DefWindowProc(hWnd, msg, w, l);
}

</code></pre>
<p><strong>Rendering a Video Frame</strong></p>
<pre><code>
void VideoWindow::Render(const unsigned char* frame, int w, int h, int stride)
{
    // Convert frame to the proper RGB bit depth to match _bpp and copy it
    // into _imgBits buffer. Update _imgWidth, _imgHeight, and _imgLength as
    // necessary.

    ::PostMessage(_hWnd, WM_PAINT, 0, (LPARAM)this);
}

</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/04/20/rendering-video-with-gdi-example/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Define NaN (Not-a-Number) on Windows</title>
		<link>http://tdistler.com/2011/03/24/how-to-define-nan-not-a-number-on-windows</link>
		<comments>http://tdistler.com/2011/03/24/how-to-define-nan-not-a-number-on-windows#comments</comments>
		<pubDate>Thu, 24 Mar 2011 20:41:48 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=874</guid>
		<description><![CDATA[The C99 spec requires that math.h should define the constant float value NAN. However, NAN isn&#8217;t defined in the Visual Studio version of math.h, so you have to define it yourself (VS only implements C89). It&#8217;s pretty straight-forward for 32-bit machines&#8230; here&#8217;s my implementation with cross-platform protection: #ifdef WIN32 #ifndef NAN static const unsigned long [...]]]></description>
			<content:encoded><![CDATA[<p>The C99 spec requires that <a title="The Open Group: math.h" href="http://pubs.opengroup.org/onlinepubs/009695399/basedefs/math.h.html" target="_blank">math.h should define the constant float value NAN</a>. However, NAN isn&#8217;t defined in the Visual Studio version of math.h, so you have to define it yourself (VS only implements C89). It&#8217;s pretty straight-forward for 32-bit machines&#8230; here&#8217;s my implementation with cross-platform protection:</p>
<pre><code>#ifdef WIN32
    #ifndef NAN
        static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
        #define NAN (*(const float *) __nan)
    #endif
#endif

</code></pre>
<p>This code is adapted from an MSDN <a title="MSDN: Not A Number (NAN) Items" href="http://msdn.microsoft.com/en-us/library/w22adx1s(v=vs.80).aspx" target="_blank">example</a>.<del datetime="2011-04-20T17:26:37+00:00"></del></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/03/24/how-to-define-nan-not-a-number-on-windows/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cross-Platform IPv6 Socket Programming</title>
		<link>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming</link>
		<comments>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming#comments</comments>
		<pubDate>Tue, 01 Mar 2011 04:00:39 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=793</guid>
		<description><![CDATA[Writing code that works on Windows, Linux, and Mac is frequently challenging. Socket programming is no exception. Modern versions of Linux and Mac have full implementations of the latest IPv6 socket API extensions defined in RFC 3493. Windows, however, has only a partial implementation of the original (deprecated) version, RFC 2553. This sounds worse than [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/02/network.jpg"><img class="alignright size-thumbnail wp-image-795" title="network" src="http://tdistler.com/wp-content/uploads/2011/02/network-150x150.jpg" alt="IPv6 Networking" width="150" height="150" /></a>Writing code that works on Windows, Linux, and Mac is frequently challenging. Socket programming is no exception. Modern versions of Linux and Mac have full implementations of the latest IPv6 socket API extensions defined in <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>. Windows, however, has only a partial implementation of the original (deprecated) version, <a title="IETF RFC 2553" href="http://tools.ietf.org/html/rfc2553" target="_blank">RFC 2553</a>. This sounds worse than it is, but it&#8217;s something you have to consider.</p>
<p><em><strong>Note</strong></em>: This post assumes you are already familiar with the socket extensions for IPv6 (<a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>).</p>
<p><strong>Linux and Mac</strong><br />
Good news&#8230; they both fully support <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>.</p>
<p><strong>Windows</strong><br />
Windows IPv6 support varies based on which version you&#8217;re targeting. Microsoft started adding IPv6 in Windows 2000, and they&#8217;ve continued adding more of the socket extensions as time went on. Most of the core functionality is present in XP, and what&#8217;s missing is easily replaced by using Winsock calls directly (more on this later).</p>
<p>Windows gained IPv6 support while <a title="IETF RFC 2553" href="http://tools.ietf.org/html/rfc2553" target="_blank">RFC 2553</a> was still the supported standard. Since then, it has been deprecated by <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>. However, Microsoft doesn&#8217;t want to break existing code written against it&#8217;s API, so the older API lives on. The main impact of this is that <code>sockaddr_in6</code> and <code>sockaddr_storage</code> are slightly different on Windows than Mac and Linux. The size of the structures across platforms is the same (the <code>sa_family_t</code> member was shortened), it&#8217;s just that the Windows structures don&#8217;t begin with the length member. For example:</p>
<pre><code>// Linux and Mac
struct sockaddr_in6 {
    uint8_t      sin6_len;    /* Added in RFC 3493 */
    sa_family_t  sin6_family;
    ...
};
struct sockaddr_storage {
    uint8_t      ss_len;      /* Added in RFC 3493 */
    sa_family_t  ss_family;
    ...
};

// Windows
struct sockaddr_in6 {
    sa_family_t  sin6_family;
    ...
};
struct sockaddr_storage {
    sa_family_t  ss_family;
    ...
};</code></pre>
<p>I&#8217;ve never had a problem with this, because the size of <code>sockaddr_in6</code> is easily determined (<code>sizeof(sockaddr_in6)</code>) and I always end up casting <code>sockaddr_storage</code> to the specific type (<code>sockaddr_in</code> or <code>sockaddr_in6</code>) based on <code>ss_family</code>.</p>
<p>Besides the data structure differences, it&#8217;s important to remember that Microsoft added IPv6 support over multiple versions. Support first appeared in Windows 2000, but more of the extensions have been added over time. Most of the core functionality was present in XP (including multicast), but not everything is implemented as of Windows 7. It&#8217;s annoying, but I will say that what&#8217;s missing is easily replaced by using Winsock calls directly.</p>
<p>Here&#8217;s the breakdown of IPv6 socket extensions by Windows version:</p>
<table border="1" width="570">
<tbody><!-- Results table headers --></p>
<tr>
<th>Socket Extension</th>
<th>2K</th>
<th>XP</th>
<th>Vista</th>
<th>7</th>
<th>Comments</th>
</tr>
<tr>
<td>if_indextoname()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>GetAdaptersAddresses() for XP</td>
</tr>
<tr>
<td>if_nametoindex()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>GetAdaptersAddresses() for XP</td>
</tr>
<tr>
<td>if_nameindex()</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>GetAdaptersAddresses() (XP, later)</td>
</tr>
<tr>
<td>if_freenameindex()</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>getaddrinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>getnameinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>freeaddrinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>gai_strerror()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>inet_pton()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>WSAStringToAddress() (2000, XP)</td>
</tr>
<tr>
<td>inet_ntop()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>WSAAddressToString() (2000, XP)</td>
</tr>
<tr>
<td>All IN6_IS_ADDR_* macros</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>Ex: IN6_IS_ADDR_LOOPBACK()</td>
</tr>
<tr>
<td>struct sockaddr_storage</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>Multicast support</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
</tbody>
</table>
<p>As you can see, you may still have to call Winsock directly depending on what version of Windows you are targeting. In my opinion, programming IPv6 on Windows is a lot easier if you only support XP and later, but I know that&#8217;s not always possible.</p>
<p><strong>Summary</strong></p>
<p>Modern operating systems all support IPv6. However, for business reasons, Windows has a slightly older version of the socket API which requires special consideration. My goal was to enumerate those differences to help make the transition to IPv6 smoother. Writing cross-platform code can be a fun challenge at times, but it&#8217;s also a little tedious. Hopefully, this post helps ease the pain.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Test if an Address is IPv4 or IPv6</title>
		<link>http://tdistler.com/2011/02/25/how-to-test-if-an-address-is-ipv4-or-ipv6</link>
		<comments>http://tdistler.com/2011/02/25/how-to-test-if-an-address-is-ipv4-or-ipv6#comments</comments>
		<pubDate>Fri, 25 Feb 2011 19:16:33 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=785</guid>
		<description><![CDATA[Here&#8217;s a simple function using getaddrinfo() that will take an IP address and return the address family (AF_INET for IPv4, AF_INET6 for IPv6, etc). I works on both Linux and Windows. This function will also accept hostnames and return the address family of the first address returned. You can disable this feature (and the corresponding [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a simple function using <a title="getaddrinfo man page" href="http://linux.die.net/man/3/getaddrinfo" target="_blank">getaddrinfo()</a> that will take an IP address and return the address family (<code>AF_INET</code> for IPv4, <code>AF_INET6</code> for IPv6, etc). I works on both Linux and Windows. This function will also accept hostnames and return the address family of the first address returned. You can disable this feature (and the corresponding DNS lookup) by passing the AI_NUMERICHOST flag.<br />
<code>
<pre>
// Returns the address family of an address or hostname.
// AF_INET, AF_INET6, or -1 on error.
int getaddrfamily(const char *addr)
{
    struct addrinfo hint, *info =0;
    memset(&amp;hint, 0, sizeof(hint));
    hint.ai_family = AF_UNSPEC;
    // Uncomment this to disable DNS lookup
    //hint.ai_flags = AI_NUMERICHOST;
    int ret = getaddrinfo(addr, 0, &amp;hint, &amp;info);
    if (ret)
        return -1;
    int result = info-&gt;ai_family;
    freeaddrinfo(info);
    return result;
}</pre>
<p></code></p>
<p>See <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a> for more information on the latest socket API for dealing with IPv6.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/02/25/how-to-test-if-an-address-is-ipv4-or-ipv6/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How To Test An Audio Codec: A Practical Approach</title>
		<link>http://tdistler.com/2011/01/25/how-to-test-an-audio-codec-a-practical-approach</link>
		<comments>http://tdistler.com/2011/01/25/how-to-test-an-audio-codec-a-practical-approach#comments</comments>
		<pubDate>Wed, 26 Jan 2011 01:16:28 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Did you know?]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=727</guid>
		<description><![CDATA[Recently, I was tasked with picking an AAC audio codec library for one of our products. There were several libraries I had to evaluate, and I needed some quantitative metrics for doing the comparison. I&#8217;m not what professionals call an &#8220;expert listener&#8221;, so I had to do the best with what I had. While creating [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/01/audio_waveform.jpg"><img class="alignright size-thumbnail wp-image-732" title="audio_waveform" src="http://tdistler.com/wp-content/uploads/2011/01/audio_waveform-150x150.jpg" alt="" width="150" height="150" /></a>Recently, I was tasked with picking an AAC audio codec library for one of our products. There were several libraries I had to evaluate, and I needed some quantitative metrics for doing the comparison. I&#8217;m not what professionals call an &#8220;expert listener&#8221;, so I had to do the best with what I had. While creating my test plan, I noticed that more people seemed interested in <em>how</em> I was doing testing rather than the actual results. So I decided to share my approach to audio codec testing.</p>
<p><strong>Note</strong>: <em>This is intended to be a pragmatic guide for engineers evaluating codecs. It is not a comprehensive treatment of the subject. The goal is to give readers a solid overview and some practical ideas</em>.</p>
<p><strong>Get Familiar with Psychoacoustics</strong></p>
<p><a title="Wikipedia: Psychoacoustics" href="http://en.wikipedia.org/wiki/Psychoacoustics" target="_blank">Psychoacoustics</a> is the study of how humans <em>perceive</em> sound. As you might expect, we humans don&#8217;t process sound in a perfect, linear fashion. The physical shape of the ear, the transfer function of the Basilar membrane, and the psychological interpretation of the data all affect how we perceive sound (and by extension, how &#8220;good&#8221; an audio codec sounds to us).</p>
<p>I highly recommend you start by reading this excerpt from <a title="EETimes: Psychoacoustics Part 1" href="http://www.eetimes.com/design/audio-design/4015872/Surround-Sound-Psychoacoustics--Part-1" target="_blank">Surround Sound: Psychoacoustics Part 1, by Tomlinson Holman</a> (he created <a title="Wikipedia: THX" href="http://en.wikipedia.org/wiki/THX" target="_blank">THX</a> for Lucasfilm).</p>
<p><strong>Understand the Codec</strong></p>
<p>Make sure you understand the codec you are testing; not necessarily the implementation, but what tools (i.e. methods) the codec uses for compression. Many codecs have different &#8220;profiles&#8221;, which describe what subset of available tools are used (e.g. <a title="MPEG-4 Part 3 Audio Preview" href="http://webstore.iec.ch/preview/info_isoiec14496-3%7Bed4.0%7Den.pdf" target="_blank">AAC</a>). You should also have some idea how each compression tool works and any short-comings it has. This will help guide you in selecting reference audio samples and knowing what artifacts to listen for.</p>
<p>For an introduction to modern audio compression, read <a title="EETimes: Audio Coding: An Introduction to Data Compression Part 1" href="http://www.eetimes.com/design/audio-design/4015827/Audio-Coding-An-Introduction-to-Data-Compression--Part-1" target="_blank">Audio Coding: An Introduction to Data Compression Part 1</a>, and <a title="EETimes: Audio Coding: An Introduction to Data Compression Part 2" href="http://www.eetimes.com/design/audio-design/4015828/Audio-Coding-An-Introduction-to-Data-Compression--Part-2" target="_blank">Part 2</a> (discusses MP3 and AAC). I actually suggest buying the book <a title="Amazon" href="http://www.amazon.com/Introduction-Compression-Kaufmann-Multimedia-Information/dp/012620862X/" target="_blank">&#8220;Introduction to Data Compression&#8221;</a>, by Khalid Sayood.</p>
<p><strong>Understand the API</strong></p>
<p>Make sure you actually read the codec documentation and look at any available code samples. This step has more to do with due-diligence than anything, as I haven&#8217;t seen a codec API we couldn&#8217;t work with, but you need to do this. This will also help you scope the work required to get a working encoder/decoder for future steps (if your lucky, the sample code can be used).</p>
<p><strong>Choose the Reference Audio Samples</strong></p>
<p>An effective test requires multiple audio samples with different characteristics. There are many types of artifacts a codec can introduce, and your choice of audio samples will dictate how easy they are to detect. It&#8217;s also important to pick samples that reflect the actual types of sound the codec to have to deal with. For example, if the final system will primarily be encoding speech, then you should choose more speech-oriented references as opposed to music samples.</p>
<p>Some characteristics you might consider:</p>
<ul>
<li><strong>Transients</strong> (snare drum): Sensitive to pre-echo and noise &#8220;smearing&#8221;.</li>
<li><strong>Tonal structure</strong> (clarinet, saxophone): Sensitive to noise and &#8220;roughness&#8221;.</li>
<li><strong>Natural speech</strong> (male and female voices of various languages): Sensitive to distortion and smearing of &#8220;attacks&#8221;.</li>
<li><strong>Complex sound</strong> (bag pipes): Stresses the codec.</li>
<li><strong>High bandwidth</strong> (bag pipes): Loss of high frequencies and program-modulated high frequency noise.</li>
</ul>
<p>It is also possible to use synthetic sounds and sweeps, but this is only recommended for the automated objective tests below.</p>
<p>As a basic guideline, you need 10-25 second &#8220;raw&#8221; samples recorded at the highest sample rate your system needs to work with. It is vital that the samples you choose have never been compressed with a lossy codec (mp3, AAC, etc)&#8230; that would severally limit the quality of your test. For sample rate and size, I suggest 48kHz 16-bit PCM, but a lower rate/size makes sense if the final system is limited in this area. It also makes sense to use a sample rate of 44.1kHz, since many quality audio samples can be ripped losslessly from CD. Just keep in mind that the objective PEAQ test mentioned below requires 48kHz 16-bit PCM, so up-sampling may be required.</p>
<p>The audio samples can be stored in whatever container format you want (raw, WAV, etc) as long as your codec test application can unpack it. This is important to keep in mind&#8230; <em>you don&#8217;t want to accidentally run the WAV header through the codec</em> (yes, I&#8217;ve done this). The container format is more of a practical issue, but it was worth mentioning.</p>
<p><strong>Generate Various Test Samples and Observe CPU Load</strong></p>
<p>This step is pretty straight-forward: wrap the codec in an application and encode the reference audio samples at different bit rates. You should choose bit rates that represent the full spectrum of bit rates that will be used in the final system. While you&#8217;re encoding, track the CPU usage on the codec and how many cores it&#8217;s using. You may even want to do a separate test running many encodes in parallel (this works nicely if the CPU usage is too low to measure accurately). Make sure to consider application overhead and disk I/O when making measurements.</p>
<p>After encoding, you need to decode back to raw PCM. Clearly label your files so you know what bit rate each one was encoded with. These decoded test samples are what we will be comparing to the original reference samples.</p>
<p><strong>Do a Subjective Test</strong></p>
<p>How you conduct your subjective testing will depend on several factors, such as time constraints, cost, and the required test precision. At the low end, you could simply listen to the test samples in a pair of headphones and judge the quality yourself. For a high precision test, you could do a full <a title="ITU BS.1116" href="http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1116-1-199710-I!!PDF-E.pdf" target="_blank">ITU BS.1116</a> test using &#8220;expert listeners&#8221; in a controlled environment. While these examples represent the extremes, there are many permutations that can give you the desired quality of results.</p>
<p>The most common subjective test is called a &#8220;double-blind triple-stimulus with hidden reference&#8221; test. The listener hears three samples (commonly labeled A, B, and C) for a period of 10 to 25 seconds. A is always the original reference sample. The next two samples, B and C, are randomly assigned either the test sample from the codec or the original reference sample played again (called the &#8220;hidden reference&#8221;). The listener must then rate the difference between B and A, and C and A, not knowing which one is the test sample. The grading scale is:</p>
<ul>
<li>5.0 Imperceptible</li>
<li>4.0 Perceptible, but not annoying</li>
<li>3.0 Slightly annoying</li>
<li>2.0 Annoying</li>
<li>1.0 Very annoying</li>
</ul>
<p>Ideally, you would conduct several tests and average the results together. If you do the listening test yourself, your results will be limited to your listening skills and understanding of audio codec artifacts. Here&#8217;s a summary of factors that affect the quality of your results:</p>
<ul>
<li>The quality of the listener.</li>
<li>The choice of audio samples.</li>
<li>The number and duration of the testing.</li>
<li>The testing environment, including speaker/headphone quality, room design, and listener placement.</li>
<li>The quality of randomization of sample order to remove any correlation between samples.</li>
<li>Proper statistical analysis of the combined test results.</li>
</ul>
<p>A proper subjective test is both expensive and time consuming. It&#8217;s important to find the right balance for your particular needs.</p>
<p><strong>Do an Objective Test</strong></p>
<p>Evaluating a codec objectively requires testing methods that correlate well to actual human perception. You can&#8217;t simply measure the distortion introduced by the codec using traditional measurements like Signal-to-Noise ratio (S/N) and  Total-Harmonic-Distortion (THD), because they don&#8217;t correlate well to perceived audio  quality. Some distortion is imperceptible to the human ear, and codecs take advantage of this to increase the compression ratio.</p>
<p>Fortunately, the <a title="Wikipedia: International Telecommunications Union" href="http://en.wikipedia.org/wiki/International_Telecommunication_Union" target="_blank">ITU</a> has standardized an objective audio test called <a title="Wikipedia: PEAQ" href="http://en.wikipedia.org/wiki/PEAQ" target="_blank">PEAQ</a> (<a title="ITU: Perceptual Evaluation of Audio Quality" href="http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1387-1-200111-I!!PDF-E.pdf" target="_blank">BS.1387</a>). The acronym stands for Perceptual Evaluation of Audio Quality. PEAQ uses software to model the entire human auditory system (including blood flow noise in the inner ear) to generate a set of metrics that are used to give a final &#8220;quality&#8221; score. The original reference signal is compared to a signal run through the codec, and the result is a real number between 0.0 and -4.0. The result is interpreted on the following scale:</p>
<ul>
<li> 0.0 = Imperceptible</li>
<li>-1.0 = Perceptible but not annoying</li>
<li>-2.0 = Slightly annoying</li>
<li>-3 .0= Annoying</li>
<li>-4.0 = Very annoying</li>
</ul>
<p>Obviously, values closer to zero are better.</p>
<p>The test was developed by a similar group of audio experts that developed BS.1116 (mentioned above) and the results have been validated against a long list of subjective tests done using expert listeners.</p>
<p>There are several free and commercial software packages available for doing PEAQ tests. The best free package I&#8217;ve found is <a title="McGill: AFsp PEAQ Software" href="http://www-mmsp.ece.mcgill.ca/Documents/Software/index.html" target="_blank">AFsp</a> from the McGill Telecommunications and Signal Processing Lab. There&#8217;s also <a title="Sourceforge: peaqb" href="http://sourceforge.net/projects/peaqb/" target="_blank">peaqb</a>, but there&#8217;s a comment that it gives incorrect results. AFsp worked great in my tests and included some helpful tools like <a title="AFsp: CompAudio" href="http://www-mmsp.ece.mcgill.ca/Documents/Software/Packages/AFsp/CompAudio.html" target="_blank">CompAudio</a> and <a title="AFsp: InfoAudio" href="http://www-mmsp.ece.mcgill.ca/Documents/Software/Packages/AFsp/InfoAudio.html" target="_blank">InfoAudio</a>.</p>
<p><strong>Summary</strong></p>
<p>Hopefully this post has given you a good starting point and some practical ideas for testing audio codecs. My goal was to provide a pragmatic approach with different options depending on what your actual evaluation needs are. This is in no way a comprehensive treatment of the subject; only an overview. I highly suggest reading some of the books I referenced if you&#8217;d like a deeper treatment of the subject. Either way, I hope you found this post helpful.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/01/25/how-to-test-an-audio-codec-a-practical-approach/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ffmpeg and Invalid Buffer Reads</title>
		<link>http://tdistler.com/2011/01/06/ffmpeg-and-invalid-buffer-reads</link>
		<comments>http://tdistler.com/2011/01/06/ffmpeg-and-invalid-buffer-reads#comments</comments>
		<pubDate>Fri, 07 Jan 2011 01:20:55 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=705</guid>
		<description><![CDATA[It always pays to read the documentation carefully. That&#8217;s the moral of this story, but I think the details are still worth reading. We&#8217;ve been using the LGPL build of Ffmpeg for a while now. However, every few months during testing the decoder will segfault. It&#8217;s always on some random box, in a release build, in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/07/ffmpeg_logo.jpg"><img class="alignright size-full wp-image-433" title="ffmpeg_logo" src="http://tdistler.com/wp-content/uploads/2010/07/ffmpeg_logo.jpg" alt="" width="150" height="37" /></a>It always pays to read the documentation carefully. That&#8217;s the moral of this story, but I think the details are still worth reading.</p>
<p>We&#8217;ve been using the LGPL build of <a title="Ffmpeg" href="http://ffmpeg.org/" target="_blank">Ffmpeg</a> for a while now. However, every few months during testing the decoder will segfault. It&#8217;s always on some random box, in a release build, in the middle of the night, and nobody can reproduce it (sound typical?). Well, I think I fixed the problem today and I wanted to share what I found.</p>
<p>I ran our decoder through <a title="Valgrind" href="http://valgrind.org" target="_blank">Valgrind</a> while playing an H.264 stream and noticed several errors like the following:<br />
<code><br />
==6757== Invalid read of size 4<br />
==6757==    at 0x4D92C50: ff_h264_decode_nal (in/usr/local/pelco/lib/libavcodec.so.52.59.0)<br />
</code></p>
<p>Hum&#8230; strange. MPEG-4 doesn&#8217;t have this problem.</p>
<p>After triple-checking all our buffer size calculations, <code>memcpy</code> lengths, buffer-overrun checks, etc I was at a loss to explain this. I even added an arbitrary 4 bytes to every allocation but still ran into problems. I finally decided to go line-by-line through our decoder source, cross-referencing with the <a title="avcodec" href="http://en.wikipedia.org/wiki/Libavcodec" target="_blank">avcodec</a> documentation.</p>
<p><strong>Found it!</strong></p>
<p>Looking at the documentation for <code>avcodec_decode_video2(...)</code>, I found the following note:</p>
<blockquote><p>Warning:<br />
The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than the actual read bytes because some optimized bitstream readers read 32 or 64 bits at once and could <strong>read over the end</strong>. The end of the input buffer buf should be set to 0 to ensure that no overreading happens for damaged MPEG streams.</p>
<p>Note:<br />
You might have to align the input buffer avpkt-&gt;data. The alignment requirements depend on the CPU: on some CPUs it isn&#8217;t necessary at all, on others it won&#8217;t work at all if not aligned and on others it will work but it will have an impact on performance.<br />
In practice, avpkt-&gt;data should have 4 byte alignment at minimum.</p></blockquote>
<p>This must have been overlooked when the decoder was written&#8230; oops!</p>
<p><strong>Solution</strong></p>
<p>I ended up adding alignment and padding parameters to our buffer objects, which (internally) uses the following methods for allocation:</p>
<p>Windows: <code>_aligned_malloc()</code>, <code>_aligned_free()</code> (requires <code>malloc.h</code>)<br />
Linux: <code>posix_memalign()</code>, <code>free()</code> (requires <code>stdlib.h</code>)</p>
<p>I mention these methods because I think they&#8217;re pretty handy and not everyone knows about them. However, don&#8217;t forget to read the documentation before using them!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/01/06/ffmpeg-and-invalid-buffer-reads/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CPU Profiling on Windows: Very Sleepy</title>
		<link>http://tdistler.com/2010/12/21/cpu-profiling-on-windows-very-sleepy</link>
		<comments>http://tdistler.com/2010/12/21/cpu-profiling-on-windows-very-sleepy#comments</comments>
		<pubDate>Tue, 21 Dec 2010 19:59:04 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=697</guid>
		<description><![CDATA[A colleague of mine found a pretty cool profiling tool for Windows called Very Sleepy. It&#8217;s simple, straight-forward, free, and it works&#8230; everything I like in a tool (this is why I like the Sysinternals stuff so much). It&#8217;s also got call-graph and 64-bit support. Definitely worth checking out.]]></description>
			<content:encoded><![CDATA[<p>A colleague of mine found a pretty cool profiling tool for Windows called <a title="Coders Notes: Very Sleepy" href="http://www.codersnotes.com/sleepy" target="_blank">Very Sleepy</a>. It&#8217;s simple, straight-forward, free, and it works&#8230; everything I like in a tool (this is why I like the <a title="Mircosoft Sysinternals" href="http://www.sysinternals.com" target="_blank">Sysinternals</a> stuff so much). It&#8217;s also got call-graph and 64-bit support. Definitely worth checking out.</p>
<p><a href="http://tdistler.com/wp-content/uploads/2011/01/very_sleepy_screenshot.jpg"><img class="aligncenter size-medium wp-image-698" title="very_sleepy_screenshot" src="http://tdistler.com/wp-content/uploads/2011/01/very_sleepy_screenshot-300x218.jpg" alt="Very Sleep Screen Shot" width="300" height="218" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/12/21/cpu-profiling-on-windows-very-sleepy/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ILM and GPU Programming</title>
		<link>http://tdistler.com/2010/10/07/ilm-and-gpu-programming</link>
		<comments>http://tdistler.com/2010/10/07/ilm-and-gpu-programming#comments</comments>
		<pubDate>Thu, 07 Oct 2010 16:15:49 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=503</guid>
		<description><![CDATA[Some artists from Industrial Light &#38; Magic (ILM) gave the closing keynote at the GPU Technology Conference (GTC) in 2009&#8230; it&#8217; s well worth watching by itself (watch here). At GTC 2010, they presented a video talking about how the GPU and CUDA are helping to render effects faster. It&#8217;s a short video with lots [...]]]></description>
			<content:encoded><![CDATA[<p>Some artists from <a title="Industrial Light and Magic" href="http://www.ilm.com/" target="_blank">Industrial Light &amp; Magic</a> (ILM) gave the closing keynote at the <a title="GPU Technology Conference" href="http://www.nvidia.com/object/gpu_technology_conference.html" target="_blank">GPU Technology Conference</a> (GTC) in 2009&#8230; it&#8217; s well worth watching by itself (<a title="ILM Keynote at GTC 2009" href="http://us.download.nvidia.com/downloads/GTC%20videos/Day3%20Keynote/1200_nv_keynote_091002.mp4" target="_blank">watch here</a>). At GTC 2010, they presented a video talking about how the GPU and CUDA are helping to render effects faster. It&#8217;s a short video with lots of cool effects.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube-nocookie.com/v/8ZIL98Uhhcg?fs=1&amp;hl=en_US&amp;rel=0" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="385" src="http://www.youtube-nocookie.com/v/8ZIL98Uhhcg?fs=1&amp;hl=en_US&amp;rel=0" allowscriptaccess="always" allowfullscreen="true"></embed></object>ct&gt;</p>
<p><a title="ILM Promo GTC 2010" href="http://www.tdistler.com/media/videos/GTC_2010_ILM.3gp">Here&#8217;s</a> a copy of the video if it is ever removed (13MB, 3gp).</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/10/07/ilm-and-gpu-programming/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://us.download.nvidia.com/downloads/GTC%20videos/Day3%20Keynote/1200_nv_keynote_091002.mp4" length="504306567" type="video/mp4" />
		</item>
		<item>
		<title>Lua Quick Reference Sheet</title>
		<link>http://tdistler.com/2010/09/27/lua-quick-reference-sheet</link>
		<comments>http://tdistler.com/2010/09/27/lua-quick-reference-sheet#comments</comments>
		<pubDate>Mon, 27 Sep 2010 19:26:15 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=485</guid>
		<description><![CDATA[Here&#8217;s a nice 4 page reference for Lua 5.1. It was created by Thomas Lauer and can be downloaded from his website. I&#8217;ve reposted it here just-in-case&#8230; I&#8217;ve been bitten before. Lua Reference Card (PDF)]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/09/lua_logo1.gif"><img class="alignright size-full wp-image-489" title="lua_logo" src="http://tdistler.com/wp-content/uploads/2010/09/lua_logo1-e1285616733640.gif" alt="" width="100" height="99" /></a>Here&#8217;s a nice 4 page reference for Lua 5.1. It was created by <a title="Thomas Lauer" href="http://thomaslauer.com/" target="_blank">Thomas Lauer</a> and can be downloaded from his <a title="Lua Short Reference" href="http://thomaslauer.com/comp/Lua_Short_Reference" target="_blank">website</a>. I&#8217;ve reposted it here just-in-case&#8230; I&#8217;ve been bitten before.</p>
<p><a title="Lua Short Reference PDF" href="http://www.tdistler.com/media/docs/luarefv51.pdf">Lua Reference Card (PDF)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/09/27/lua-quick-reference-sheet/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>C++ Enums in Lua</title>
		<link>http://tdistler.com/2010/09/13/c-enums-in-lua</link>
		<comments>http://tdistler.com/2010/09/13/c-enums-in-lua#comments</comments>
		<pubDate>Mon, 13 Sep 2010 15:28:42 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=460</guid>
		<description><![CDATA[I&#8217;ve been working lately on embedding Lua 5.1.4 into a C++ application. I&#8217;m really impressed with Lua, and most things are pretty straight-forward. However, when it comes to mapping typed enumerations into Lua, I just haven&#8217;t found an easy way to do it. For example, let&#8217;s say you want to expose a C++ function into [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/09/lua_logo.gif"><img class="alignright size-thumbnail wp-image-462" title="lua_logo" src="http://tdistler.com/wp-content/uploads/2010/09/lua_logo-150x150.gif" alt="Lua" width="150" height="150" /></a>I&#8217;ve been working lately on embedding <a title="Lua Programming Language" href="http://www.lua.org/" target="_blank">Lua 5.1.4</a> into a C++ application. I&#8217;m really impressed with Lua, and most things are pretty straight-forward. However, when it comes to mapping typed enumerations into Lua, I just haven&#8217;t found an easy way to do it. For example, let&#8217;s say you want to expose a C++ function into Lua called <code>create()</code>, which takes an enumerated type as a parameter. In C++ this would look like:</p>
<pre><code>typedef enum _TYPE {
    TYPE_FOO = 0,
    TYPE_BAR,
    TYPE_BAZ,
    TYPE_MAX
} TYPE;

bool create(const TYPE type);</code></pre>
<p>To me, it makes the most sense to call <code>create()</code> from Lua with syntax like:</p>
<p><code>&gt; create(type.foo)</code></p>
<p>Ideally, we&#8217;d also like the following:</p>
<ol>
<li>The enumeration is const, and can&#8217;t be altered from Lua code.</li>
<li>The C++ implementation of <code>create()</code> could validate the type passed to it is the expected type.</li>
</ol>
<p>Unfortunately, this isn&#8217;t as straight-forward as everything else I&#8217;ve done with Lua.</p>
<h4>Solution (i.e. cut-to-the-chase and explain later)</h4>
<p>Okay, I&#8217;m a practical guy&#8230; download <strong><a title="lua_typed_enums.h Header File" href="/media/code/lua_typed_enums.h">lua_typed_enums.h</a></strong> and include it in your code. Then you can add the enums shown above to Lua by calling <code>add_enum_to_lua()</code>:</p>
<pre><code>add_enum_to_lua( L, "type",
    "foo", TYPE_FOO,
    "bar", TYPE_BAR,
    "baz", TYPE_BAZ,
    0 );</code></pre>
<p>Your enums are now available in Lua as:</p>
<p><code>type.foo<br />
type.bar<br />
type.baz</code></p>
<p>Now, your C++ code that takes TYPE as an input and returns a boolean would be written as follows:</p>
<pre><code>static int lua_create( lua_State *L )
{
    if( !check_enum_type( L, "type", -1 ) ) {
        /* error */
    }

    int value = get_enum_value( L, -1 );

    /* do something cool */

    lua_pushboolean( L, 1 );
    return (1);
}</code></pre>
<p>You can now call your <code>create()</code> method from Lua how we wanted:</p>
<p><code>&gt; create(type.bar)</code></p>
<p>Look at the comments in the header file if you want more info about using <code>add_enum_to_lua()</code>, <code>check_enum_type()</code>, and <code>get_enum_value()</code>.</p>
<h4>How it Works</h4>
<p>There&#8217;s no direct way to map the expected behavior of C-enums into Lua (const-ness with typing). What I did was to create a read-only Lua table representing the enumerated type and then make each value in that table have a defined type.</p>
<p>Let&#8217;s deal with the first task: making a read-only table. This is pretty well documented on the web, but I&#8217;ve included a drawing below that would have helped me a lot in the beginning. Let&#8217;s assume we want to represent our enum as a Lua table. We could visualize it as follows:</p>
<p><a href="http://tdistler.com/wp-content/uploads/2010/09/lua_rotables_unprotected.jpg"><img class="aligncenter size-full wp-image-472" title="lua_rotables_unprotected" src="http://tdistler.com/wp-content/uploads/2010/09/lua_rotables_unprotected.jpg" alt="" width="169" height="97" /></a></p>
<p>We could still use the <code>type.foo</code> syntax with this table, but a user could assign a new value to the enum like:</p>
<p><code>&gt; type.foo = 9</code></p>
<p>To prevent this, we need to deny write access to the table. The trick to doing this is to use a metatable and set the <code>__index</code> and <code>__newindex</code> values.</p>
<p><a href="http://tdistler.com/wp-content/uploads/2010/09/lua_rotables_untyped.jpg"><img class="aligncenter size-full wp-image-473" title="lua_rotables_untyped" src="http://tdistler.com/wp-content/uploads/2010/09/lua_rotables_untyped.jpg" alt="" width="361" height="145" /></a></p>
<p>So how does this work? When the user reads a value from the table (i.e. by using <code>type.foo</code>), Lua fails to find &#8220;foo&#8221; in the table. So it looks in the metatable for the <code>__index</code> key. If that is set to point to a table, then it will try to lookup the value in that table. In the case above, it finds the &#8220;foo&#8221; value and returns it like normal. However, if the user attempts to assign to type.foo, Lua follows the <code>__newindex</code> path, which causes a function to get called that does nothing but print an error&#8230; effectively, the write is denied. Here&#8217;s what happens:</p>
<p><code>&gt; type.foo = 9<br />
[string "?"]:1: Attempt to modify read-only table</code></p>
<p>Okay, cool&#8230; we&#8217;ve made read-only enumerations, but what about typing. Glad you asked! We add one more layer of abstraction, of course &lt;groaning&gt;:</p>
<p><a href="http://tdistler.com/wp-content/uploads/2010/09/lua_rotables_typed1.jpg"><img class="aligncenter size-full wp-image-475" title="lua_rotables_typed" src="http://tdistler.com/wp-content/uploads/2010/09/lua_rotables_typed1.jpg" alt="" width="553" height="181" /></a></p>
<p>Basically, we make each value a table that includes the <em>actual</em> value and a type (&#8220;type&#8221; in our example above). The <code>check_enum_type()</code> function looks at the &#8220;type&#8221; field in the table to make sure the correct type was passed to your function. The <code>get_enum_value()</code> function gets the &#8220;value&#8221; field&#8230; which is equal to the actual C-enum type you&#8217;d expect. From the Lua side, you can inspect the enums like:</p>
<p><code>&gt; print(type.foo.value)<br />
0<br />
&gt; print(type.foo.type)<br />
type</code></p>
<p>Explicitly, &#8220;type&#8221; is a read-only table with value &#8220;foo&#8221;. The value of &#8220;foo&#8221; is the table <code>{ value=0, type="type" }</code>. I hope this explanation helps. Obviously, I&#8217;ve been geeking out on Lua a little too much lately <img src='http://tdistler.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/09/13/c-enums-in-lua/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux: Parsing IP Address, MAC, and Gateway</title>
		<link>http://tdistler.com/2010/08/17/linux-parsing-ip-address-mac-and-gateway</link>
		<comments>http://tdistler.com/2010/08/17/linux-parsing-ip-address-mac-and-gateway#comments</comments>
		<pubDate>Tue, 17 Aug 2010 18:28:33 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=453</guid>
		<description><![CDATA[Yesterday, I needed to get my server&#8217;s network information for a Bash script I was writing. Here are the commands so I don&#8217;t forget. They were tested using Fedora 12. Get IP address: ifconfig eth0 &#124; awk '/inet / {print $2}' &#124; awk -F: '{print $2}&#8216; Get MAC address: ifconfig eth0 &#124; awk '/HWaddr/ {print [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2010/08/bash_cmd_prompt.jpg"><img class="alignright size-full wp-image-455" title="bash_cmd_prompt" src="http://tdistler.com/wp-content/uploads/2010/08/bash_cmd_prompt.jpg" alt="" width="102" height="102" /></a>Yesterday, I needed to get my server&#8217;s network information for a Bash script I was writing. Here are the commands so I don&#8217;t forget. They were tested using <a title="Fedora Linux" href="http://fedoraproject.org/" target="_blank">Fedora</a> 12.</p>
<p>Get IP address:<br />
<code>ifconfig eth0 | awk '/inet / {print $2}' | awk -F: '{print $2}</code>&#8216;</p>
<p>Get MAC address:<br />
<code>ifconfig eth0 | awk '/HWaddr/ {print $5}'</code></p>
<p>Get network gateway IP address:<br />
<code>route -n | awk '/^0.0.0.0/ {print $2}'</code></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2010/08/17/linux-parsing-ip-address-mac-and-gateway/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

