<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>valeriu.palos.ro</title>
	
	<link>http://valeriu.palos.ro</link>
	<description>...milk, cookies and segmentation faults.</description>
	<lastBuildDate>Thu, 02 Sep 2010 16:57:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/valeriu" /><feedburner:info uri="valeriu" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Case study: fixed number of iterations with LPeg</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/F2gdzH930ZA/</link>
		<comments>http://valeriu.palos.ro/755/case-study-fixed-number-of-iterations-with-lpeg/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 15:49:02 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Dynamic scripting]]></category>
		<category><![CDATA[Research]]></category>
		<category><![CDATA[action message format]]></category>
		<category><![CDATA[actionscript3]]></category>
		<category><![CDATA[amf]]></category>
		<category><![CDATA[amf0]]></category>
		<category><![CDATA[amf3]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[iterations]]></category>
		<category><![CDATA[lpeg]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[match]]></category>
		<category><![CDATA[occurrences]]></category>
		<category><![CDATA[pcre]]></category>
		<category><![CDATA[regular expressions]]></category>
		<category><![CDATA[repeat]]></category>
		<category><![CDATA[repetitions]]></category>
		<category><![CDATA[strict repetitions]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=755</guid>
		<description><![CDATA[Words fail me to describe just how awesome LPeg is. Designed as a Lua implementation of the PEG concept, it is a true programming gem! Please, if you dont&#8217;t know what it is, take some time to familiarize yourself with it! It&#8217;s not the easiest thing to grasp, but you will *not* regret it! It [...]]]></description>
			<content:encoded><![CDATA[<p>Words fail me to describe just how awesome <a href="http://www.inf.puc-rio.br/~roberto/lpeg/" target="_blank">LPeg</a> is. Designed as a Lua implementation of the <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar" target="_blank">PEG</a> concept, it is a true programming gem! Please, if you dont&#8217;t know what it is, take some time to familiarize yourself with it! It&#8217;s not the easiest thing to grasp, but you will *not* regret it! It is certainly one of the most worthwhile learning efforts you can make in generic programming.</p>
<p>One great feature of LPeg is that it&#8217;s<em> binary-safe</em>, meaning that (unlike regular expressions) it can be <em>safely</em> used to parse <em>binary data</em>! This makes it an excellent tool for parsing binary protocols, especially network communication protocols, such as the <a href="http://en.wikipedia.org/wiki/Action_Message_Format" target="_blank">Action Message Format</a> (used by Adobe Flash for making remote calls and even in FLV movie files). I&#8217;ll leave it to you to explore the possibilities&#8230;</p>
<p>Beware that from here on, I assume that you know your way around Lua, LPeg and how they work.</p>
<h3><span style="color: #ff0000;">The problem</span></h3>
<p>That being said, this article is actually about an unusual roadblock I hit while using LPeg to build a Lua-based AMF parser, and the various solutions I found and/or came up with to overcome it (you didn&#8217;t think that I mentioned AMF before by accident, did you?).</p>
<p>The issue is <span style="color: #0000ff;">LPeg&#8217;s implementation of repetitive patterns: in particular, its inability to match (or capture) <strong>a fixed number of occurrences</strong> of a certain pattern</span>, although it can match a minimum or a maximum number of such occurrences, which is perfect for stream-oriented parsing (such as parsing programming languages) but insufficient for binary data.</p>
<p>Just to clarify, here&#8217;s a small list of LPeg patterns which correspond to the typical <a href="http://www.pcre.org/" target="_blank">PCRE</a> repetitive constructs (in each case we&#8217;re trying to match the string &#8216;cloth&#8217;):</p>
<table style="white-space: nowrap; border: 2px solid #ccc;" cellspacing="1">
<tbody>
<tr>
<td style="background: #444; color: #fff; padding: 0px 5px;">Nr.</td>
<td style="background: #444; color: #fff; padding: 0px 5px;">Matching occurrences of &#8216;cloth&#8217;</td>
<td style="background: #444; color: #fff; padding: 0px 5px;">PCRE pattern</td>
<td style="background: #444; color: #fff; padding: 0px 5px;">LPeg pattern</td>
</tr>
<tr>
<td style="padding: 0px 5px;">1</td>
<td style="padding: 0px 5px;">0 or more (at least 0)</td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth)*/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #ff0000;">'cloth'</span>^<span style="color: #cc66cc;">0</span></span></code></td>
</tr>
<tr>
<td style="padding: 0px 5px;">2</td>
<td style="padding: 0px 5px;">1 or more (at least 1)</td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth)+/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #ff0000;">'cloth'</span>^<span style="color: #cc66cc;">1</span></span></code></td>
</tr>
<tr>
<td style="padding: 0px 5px;">3</td>
<td style="padding: 0px 5px;"><strong><em>X</em></strong> or more (at least <strong><em>X</em></strong>)</td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth){X,}/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #ff0000;">'cloth'</span>^X</span></code></td>
</tr>
<tr>
<td style="padding: 0px 5px;">4</td>
<td style="padding: 0px 5px;">1 or less (at most 1)</td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth)?/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #ff0000;">'cloth'</span>^-<span style="color: #cc66cc;">1</span></span></code></td>
</tr>
<tr>
<td style="padding: 0px 5px;">5</td>
<td style="padding: 0px 5px;"><strong><em>X</em></strong> or less (at most <strong><em>X</em></strong>)</td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth){,X}/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #ff0000;">'cloth'</span>^-X</span></code></td>
</tr>
<tr>
<td style="padding: 0px 5px;">6</td>
<td style="padding: 0px 5px;"><span style="color: #ff0000;">precisely </span><strong><em><span style="color: #ff0000;">X</span></em></strong><span style="color: #ff0000;"> (no more, no less)</span></td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth){X,X}/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua"><span style="color: #808080; font-style: italic;">-- not implemented --</span></span></code></td>
</tr>
<tr>
<td style="padding: 0px 5px;">7</td>
<td style="padding: 0px 5px;"><span style="color: #ff0000;">anywhere between </span><strong><em><span style="color: #ff0000;">X</span></em></strong><span style="color: #ff0000;"> and </span><strong><em><span style="color: #ff0000;">Y</span></em></strong></td>
<td style="padding: 0px 5px;"><code class="codecolorer text mac-classic"><span class="text">/(cloth){X,Y}/</span></code></td>
<td style="padding: 0px 5px;"><code class="codecolorer lua mac-classic"><span class="lua"><span style="color: #808080; font-style: italic;">-- not implemented --</span></span></code></td>
</tr>
</tbody>
</table>
<p><span style="font-weight: normal;">For cases 6 and 7, LPeg does not offer any simple constructs so we have to find a complex one. But let&#8217;s put case 7 aside for a while, and try to tackle case 6, then we&#8217;ll see&#8230;</span><span id="more-755"></span></p>
<h4><span style="color: #ff0000;">Attempt 1 (brute force)</span></h4>
<p>The first solution was rather straight-forward: we explicitly compose (i.e. append) a pattern for every occurrence we need to match. I call this the <em>brute force</em> method (for obvious reasons). For example, to match the word &#8216;cloth&#8217; exactly three times we would use the pattern <code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #ff0000;">'cloth'</span> <span style="color: #66cc66;">*</span> lpeg.P<span style="color: #ff0000;">'cloth'</span> <span style="color: #66cc66;">*</span> lpeg.P<span style="color: #ff0000;">'cloth'</span></span></code>.</p>
<p>Naturally, this is quite inflexible: what if we need to match 183 occurrences? To achieve that, we use a pattern generation function. Here&#8217;s a complete working example:</p>
<div class="codecolorer-container lua mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="lua codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">local</span> lpeg <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">require</span><span style="color: #ff0000;">'lpeg'</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- Version 1.</span><br />
<span style="color: #808080; font-style: italic;">-- Generates a big pattern where every interation has </span><br />
<span style="color: #808080; font-style: italic;">-- a corresponding instance of the initial pattern. The</span><br />
<span style="color: #808080; font-style: italic;">-- resulting pattern captures all occurrences in a table.</span><br />
<span style="color: #b1b100;">function</span> multiply_1<span style="color: #66cc66;">&#40;</span>item, count<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">local</span> set <span style="color: #66cc66;">=</span> lpeg.P<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">true</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span> count <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #b1b100;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; set <span style="color: #66cc66;">=</span> set <span style="color: #66cc66;">*</span> item<br />
&nbsp; &nbsp; &nbsp; &nbsp; count <span style="color: #66cc66;">=</span> count - <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> lpeg.Ct<span style="color: #66cc66;">&#40;</span>set<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #b1b100;">end</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- Generate subject ('cloth,cloth,...').</span><br />
<span style="color: #b1b100;">local</span> subject <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">string.rep</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'cloth,'</span>, <span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- A capture of the word 'cloth' optionally followed by a comma.</span><br />
<span style="color: #b1b100;">local</span> item <span style="color: #66cc66;">=</span> lpeg.C<span style="color: #66cc66;">&#40;</span>lpeg.P<span style="color: #ff0000;">'cloth'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> lpeg.P<span style="color: #ff0000;">','</span>^-<span style="color: #cc66cc;">1</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- Match exactly 10 items.</span><br />
<span style="color: #b1b100;">local</span> result <span style="color: #66cc66;">=</span> lpeg.match<span style="color: #66cc66;">&#40;</span>multiply_1<span style="color: #66cc66;">&#40;</span>item, <span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span>, subject<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- Display capture table.</span><br />
<span style="color: #b1b100;">print</span><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">unpack</span><span style="color: #66cc66;">&#40;</span>result<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
<p>This function adds a composition operation to the big pattern for each occurrence. One method of improving this is to reduce the amount of compositions to the a bare minimum. We do this by duplicating (i.e. growing in powers of 2) the pattern until the required size is reached (also used by LPeg&#8217;s <a href="http://www.inf.puc-rio.br/~roberto/lpeg/re.html" target="_blank">regexp emulator</a>):</p>
<div class="codecolorer-container lua mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="lua codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- Version 1(b).</span><br />
<span style="color: #808080; font-style: italic;">-- Generates a (potentially large) pattern using only</span><br />
<span style="color: #808080; font-style: italic;">-- the minimum possible amount of compositions. </span><br />
<span style="color: #b1b100;">function</span> multiply_1b<span style="color: #66cc66;">&#40;</span>item, count<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">local</span> set <span style="color: #66cc66;">=</span> lpeg.P<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">true</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span> count <span style="color: #66cc66;">&gt;=</span> <span style="color: #cc66cc;">1</span> <span style="color: #b1b100;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> count <span style="color: #66cc66;">%</span> <span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">&gt;=</span> <span style="color: #cc66cc;">1</span> <span style="color: #b1b100;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set <span style="color: #66cc66;">=</span> set <span style="color: #66cc66;">*</span> item<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; item <span style="color: #66cc66;">=</span> item <span style="color: #66cc66;">*</span> item<br />
&nbsp; &nbsp; &nbsp; &nbsp; count <span style="color: #66cc66;">=</span> count <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> lpeg.Ct<span style="color: #66cc66;">&#40;</span>set<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #b1b100;">end</span></div></td></tr></tbody></table></div>
<p>Looks good, however,  this method presents a serious problem:<strong> the resulting pattern can get very large</strong>, forcing the limits of the Lua stack. It works well enough for small jobs, but <strong>it is unwise to generate more than a few hundred repetitions using this method (and even that may be pushing it).</strong> This means that the brute force method is unusable for heavy binary parsing, <strong>where we would often need to match even thousands of pattern repetitions</strong>.</p>
<p>We need to do better&#8230;</p>
<h4><span style="color: #ff0000;">Attempt 2 (capture folding)</span></h4>
<p>The next approach is a bit more complex and makes use of the more advanced features of LPeg: the <a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html#cap-f">lpeg.Cf()</a> and <a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html#matchtime">lpeg.Cmt()</a> captures.</p>
<p>In essence, we match <em>at most</em> the desired number of occurrences (using the <code class="codecolorer lua mac-classic"><span class="lua">^-N</span></code> operation described in the table at the top) and on every match (i.e. iteration) we execute a folding function (via <code class="codecolorer lua mac-classic"><span class="lua">lpeg.Cf<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></span></code>) that adds the item to the result table and also decreases a counter. At the end, we execute a checking function (via <code class="codecolorer lua mac-classic"><span class="lua">lpeg.Cmt<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></span></code>) which will test if the counter reached 0 (thus ensuring exact matching) and will fail if not.</p>
<div class="codecolorer-container lua mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="lua codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- Version 2.</span><br />
<span style="color: #808080; font-style: italic;">-- Somewhat better approach, which starts with an empty table and gradually</span><br />
<span style="color: #808080; font-style: italic;">-- folds every occurring capture of the initial pattern into this table, at</span><br />
<span style="color: #808080; font-style: italic;">-- the same time decrementing the counter. Eventually, it also checks if the</span><br />
<span style="color: #808080; font-style: italic;">-- counter reached 0 and fails otherwise.</span><br />
<span style="color: #b1b100;">function</span> multiply_2<span style="color: #66cc66;">&#40;</span>item, count<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> lpeg.Cmt<span style="color: #66cc66;">&#40;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">-- Fold capture.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lpeg.Cf<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lpeg.Ct<span style="color: #ff0000;">''</span> <span style="color: #66cc66;">*</span> item^-count,<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">-- Append capture.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span>set, item<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;count <span style="color: #66cc66;">=</span> count - <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">table.insert</span><span style="color: #66cc66;">&#40;</span>set, item<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> set<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><span style="color: #66cc66;">&#41;</span>,<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">-- Final check.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span>s, i, set<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> count <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #b1b100;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> <span style="color: #b1b100;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> i, set<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #b1b100;">end</span></div></td></tr></tbody></table></div>
<p>Note that the capture starts with an empty table created from the empty string (i.e. <code class="codecolorer lua mac-classic"><span class="lua">lpeg.Ct<span style="color: #ff0000;">''</span></span></code>). This table is the first parameter given to the folding function (i.e. <code class="codecolorer lua mac-classic"><span class="lua">set</span></code>); after all the iterations, it will contain all captured items and will then be given to the check-up function for evaluation. Eventually, if all goes well, it will be returned back as the final result of multiply().</p>
<p>Overall this method will behave much better than the first; the generated pattern is much more elegant. However, <strong>the generated pattern can still grow quite large in memory</strong>, even though it&#8217;s not that obvious (i.e. I was surprised to find that it also crashed when generating more than a few thousand iterations).</p>
<p>The issue is the <code class="codecolorer lua mac-classic"><span class="lua">item^-count</span></code> bit. Checking the C code of the LPeg implementation, quickly reveals that whenever <code class="codecolorer lua mac-classic"><span class="lua">count</span></code> is not <code class="codecolorer lua mac-classic"><span class="lua"><span style="color: #cc66cc;">0</span></span></code> (i.e. which is a special case), the engine is forced to allocate <code class="codecolorer lua mac-classic"><span class="lua">count</span></code> objects in memory, and while these objects are lighter than a complete item pattern (as in the first solution) <strong>they are still scaling-up the problem badly</strong>!</p>
<p>Eventually, this method only allows generating repetitive patterns of a few thousand iterations (that is as far as I was able to push it). But, what if we need to handle a rogue pattern of 35 000 occurrences? What then? No!&#8230; we still need better!</p>
<h4><span style="color: #ff0000;">Attempt 3 (classic loop)</span></h4>
<p>The only thing left to try is a (slightly) more rudimentary technique. Basically, it is the same as the second approach but with a significant modification: instead of using <code class="codecolorer lua mac-classic"><span class="lua">lpeg.Cf<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></span></code> to &#8220;accumulate&#8221; (i.e. fold) every occurrence of item to the result table, we just use a straight-forward loop that will advance through the input stream at every iteration.</p>
<p>That makes the pattern completely dynamic, i.e. totally non-proportional to the number of matched occurrences. As a result, this method allows for an unlimited number of iterations with no memory wastes.</p>
<div class="codecolorer-container lua mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="lua codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- Version 3.</span><br />
<span style="color: #808080; font-style: italic;">-- Best method so far, capable of an unlimited number of iterations. It uses</span><br />
<span style="color: #808080; font-style: italic;">-- an explicit loop to walk over all all iterations at match-time, so there</span><br />
<span style="color: #808080; font-style: italic;">-- is no potentially huge pattern ever created. This method simply populates</span><br />
<span style="color: #808080; font-style: italic;">-- the result table at each iteration, or fails the entire set if the count</span><br />
<span style="color: #808080; font-style: italic;">-- is not reached precisely.</span><br />
<span style="color: #b1b100;">function</span> multiply_3<span style="color: #66cc66;">&#40;</span>item, count<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> lpeg.Cmt<span style="color: #66cc66;">&#40;</span>lpeg.P<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">true</span><span style="color: #66cc66;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span>s, i<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">local</span> set, offset <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>, i<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">for</span> j <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>, count <span style="color: #b1b100;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set<span style="color: #66cc66;">&#91;</span>j<span style="color: #66cc66;">&#93;</span>, offset <span style="color: #66cc66;">=</span> lpeg.match<span style="color: #66cc66;">&#40;</span>item <span style="color: #66cc66;">*</span> lpeg.Cp<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, s, offset<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #b1b100;">not</span> offset <span style="color: #b1b100;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> <span style="color: #b1b100;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> offset, set<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #b1b100;">end</span></div></td></tr></tbody></table></div>
<p>When applied to a string, this will start matching at the current position (i.e. due to the <code class="codecolorer lua mac-classic"><span class="lua">lpeg.P<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">true</span><span style="color: #66cc66;">&#41;</span></span></code> construct). The <code class="codecolorer lua mac-classic"><span class="lua">lpeg.Cmt<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></span></code> capture will trigger the iteration function immediately and there, in turn, will loop for &#8216;count&#8217; number of times, matching the item at every iteration and appending it to the results table. At the same time, at each iteration, the offset is advanced by capturing the position immediately following the matched item (i.e. the <code class="codecolorer lua mac-classic"><span class="lua">lpeg.Cp<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></span></code> construct). If anything goes wrong, then the entire match fails (i.e. via <code class="codecolorer lua mac-classic"><span class="lua"><span style="color: #b1b100;">return</span> <span style="color: #b1b100;">false</span></span></code>).</p>
<p>This method works flawlessly (as far as I could tell). The generated pattern is minimal (memory-wise), the source code is very small, and the function is overall very fast (only slightly slower than the first two approaches, when matching small-sized patterns). But most importantly, with this version, matching huge numbers of item repetitions is trivial (e.g. tens of thousands, millions&#8230;).</p>
<h4><span style="color: #ff0000;">Intervals</span></h4>
<p>From here, implementing case 7 (i.e. <code class="codecolorer lua mac-classic"><span class="lua">multiply<span style="color: #66cc66;">&#40;</span>X, Y<span style="color: #66cc66;">&#41;</span></span></code>) is quite easy&#8230;</p>
<p>One approach would be to use <code class="codecolorer lua mac-classic"><span class="lua">multiply_3<span style="color: #66cc66;">&#40;</span>item, X<span style="color: #66cc66;">&#41;</span></span></code> to ensure the minimum number of occurrences (i.e. <strong><em>X</em></strong>) and then append the pattern <code class="codecolorer lua mac-classic"><span class="lua">item^-<span style="color: #66cc66;">&#40;</span>Y-X<span style="color: #66cc66;">&#41;</span></span></code> which will optionally match the remaining occurrences up to the maximum amount allowed. This method will work, and can also be used with the first two solutions, but will still (potentially) waste memory when <code class="codecolorer lua mac-classic"><span class="lua"><span style="color: #66cc66;">&#40;</span>Y-X<span style="color: #66cc66;">&#41;</span></span></code> is large.</p>
<p>A better (and still easy) approach would be to modify the loop inside <code class="codecolorer lua mac-classic"><span class="lua">multiply_3<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></span></code> to also accept an optional number of iterations (above the minimum). Here&#8217;s how&#8230;</p>
<div class="codecolorer-container lua mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="lua codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- Version 3(b).</span><br />
<span style="color: #808080; font-style: italic;">-- The final variant with support for interval matching</span><br />
<span style="color: #808080; font-style: italic;">-- based on the third capturing approach (classic loop).</span><br />
<span style="color: #b1b100;">function</span> multiply_3b<span style="color: #66cc66;">&#40;</span>item, <span style="color: #b1b100;">min</span>, <span style="color: #b1b100;">max</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> lpeg.Cmt<span style="color: #66cc66;">&#40;</span>lpeg.P<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">true</span><span style="color: #66cc66;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span>s, i<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">local</span> set, offset, attempt <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>, i, <span style="color: #cc66cc;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">for</span> j <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>, <span style="color: #b1b100;">max</span> <span style="color: #b1b100;">or</span> <span style="color: #b1b100;">min</span> <span style="color: #b1b100;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set<span style="color: #66cc66;">&#91;</span>j<span style="color: #66cc66;">&#93;</span>, attempt <span style="color: #66cc66;">=</span> lpeg.match<span style="color: #66cc66;">&#40;</span>item <span style="color: #66cc66;">*</span> lpeg.Cp<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, s, offset<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #b1b100;">not</span> attempt <span style="color: #b1b100;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> j <span style="color: #66cc66;">&gt;</span> <span style="color: #b1b100;">min</span> <span style="color: #b1b100;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">break</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> <span style="color: #b1b100;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;offset <span style="color: #66cc66;">=</span> attempt<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> offset, set<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">end</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #b1b100;">end</span></div></td></tr></tbody></table></div>
<h4><span style="color: #ff0000;">In conclusion&#8230;</span></h4>
<p>So, that was&#8230; quite a trip! Anyway, in hope that someone will find all this useful, I close with the usual&#8230; </p>
<p>Enjoy! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>P.S. I would be very surprised if anyone actually reads this ridiculous banter; if you are still here, I take my hat off to you, sir (or madam)!</p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/F2gdzH930ZA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/755/case-study-fixed-number-of-iterations-with-lpeg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/755/case-study-fixed-number-of-iterations-with-lpeg/</feedburner:origLink></item>
		<item>
		<title>Lua2C, an updated version</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/DxeOyCW5noI/</link>
		<comments>http://valeriu.palos.ro/669/lua2c/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 05:26:58 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Command line tools]]></category>
		<category><![CDATA[Dynamic scripting]]></category>
		<category><![CDATA[bin-to-cee]]></category>
		<category><![CDATA[bin2c]]></category>
		<category><![CDATA[bin2c.lua]]></category>
		<category><![CDATA[lpeg]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[lua2c]]></category>
		<category><![CDATA[lua2c.lua]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=669</guid>
		<description><![CDATA[I know I have been &#8220;missing in action&#8221; lately but I am working furiously, and I seem to have too little time for my blog (very sad face). But, just for a breath of fresh air, I thought I&#8217;d share something with the world. Entering lua2c.lua Lately I became quite interested in Lua (a lot [...]]]></description>
			<content:encoded><![CDATA[<p>I know I have been &#8220;missing in action&#8221; lately but I am working <strong>furiously</strong>, and I seem to have too little time for my blog (very sad face). But, just for a breath of fresh air, I thought I&#8217;d share something with the world.</p>
<h2><span style="color: #ff0000">Entering <em>lua2c.lua</em></span></h2>
<p>Lately I became quite interested in Lua (a lot actually). It has phenomenal speed, exceptional interfacing with C and some features and libraries that just make my day (i.e. coroutines, lpeg, lua-ev and others), and since I needed to embed some Lua scripts (entirely) in a C project I&#8217;m currently working on, I ended up adapting <a href="http://lua-users.org/wiki/BinToCee" target="_blank">Mike Edgar&#8217;s &#8220;bin2c.lua&#8221;</a> script (which takes a Lua script and turns it into a C header file) to suit my needs. </p>
<h2><span style="color: #ff0000">Basic functionality</span></h2>
<p>Specifically, this adaptation <strong>generates a function that takes a Lua state as the only argument and then runs the embedded Lua code in the given state after which it returns the status</strong> (as opposed to putting the code straight in the top-level scope of the generated file). This makes it easier to embed code in C and then invoke it, and also to apply the same code onto multiple Lua states (e.g. multiple threads).</p>
<p>Check the end of the post for a usage sample.<span id="more-669"></span></p>
<h2><span style="color: #ff0000">Options</span></h2>
<ul>
<li><code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #660033;">-c</span></span></code> compiles to Lua bytecode for (slightly) faster loading (does <strong>not</strong> work with LuaJIT)</li>
<li><code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #660033;">-s</span></span></code> <a href="http://en.wikipedia.org/wiki/Minification_(programming)">minifies</a> the source code before embedding to minimize wastes</li>
<li><code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #660033;">-e</span></span></code> applies a mild (XOR-based) obfuscation to prevent embedding of plain text</li>
<li><span style="color: #ff0000">[UPDATE:</span> <code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #660033;">-u</span></span></code> produces a (void) function that never fails and panics on errors <span style="color: #ff0000">]</span></li>
</ul>
<h2><span style="color: #ff0000">Download</span></h2>
<p>So here it is, enjoy: <a href="/download/lua2c.lua">lua2c.lua</a> (<strong>MIT license</strong>, same as Lua)<br /><span style="color: #ff0000">[UPDATE: </span> It seems that Codecolorer (or GeSHI) totally trashes my script (breaks comments, escapes etc.) so I had to remove the embedded source and instead just post a download link. <span style="color: #ff0000">]</span></p>
<h2><span style="color: #ff0000">Just to be clear</span></h2>
<p>For example, given a lua script file called &#8216;test.lua&#8217; (shown below) this is how we would go about embedding it into a simple C program called &#8216;test.c&#8217;.</p>
<div class="codecolorer-container lua mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="lua codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">-- test.lua: a small sign that we're up and running...</span><br />
<br />
<span style="color: #b1b100;">print</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;I am an embedded Lua script running inside a C binary! Hmm... cozy!&quot;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #b1b100;">function</span> some_activity<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">-- ...</span><br />
<span style="color: #b1b100;">end</span><br />
<br />
<span style="color: #808080; font-style: italic;">-- ...</span></div></td></tr></tbody></table></div>
<p>And here is the C file (rather overly commented)&#8230;</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/*<br />
&nbsp;* Include our embedded script.<br />
&nbsp;*/</span><br />
<span style="color: #339933;">#include &quot;test.h&quot;</span><br />
<br />
<span style="color: #808080; font-style: italic;">/*<br />
&nbsp;* Invoke the script.<br />
&nbsp;*/</span><br />
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</span> argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// create a Lua state</span><br />
&nbsp; &nbsp; lua_State<span style="color: #339933;">*</span> L <span style="color: #339933;">=</span> lua_open<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// load basic libraries into state</span><br />
&nbsp; &nbsp; luaL_openlibs<span style="color: #009900;">&#40;</span>L<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// invoke embedded script into state</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// by calling the generated function</span><br />
&nbsp; &nbsp; load_test_lua<span style="color: #009900;">&#40;</span>L<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// finish</span><br />
&nbsp; &nbsp; lua_close<span style="color: #009900;">&#40;</span>L<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>And here&#8217;s how we can compile all this into an executable. Note that I tested this on Ubuntu Lucid and the following packages had to be installed: lua5.1, liblua5.1-0-dev, liblua5.1-lpeg2, liblua5.1-bitop0. Your configuration may differ, and if you don&#8217;t have the pre-built Lua packages, you will have to install them manyally (along with the dependencies)!</p>
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># generate (unprotected, minified and encrypted) C code </span><br />
lua lua2c.lua <span style="color: #660033;">-seu</span> test.lua <span style="color: #000000; font-weight: bold;">&gt;</span> test.h<br />
<br />
<span style="color: #666666; font-style: italic;"># compile C program against Lua library</span><br />
<span style="color: #c20cb9; font-weight: bold;">gcc</span> test.c <span style="color: #660033;">-o</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #000000; font-weight: bold;">`</span>pkg-config lua5.1 <span style="color: #660033;">--libs</span> --cflags<span style="color: #000000; font-weight: bold;">`</span><br />
<br />
<span style="color: #666666; font-style: italic;"># run program</span><br />
.<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">test</span><br />
I am an embedded script running from inside a C binary<span style="color: #000000; font-weight: bold;">!</span> Hmm... cozy<span style="color: #000000; font-weight: bold;">!</span></div></td></tr></tbody></table></div>
<p>Let me know if it works fr you, or if you think of some cool improvement! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /><br />
Cheers!</p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/DxeOyCW5noI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/669/lua2c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/669/lua2c/</feedburner:origLink></item>
		<item>
		<title>Loomiere/Stream: Revived!</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/Qc7qwWjU594/</link>
		<comments>http://valeriu.palos.ro/629/loomierestream-revived/#comments</comments>
		<pubDate>Sat, 01 May 2010 20:57:59 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Web-development]]></category>
		<category><![CDATA[flv]]></category>
		<category><![CDATA[loomiere]]></category>
		<category><![CDATA[loomiere/stream]]></category>
		<category><![CDATA[moov atom]]></category>
		<category><![CDATA[mp4]]></category>
		<category><![CDATA[mp4 streaming]]></category>
		<category><![CDATA[streaming]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=629</guid>
		<description><![CDATA[OK folks, things have settled down and we are good to go. After some considerations the legal concerns for Loomiere/Stream are now cleared and gone. The source is now released and will be available indefinitely. Again, this streamer (minimally customized) has already been serving all the video content at http://peteava.ro for 3 full months (for [...]]]></description>
			<content:encoded><![CDATA[<p>OK folks, things have settled down and we are good to go. After some considerations the legal concerns for Loomiere/Stream are now cleared and gone. The source is now released and will be available indefinitely. Again, this streamer (minimally customized) has already been serving all the video content at <a href="http://peteava.ro">http://peteava.ro</a> for 3 full months (for those seeking a demo).</p>
<p>Source code: <a href="http://valeriu.palos.ro/wp-content/uploads/2010/05/loomiere-0.2.1.tar.gz">loomiere-0.2.1-tar.gz</a></p>
<p><span style="color: #c30;"><strong>Warning:</strong><br />
Any software downloaded from this website is <strong>*never* </strong>to be associated in any form with pornographic or erotic content! I.E. &#8220;Loomiere/Stream&#8221; must <strong>*never* </strong>be used to stream pornographic or erotic videos! There are plenty alternatives if you can&#8217;t help it.</span></p>
<p><strong>Just a teaser:</strong><br />
Fighting the video-streaming problem has taught me very many things which, in turn, led me to realize that I might be able to use a substantially different streaming approach to achieve a massive amount of optimization in this field. So quite soon, I think I&#8217;ll have ready a brand new (and far more powerful) streamer that aims at making it possible for a single server to serve many thousands (I am still testing this) of streams simultaneously using commodity hardware. I am not yet settled on whether this project will be commercial, open-sourced or both but I hope to clear this aspect soon as well. Real-world streaming (i.e. before and after) statistics will be made available on release.</p>
<p>Stay tuned! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/Qc7qwWjU594" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/629/loomierestream-revived/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/629/loomierestream-revived/</feedburner:origLink></item>
		<item>
		<title>Seven essential WordPress plugins</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/qt0RpZh4JZs/</link>
		<comments>http://valeriu.palos.ro/622/seven-essential-wordpress-plugins/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 08:53:50 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Akismet]]></category>
		<category><![CDATA[Bad-behaviour]]></category>
		<category><![CDATA[best plugins]]></category>
		<category><![CDATA[CodeColorer]]></category>
		<category><![CDATA[essential plugins]]></category>
		<category><![CDATA[FlagrantDisregard]]></category>
		<category><![CDATA[PHPIDS]]></category>
		<category><![CDATA[wordpress plugins]]></category>
		<category><![CDATA[WP Total Cache]]></category>
		<category><![CDATA[WPIDS]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=622</guid>
		<description><![CDATA[Here are the plugins I recommend for use on a WordPress blog. Most (not all) of these plugins are generic, meaning that they are not bound to a specific type of blog and may (or should) be used regardless of what you write. All of these plugins are top quality (IMHO) and provide an invaluable [...]]]></description>
			<content:encoded><![CDATA[<p>Here are the plugins I recommend for use on a WordPress blog.</p>
<p><strong>Most</strong> (<em>not all</em>) of these plugins are generic, meaning that they are not bound to a specific type of blog and may (or <em>should</em>) be used regardless of what you write.</p>
<p><strong>All</strong> of these plugins are top quality (IMHO) and provide an invaluable service for any blogger. I wholeheartedly recommend that you <strong>use and support them</strong>. I think that <strong>all of these should be apart of a standard</strong> WordPress installation.<br />
<span id="more-622"></span></p>
<h3>1. Akismet</h3>
<p>Website: ﻿<a href="http://akismet.com/download/" target="_blank">http://akismet.com/download/</a><br />
Everyone knows this one but it deserves mention. It prevents content spam. I&#8217;ve used it for about two years and so far it did [edit] <em>not</em> miss! I believe it now comes bundled with WordPress out-of-the-box.</p>
<h3>2. Bad-behaviour</h3>
<p>Website: <a href="http://www.bad-behavior.ioerror.us/download/" target="_blank">http://www.bad-behavior.ioerror.us/download/</a><br />
Prevents link and robot spam. Again, very good service repelling e-mail address harvesters, spam bots and all kinds of evil insects.</p>
<h3>3. WPIDS</h3>
<p>Website: <a href="http://php-ids.org/2007/09/12/wpids-phpids-your-wordpress-the-comfy-way/" target="_blank">http://php-ids.org/2007/09/12/wpids-phpids-your-wordpress-the-comfy-way/</a><br />
An excellent alliance between WordPress and the <a href="http://php-ids.org/" target="_blank">PHPIDS</a> project. It monitors your website for a very wide range of security attacks and does it very well.</p>
<h3>4. WP Total Cache</h3>
<p>Website: <a href="http://www.w3-edge.com/wordpress-plugins/w3-total-cache/" target="_blank">http://www.w3-edge.com/wordpress-plugins/w3-total-cache/</a><br />
This plugin enhances the performance of your blog and it seems to me, after trying out wp-cache and wp-super -cache that this is the best of the lot. It can even use a memcached server (if you have one).</p>
<h3>5. FlagrantDisregard FeedBurner</h3>
<p>Website: <a href="http://flagrantdisregard.com/feedburner/" target="_blank">http://flagrantdisregard.com/feedburner/</a><br />
This plugin provides the fundamental functionality of redirecting you blog feeds to FeedBurner, so you can track your subscribers properly.</p>
<h3>6. WordPress Stats</h3>
<p>Website: <a href="http://wordpress.org/extend/plugins/stats/" target="_blank">http://wordpress.org/extend/plugins/stats/</a><br />
Again, a fundamental feature: basic statistical tracking of your website right in the dashboard.</p>
<h3>7. CodeColorer</h3>
<p>Website: <a href="http://kpumuk.info/projects/wordpress-plugins/codecolorer/" target="_blank">http://kpumuk.info/projects/wordpress-plugins/codecolorer/</a><br />
I have yet to see a better syntax highlighting plugin than this one. Full-featured, configurable, knows any language in the book and <em>very</em> easy to use. Mix in <a href="http://valeriu.palos.ro/595/font-face-for-a-programmers-blog/" target="_blank">a good mono-spaced font</a> and your set!</p>
<p>Ok so maybe there are more, but these, I find myself installing constantly on all blogs that fall into my hands (except number 7 &#8211; CodeColorer &#8211; since it is only meant for posting source code).</p>
<p>Enjoy&#8230; and contribute if you like! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/qt0RpZh4JZs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/622/seven-essential-wordpress-plugins/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/622/seven-essential-wordpress-plugins/</feedburner:origLink></item>
		<item>
		<title>@font-face for a programmer’s blog?</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/Jpb2g7PLOl0/</link>
		<comments>http://valeriu.palos.ro/595/font-face-for-a-programmers-blog/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 08:28:51 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Web-development]]></category>
		<category><![CDATA[@font-face]]></category>
		<category><![CDATA[ascenderfonts]]></category>
		<category><![CDATA[consolas]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[fontsquirrel]]></category>
		<category><![CDATA[free fonts]]></category>
		<category><![CDATA[free for commercial use]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=595</guid>
		<description><![CDATA[I&#8217;m sure that many of you are well aware of the exceptional @font-face CSS3 rule, which made life much easier for many designers, I would think. A few days ago I started wondering if it would be appropriate to use such an instrument on my blog&#8230; the site you&#8217;re on! Yoopie! And, why not!? I [...]]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_605" class="wp-caption alignright" style="width: 185px"><a target="_blank" href="http://valeriu.palos.ro/wp-content/uploads/2010/02/Screenshot.png"><img class="size-medium wp-image-605 " title="Consolas on the web" src="http://valeriu.palos.ro/wp-content/uploads/2010/02/Screenshot-292x300.png" alt="" width="175" height="180" /></a><p class="wp-caption-text">See Consolas in action</p></div>I&#8217;m sure that many of you are well aware of the exceptional <a href="http://www.css3.info/preview/web-fonts-with-font-face/" target="_blank">@font-face CSS3 rule</a>, which made life much easier for many designers, I would think. A few days ago I started wondering if it would be appropriate to use such an instrument on my blog&#8230; the site you&#8217;re on! Yoopie!</p>
<p><strong>And, why not!?</strong> I love the idea of making my source codes more readable by using some custom font (<a href="http://www.microsoft.com/downloads/details.aspx?familyid=22e69ae4-7e40-4807-8a86-b3d36fab68d3&amp;displaylang=en" target="_blank">Consolas</a> anyone?). Anyway, I started looking around for some fonts and was not pleased with any of them (well to be fair I did like <a href="http://dejavu-fonts.org/wiki/index.php?title=Main_Page" target="_blank">DejaVu Sans Mono</a> but not as much as Consolas, unfortunately).<br />
<span id="more-595"></span><br />
Long story short, here is <a href="http://www.fontsquirrel.com/fontface" target="_blank"><strong>a very generous list of web-embeddable fonts</strong></a> which can be used freely in commercial scenarios, gathered by the awesome <a href="http://www.fontsquirrel.com" target="_blank">FontSquirrel.com</a> website (an instant friend!). They even provide a <a href="http://www.fontsquirrel.com/fontface/generator" target="_blank">@font-face generator</a> interface that transforms a given font file (TTF or OTF) into the needed formats (mainly EOT for IE) and also generates the embedding CSS3 rules. You should really give it a go!</p>
<p>And if you are wondering how I could speak of embedding Consolas on my blog, knowing full-well the licensing policy of Microsoft in these matters, here is your answer: one can buy a license to embed Consolas on the web (I paid $17.50) from <a href="http://www.ascenderfonts.com/font/consolas-regular.aspx" target="_blank">here</a>.</p>
<p>You can see it in action on any of my posts that contains some source code. Like <a href="http://valeriu.palos.ro/537/uri-parsing-using-bash-built-in-features/">this one</a>! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I know, I know! I also would have never believed that I would actually promote a Microsoft product on my blog, but the Consolas font deserves all the credit! It is simply unsurpassed as far as programming goes.</p>
<p>So, does anyone know any other web-embeddable fonts worth mentioning?</p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/Jpb2g7PLOl0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/595/font-face-for-a-programmers-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/595/font-face-for-a-programmers-blog/</feedburner:origLink></item>
		<item>
		<title>URI parsing using Bash built-in features</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/uB2jlIZrT0Q/</link>
		<comments>http://valeriu.palos.ro/537/uri-parsing-using-bash-built-in-features/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 08:24:04 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Bash scripting]]></category>
		<category><![CDATA[Command line tools]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[bash uri parser]]></category>
		<category><![CDATA[http parser]]></category>
		<category><![CDATA[http request]]></category>
		<category><![CDATA[pattern matching]]></category>
		<category><![CDATA[sed]]></category>
		<category><![CDATA[uri parser]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=537</guid>
		<description><![CDATA[A bit of background A while ago I posted an article describing how one could parse complete URIs in Bash using the sed program. Since then, I have realized that there is a better way to do it, a much better way: via Bash built-in pattern matching!  Here are some benefits of this improvement: It [...]]]></description>
			<content:encoded><![CDATA[<h3>A bit of background</h3>
<p>A while ago <a href="http://valeriu.palos.ro/219/bash-uri-parser-using-sed/">I posted an article</a> describing how one could parse complete URIs in Bash using the <code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #c20cb9; font-weight: bold;">sed</span></span></code> program. Since then, I have realized that there is a better way to do it, a <strong>much</strong> better way: <strong><span style="color: #ff0000;">via Bash built-in pattern matching! <span style="color: #000000; font-weight: normal;"><br />
Here are some benefits of this improvement:</span></span></strong></p>
<ul>
<li><strong>It no longer executes external programs</strong> (i.e. <code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #c20cb9; font-weight: bold;">sed</span></span></code>) for pattern matching. This translates to higher speed and lower memory and CPU usages, which means that you could use this parser for much more intense URI crunching.</li>
<li><strong>The new regular expressions are drastically simplified</strong> thanks to the <code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #800000;">${BASH_REMATCH[*]}</span></span></code> array that is able to hold more than 9 matched sub-expressions, unlike <code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #c20cb9; font-weight: bold;">sed</span></span></code> that can only work with single-digit escapes: <code class="codecolorer bash mac-classic"><span class="bash">\<span style="color: #000000;">1</span>-\<span style="color: #000000;">9</span></span></code> (<strong>yuck!</strong>).</li>
<li><strong>The parsing algorithm is contained in a single Bash function</strong>, so no external file is needed to hold the regular expressions. This also means, obviously, that the pattern file is no longer loaded from disk on every execution (so HDD is saved as well).</li>
<li><strong>The generated variables are named identically to the first version</strong>, so you should be able to upgrade your scripts to this version with absolutely minimal effort.</li>
<li>[Edit]<br /><strong>No eval instruction is needed</strong> (unlike in the first version), further improving performance.</li>
</ul>
<p><span id="more-537"></span></p>
<h3>Functionality</h3>
<ul>
<li>The function takes the URI as its parameter(s) and parses it. If  the parsing was successful it returns 0 (zero), if not (bad URI) it will return 1 (or any other non-zero integer).</li>
<li>The URI components are placed on global variables identical to those from <a href="http://valeriu.palos.ro/219/bash-uri-parser-using-sed/">the first article</a>. There is an example script further down either way so you will get the picture.
</ul>
</p>
<h3>Expected URI syntax</h3>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[schema://][user[:password]@]host[:port][/path][?[param=value]...][#fragment]</div></td></tr></tbody></table></div>
</p>
<h3>The actual parser code</h3>
<p>This is the actual function. You can embed this straight into your Bash script and it will be available for execution. This method greatly simplifies the usage and even debugging of this parser.</p>
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#</span><br />
<span style="color: #666666; font-style: italic;"># URI parsing function</span><br />
<span style="color: #666666; font-style: italic;">#</span><br />
<span style="color: #666666; font-style: italic;"># The function creates global variables with the parsed results.</span><br />
<span style="color: #666666; font-style: italic;"># It returns 0 if parsing was successful or non-zero otherwise.</span><br />
<span style="color: #666666; font-style: italic;">#</span><br />
<span style="color: #666666; font-style: italic;"># [schema://][user[:password]@]host[:port][/path][?[param=value]...][#fragment]</span><br />
<span style="color: #666666; font-style: italic;">#</span><br />
<span style="color: #000000; font-weight: bold;">function</span> uri_parser<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># uri capture</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri</span>=<span style="color: #ff0000;">&quot;$@&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># safe escaping</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${uri//\`/%60}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${uri//\&quot;/%22}</span>&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># top level parsing</span><br />
&nbsp; &nbsp; <span style="color: #007800;">pattern</span>=<span style="color: #ff0000;">'^(([a-z]{3,5})://)?((([^:\/]+)(:([^@\/]*))?@)?([^:\/?]+)(:([0-9]+))?)(\/[^?]*)?(\?[^#]*)?(#.*)?$'</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$uri</span>&quot;</span> =~ <span style="color: #007800;">$pattern</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #000000;">1</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># component extraction</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri</span>=<span style="color: #800000;">${BASH_REMATCH[0]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_schema</span>=<span style="color: #800000;">${BASH_REMATCH[2]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_address</span>=<span style="color: #800000;">${BASH_REMATCH[3]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_user</span>=<span style="color: #800000;">${BASH_REMATCH[5]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_password</span>=<span style="color: #800000;">${BASH_REMATCH[7]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_host</span>=<span style="color: #800000;">${BASH_REMATCH[8]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_port</span>=<span style="color: #800000;">${BASH_REMATCH[10]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_path</span>=<span style="color: #800000;">${BASH_REMATCH[11]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_query</span>=<span style="color: #800000;">${BASH_REMATCH[12]}</span><br />
&nbsp; &nbsp; <span style="color: #007800;">uri_fragment</span>=<span style="color: #800000;">${BASH_REMATCH[13]}</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># path parsing</span><br />
&nbsp; &nbsp; <span style="color: #007800;">count</span>=<span style="color: #000000;">0</span><br />
&nbsp; &nbsp; <span style="color: #007800;">path</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$uri_path</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">pattern</span>=<span style="color: #ff0000;">'^/+([^/]+)'</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$path</span> =~ <span style="color: #007800;">$pattern</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;uri_parts[<span style="color: #007800;">$count</span>]=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${BASH_REMATCH[1]}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">path</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${path:${#BASH_REMATCH[0]}</span>}&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">let</span> count++<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># query parsing</span><br />
&nbsp; &nbsp; <span style="color: #007800;">count</span>=<span style="color: #000000;">0</span><br />
&nbsp; &nbsp; <span style="color: #007800;">query</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$uri_query</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">pattern</span>=<span style="color: #ff0000;">'^[?&amp;]+([^= ]+)(=([^&amp;]*))?'</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$query</span> =~ <span style="color: #007800;">$pattern</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;uri_args[<span style="color: #007800;">$count</span>]=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${BASH_REMATCH[1]}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;uri_arg_<span style="color: #007800;">${BASH_REMATCH[1]}</span>=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${BASH_REMATCH[3]}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">query</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${query:${#BASH_REMATCH[0]}</span>}&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">let</span> count++<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># return success</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #000000;">0</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span></div></td></tr></tbody></table></div>
</p>
<h3>A demonstration</h3>
<p>Ok, I wouldn&#8217;t let you hanging there without an example, would I? This example basically uses the sample URI from the first version, and parses it accordingly. The difference is that this is an actual bash script so you can paste the parser function at the top (after <code class="codecolorer bash mac-classic"><span class="bash"><span style="color: #666666; font-style: italic;">#!/bin/bash</span></span></code>) and just run it to see the parser in action.</p>
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/bash</span><br />
<br />
<span style="color: #666666; font-style: italic;"># parser function goes here...</span><br />
<br />
<span style="color: #666666; font-style: italic;"># sample URI (including an injection attack)</span><br />
<span style="color: #007800;">uri</span>=<span style="color: #ff0000;">'http://user:pass@www.example.com:19741/dir1/dir2/file.php?param=some_value&amp;array[0]=&quot;123&quot;&amp;param2=\`cat /etc/passwd\`#bottom-left'</span><br />
<br />
<span style="color: #666666; font-style: italic;"># perform parsing and handle failure</span><br />
uri_parser <span style="color: #ff0000;">&quot;<span style="color: #007800;">$uri</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Malformed URI!&quot;</span>; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>; <span style="color: #7a0874; font-weight: bold;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># main uri</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = <span style="color: #007800;">$uri</span>&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># mai uri components</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_schema &nbsp; &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_schema</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_address &nbsp; &nbsp; &nbsp; = <span style="color: #007800;">$uri_address</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_user &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_user</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_password &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_password</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_host &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_host</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_port &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_port</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_path &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_path</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_query &nbsp; &nbsp; &nbsp; &nbsp; = <span style="color: #007800;">$uri_query</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_fragment &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">$uri_fragment</span>&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># path segments</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_parts[0] &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">${uri_parts[0]}</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_parts[1] &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">${uri_parts[1]}</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_parts[2] &nbsp; &nbsp; &nbsp;= <span style="color: #007800;">${uri_parts[2]}</span>&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># query arguments</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_args[0] &nbsp; &nbsp; &nbsp; = <span style="color: #007800;">${uri_args[0]}</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_args[1] &nbsp; &nbsp; &nbsp; = <span style="color: #007800;">${uri_args[1]}</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_args[2] &nbsp; &nbsp; &nbsp; = <span style="color: #007800;">${uri_args[2]}</span>&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># query arguments values</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_arg_param &nbsp; &nbsp; = <span style="color: #007800;">$uri_arg_param</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_arg_array[0] &nbsp;= <span style="color: #007800;">${uri_arg_array[0]}</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;uri_arg_param2 &nbsp; &nbsp;= <span style="color: #007800;">$uri_arg_param2</span>&quot;</span></div></td></tr></tbody></table></div>
</p>
<h3>Expected output</h3>
<p>The demonstration above should output the following lines of text.<br />
Check to see if it matches and <strong><span style="color: #ff0000">give me some feedback with the results!</span></strong> <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">uri &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = http://user:pass@www.example.com:19741/dir1/dir2/file.php?param=some_value&amp;array[0]=%22123%22&amp;param2=\%60cat /etc/passwd\%60#bottom-left<br />
uri_schema &nbsp; &nbsp; &nbsp; &nbsp;= http<br />
uri_address &nbsp; &nbsp; &nbsp; = user:pass@www.example.com:19741<br />
uri_user &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= user<br />
uri_password &nbsp; &nbsp; &nbsp;= pass<br />
uri_host &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= www.example.com<br />
uri_port &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= 19741<br />
uri_path &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= /dir1/dir2/file.php<br />
uri_query &nbsp; &nbsp; &nbsp; &nbsp; = ?param=some_value&amp;array[0]=%22123%22&amp;param2=\%60cat /etc/passwd\%60<br />
uri_fragment &nbsp; &nbsp; &nbsp;= #bottom-left<br />
uri_parts[0] &nbsp; &nbsp; &nbsp;= dir1<br />
uri_parts[1] &nbsp; &nbsp; &nbsp;= dir2<br />
uri_parts[2] &nbsp; &nbsp; &nbsp;= file.php<br />
uri_args[0] &nbsp; &nbsp; &nbsp; = param<br />
uri_args[1] &nbsp; &nbsp; &nbsp; = array[0]<br />
uri_args[2] &nbsp; &nbsp; &nbsp; = param2<br />
uri_arg_param &nbsp; &nbsp; = some_value<br />
uri_arg_array[0] &nbsp;= %22123%22<br />
uri_arg_param2 &nbsp; &nbsp;= \%60cat /etc/passwd\%60</div></td></tr></tbody></table></div>
</p>
<h3>Conclusion</h3>
<p>So, that&#8217;s it! A far better URI parser implemented straight in Bash. <span style="color: #ff0000">However, I think it could be taken even further with your help <strong>so please give it a try and write some feedback!</strong></span></p>
<p>Enjoy! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/uB2jlIZrT0Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/537/uri-parsing-using-bash-built-in-features/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/537/uri-parsing-using-bash-built-in-features/</feedburner:origLink></item>
		<item>
		<title>Quality Coding Practices</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/4siT88OHWgQ/</link>
		<comments>http://valeriu.palos.ro/511/quality-coding-practices/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 19:53:59 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[efficient programming]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[principles]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Quality Coding Practices]]></category>
		<category><![CDATA[safe programs]]></category>
		<category><![CDATA[secure programming]]></category>
		<category><![CDATA[writing fast programs]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=511</guid>
		<description><![CDATA[This is a set of guidelines that I put together starting a while back, which I try to respect when I write code. It is mostly (at least for now) oriented towards programming in C, but any systems programming language could benefit. Be aware that these do not apply to everyone or every scenario, adaptation and [...]]]></description>
			<content:encoded><![CDATA[<p>This is a set of guidelines that I put together starting a while back, which I try to respect when I write code. It is mostly (at least for now) oriented towards programming in C, but any systems programming language could benefit. Be aware that these do <em>not</em> apply to everyone or every scenario, adaptation and clever compromises are essential!</p>
<p><span style="color: #993300;">Now, this is obviously only a humble start, so I would like to ask the community <span style="color: #ff0000;">(yes, </span></span><strong><span style="color: #ff0000;">you!</span></strong><span style="color: #993300;"><span style="color: #ff0000;">) </span>to pitch in and help grow (and correct) this list of useful principles, so that, in time, it may actually become something used by folks around the web to better their coding practices. <span style="color: #ff0000;">C&#8217;mon, this will be <strong>fun, fun, fun!</strong> <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </span></span><span id="more-511"></span></p>
<h3>I. System operations on data, memory or file descriptors</h3>
<p><span style="font-weight: normal; font-size: 13px;"> </span></p>
<ol>
<li><span style="font-weight: normal; font-size: 13px;">Use </span><span style="font-weight: normal; font-size: 13px;"><strong>variable-length-arrays</strong></span><span style="font-weight: normal; font-size: 13px;"> or </span><span style="font-weight: normal; font-size: 13px;"><strong>alloca()</strong></span><span style="font-weight: normal; font-size: 13px;"> as much as possible instead of </span><span style="font-weight: normal; font-size: 13px;"><strong>malloc()</strong></span><span style="font-weight: normal; font-size: 13px;"> and friends. This kind of allocation is much faster and is allocated on the current function&#8217;s stack instead of the heap, so the allocated memory is automatically released when the containing function returns .<br />
[see <a href="http://en.wikipedia.org/wiki/Variable-length_array" target="_blank">http://en.wikipedia.org/wiki/Variable-length_array</a>]<br />
[see <a href="http://www.gnu.org/s/libc/manual/html_node/Advantages-of-Alloca.html" target="_blank">http://www.gnu.org/s/libc/manual/html_node/Advantages-of-Alloca.html</a>]</span></li>
<li><span style="font-weight: normal; font-size: 13px;"><strong>Limit kernel syscalls to an absolute minimum.</strong></span><span style="font-weight: normal; font-size: 13px;"> All operations on file handles (including stdin, stdout and stderr) are translated (at some point) into kernel syscalls! The same goes for malloc()/free() and many others. To this end you may consider reading the following points&#8230;</span></li>
<li><span style="font-weight: normal; font-size: 13px;">Use <strong>mmap()/munmap(</strong>) and friends whenever possible to dramatically reduce the costs of highly fragmented file i/o operations and/or memory allocations ;<br />
[see <a href="http://en.wikipedia.org/wiki/Memory-mapped_file" target="_blank">http://en.wikipedia.org/wiki/Memory-mapped_file</a>]<br />
</span></li>
<li><span style="font-weight: normal; font-size: 13px;">Use <strong>readv()/writev()</strong> and friends whenever possible instead of multiple </span><span style="font-weight: normal; font-size: 13px;"><strong>read()/write()</strong></span><span style="font-weight: normal; font-size: 13px;"> calls to make use of scatter/gather file operations, enabling you to combine multiple read or write operations in a single kernel syscall;<br />
[see <a href="http://en.wikipedia.org/wiki/Memory-mapped_file" target="_blank">http://en.wikipedia.org/wiki/Vectored_I/O</a>]</span></li>
<li><span style="font-weight: normal; font-size: 13px;">Use <strong>splice()/sendfile()</strong> to replace <strong>malloc()/read()/write()</strong> when copying data between file descriptors. The splice()/sendfile() calls are able to copy a segment of a given input file to an output file or internet socket just like a read()/write() instruction pair would (using a memory buffer pre-allocated with malloc()). However, splice()/sendfile() operate entirely inside the kernel, thus many syscalls are saved and no pre-allocated buffer is needed the whole copy yielding much higher performance.</span></li>
</ol>
<h3>II. Source generation, preprocessing, compilation</h3>
<ol>
<li><strong>Avoid passing expressions or function calls as parameters to macros. </strong>The macros will simply get expanded and the expression or function call that was given as a parameter will be executed at runtime in all places where they were expanded by the macro definition; this creates a lot of useless work and opens the possibility for undefined behaviour since an expression or function will be executed multiple times rather than only once as intended.
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Example</span><br />
<span style="color: #339933;">#define MAX(a, b) ((a) &gt; (b) ? (a) : (b)) // the macro</span><br />
<span style="color: #993333;">int</span> level <span style="color: #339933;">=</span> MAX<span style="color: #009900;">&#40;</span>get_level<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>         <span style="color: #666666; font-style: italic;">// bad usage</span><br />
<span style="color: #993333;">int</span> current_level <span style="color: #339933;">=</span> get_level<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>          <span style="color: #666666; font-style: italic;">// good usage</span><br />
<span style="color: #993333;">int</span> level <span style="color: #339933;">=</span> MAX<span style="color: #009900;">&#40;</span>current_level<span style="color: #339933;">,</span> <span style="color: #0000dd;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>     &nbsp; <span style="color: #666666; font-style: italic;">// ...</span></div></td></tr></tbody></table></div>
</li>
<li><strong>Surround macro parameters with parantheses.</strong> This prevents syntax errors when expanding expression parameters.</li>
<li><strong>Analyze the preprocessed code.</strong> Many times your macros can expand to unexpectedly large pieces of code making the final executable much larger; analyzing the preprocessed code cand enable you to translate such macros into function calls that get executed at run-time instead of expanded at compile-time.  
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># GCC: preprocess only</span><br />
 $ <span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-E</span> source.c <span style="color: #000000; font-weight: bold;">&gt;</span> source.txt</div></td></tr></tbody></table></div>
<p>  This optimization can make the final executable much smaller and faster to load (and sometimes even execute) into the system memory (ergo inlining code is *not* always a better choice)!</li>
</ol>
<h3>III. Miscellaneous</h3>
<ol>
<li><strong>Use environment variables or program parameters instead of configuration files whenever possible.</strong> Having configuration files, while attractive, is costly in many cases. Your program must have additional code to load and parse the configurations in memory and it also has to access the disk to read the file(s) on every run. Using parameters or environment variables avoids all these problems elegantly while still allowing you to pass various settings to the program. If you are writing a performance-critical program, that has to be small and quick to load in memory, this may save you a lot of unneeded bloat.</li>
</ol>
<p><span style="color: #ff0000;">That&#8217;s it for now!<br />
And, don&#8217;t be a scrooge! <strong>Tell me what you think.</strong></span></p>
<p>Enjoy! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/4siT88OHWgQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/511/quality-coding-practices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/511/quality-coding-practices/</feedburner:origLink></item>
		<item>
		<title>First impressions on Loomiere/Stream performance</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/gFsD3lKOqfg/</link>
		<comments>http://valeriu.palos.ro/495/first-impressions-on-loomierestream-performance/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 11:47:09 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[device utilization]]></category>
		<category><![CDATA[graphs]]></category>
		<category><![CDATA[iostat]]></category>
		<category><![CDATA[loomiere]]></category>
		<category><![CDATA[loomiere/stream]]></category>
		<category><![CDATA[memory usage]]></category>
		<category><![CDATA[munin]]></category>
		<category><![CDATA[traffic]]></category>
		<category><![CDATA[work loads]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=495</guid>
		<description><![CDATA[As promised, here are some of the first monitoring statistics of Loomiere/Stream in a production environment after moving away from psstream. Only one server is considered, a Quad-core Xeon with 8GB RAM (not that they are used anymore). This shows the memory usage over one week (the switch was made on the 29th as is [...]]]></description>
			<content:encoded><![CDATA[<p>As promised, here are some of the first monitoring statistics of Loomiere/Stream in a production environment after moving away from psstream. Only one server is considered, a Quad-core Xeon with 8GB RAM (not that they are used anymore).</p>
<p>This shows the memory usage over one week (the switch was made on the <strong>29th</strong> as is obvious).</p>
<p><img class="size-full wp-image-494  alignnone" title="Memory usage after loomiere/stream was installed" src="http://valeriu.palos.ro/wp-content/uploads/2010/02/content03-memory-week.png" alt="" width="501" height="389" /></p>
<p><span id="more-495"></span>&#8230;and the swap for that week:</p>
<p><img class="size-full wp-image-499 alignnone" title="Swap activity after loomiere/stream was installed" src="http://valeriu.palos.ro/wp-content/uploads/2010/02/content03-swap-week.png" alt="" width="501" height="269" /></p>
<p>Next we have the disk-drives load as given by iostat over one week:</p>
<p><img class="size-full wp-image-498 alignnone" title="Device load after loomiere/stream was installed" src="http://valeriu.palos.ro/wp-content/uploads/2010/02/content03-iostat-week.png" alt="" width="501" height="269" /></p>
<p>Here is the TCP traffic over the interface (bare in mind that when the switch occurred, there were far more clients served simultaneously):</p>
<p><img class="size-full wp-image-500 alignnone" title="Bandwidth usage after loomiere/stream was installed" src="http://valeriu.palos.ro/wp-content/uploads/2010/02/content03-if_eth1-week.png" alt="" width="501" height="269" /></p>
<p>And finally, here is a chart showing the number of active simultaneous connections handled by the streamer over the course of one day:</p>
<p><img class="size-full wp-image-501 alignnone" title="Active connections handled by loomiere/stream" src="http://valeriu.palos.ro/wp-content/uploads/2010/02/content03-netstat-day.png" alt="" width="501" height="305" /></p>
<p>Before, with psstream setup with NGINX/php-fastcgi, this server was processing 150 or (maximum 200) connections simultaneously.</p>
<p>So these are some first impressions, and it is plain to see that this streamer <strong>works</strong>! However, I am still not satisfied, I will continue to tinker with it and squeeze as much performance out of one server as I can.</p>
<p>Til&#8217;later.</p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/gFsD3lKOqfg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/495/first-impressions-on-loomierestream-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/495/first-impressions-on-loomierestream-performance/</feedburner:origLink></item>
		<item>
		<title>Loomiere/Stream – A high performance streaming server</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/f8PAOfv7CKU/</link>
		<comments>http://valeriu.palos.ro/445/loomierestream-a-high-performance-streaming-server/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 16:35:35 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[aac]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[flahs streaming]]></category>
		<category><![CDATA[flv]]></category>
		<category><![CDATA[h264]]></category>
		<category><![CDATA[ipsvd]]></category>
		<category><![CDATA[loomiere]]></category>
		<category><![CDATA[m4a]]></category>
		<category><![CDATA[m4v]]></category>
		<category><![CDATA[moov]]></category>
		<category><![CDATA[mov]]></category>
		<category><![CDATA[mp4]]></category>
		<category><![CDATA[pre-buffering]]></category>
		<category><![CDATA[pseudo-streaming]]></category>
		<category><![CDATA[psstream]]></category>
		<category><![CDATA[run-ahead]]></category>
		<category><![CDATA[runit]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=445</guid>
		<description><![CDATA[UPDATE: The code is now freely available under GPLv3. Please see this post for an update. ATTENTION: Due to the fact that myself and my company are not yet satisfied with some issues regarding the legal terms of Loomiere/Stream, I think it is wise to take it (temporarily) offline until we resolve our concerns! Also [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;"><span style="color: #000080;"><strong>UPDATE: The code is now freely available under GPLv3. Please see <a href="http://valeriu.palos.ro/629/loomierestream-revived/">this post</a> for an update.</strong></span></p>
<p style="text-align: left;"><span style="color: #808080;"><span style="color: #ff0000;text-decoration: line-through;">ATTENTION: Due to the fact that myself and my company are not yet satisfied with some issues regarding the legal terms of Loomiere/Stream, I think it is wise to take it (temporarily) offline until we resolve our concerns! Also some of the technical characteristics have been retracted.</span></span></p>
<h3><span style="color: #ff0000;">A</span>re you killing psstream?</h3>
<p>Well,<strong> yes!</strong> I am sure that many of you already know about <a href="http://codeblog.palos.ro/2008/11/13/pseudo-streaming-mp4h264-video-from-php/" target="_blank">psstream</a> (the PHP streaming extension I made a while back). Well, many things happened since then and I came to realize I could do better; a whole lot better actually. As of now the &#8216;psstream&#8217; project is officially no longer developed (see below). It will remain on the website for some time to come for archiving purposes but that is it.</p>
<h3><span style="color: #ff0000;">B</span>ut wait, why did you do it?</h3>
<p>For some time now I have be looking into improving the streaming mechanism for a large video-sharing project run by my company. PSStream was a first effort, and it did the job but soon ran into problems. None of our servers was able to properly stream more than 150 clients simultaneously and the resources were grossly wasted, hence, Loomiere/Stream.<span id="more-445"></span></p>
<h3><span style="color: #ff0000;">C</span>are to share some caracteristics?</h3>
<p>Sure. Unlike psstream (in which the moov parsing code from code-shop.com was used) Loomiere/Stream is written from scratch in C (and a bit of Bash) and uses a very minimalistic and lightweight approach. A lot of time was invested into optimizing this streamer; here are some delicious features I consider worth mentioning:</p>
<ul>
<li><strong>Secure and configurable</strong>
<ul>
<li>Loomiere/Streamer is, in fact, a set of <strong>micro-streamers</strong> (mp4, flv etc.) that come together into a <strong>fast </strong>and <strong>secure</strong> HTTP server using the <a href="http://smarden.org/ipsvd/" target="_blank">ipsvd</a> and <a href="http://smarden.org/runit/" target="_blank">runit</a> server tools which are very well optimized and stable. This means that I (and you) don&#8217;t have to go through the huge pain of making this server secure over time. It also means that the server&#8217;s <a href="http://smarden.org/ipsvd/ipsvd-instruct.5.html" target="_blank">security rules</a> will be very flexible and easy to manage.</li>
</ul>
</li>
<li><strong>Optimized to the extreme</strong>
<ul>
<li>Each micro-streamer is an <strong>extremely small</strong> <strong>program</strong> written in C/<a href="http://www.fefe.de/dietlibc/" target="_blank">dietlibc</a> (the mp4 streamer has at most 21k depending on system) and completely statically linked (no external libraries are linked when executed); this means that these processes can be started very quickly and the CPU is not strained by linking.</li>
<li>The micro-streamers have an <strong>extremely</strong><strong> low memory footprint </strong>(mp4 has uses about <strong>120k</strong>, never more);</li>
<li>Loomiere/Stream uses a &#8220;One process per request&#8221; approach, which is not usually very recommended on a web-server (due to the fact that it a process is usually heavier than a thread), but in the case of video streaming processes are better (IMO) than thread-pools. This is because each connection transfers a <strong>large amount of data</strong> and takes a <strong>very long time</strong> to complete, and would therefore fill-up the thread-pool rather quickly and keep it occupied for the duration of the streaming regardless of server load; here the process start-up time becomes irrelevant, and anyway the Loomiere/Strem micro-streamers startup extremely fast.</li>
<li><span style="color: #993300;">As a side-note, I think it would be beneficial to test a thread-based approach in the case of smooth-streaming, since in that case the requests would be short enough to make it feasible. Or maybe I could use unlimited threads to stream (i.e. use threads but <strong>not</strong> a thread pool), that would be worth trying out, I think since it is possible that less context switching will occur. I&#8217;ll have to do some tests. <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </span></li>
</ul>
</li>
<li><strong>Saves bandwidth (throttling)</strong>
<ul>
<li>The streamer tries to send only enough data to the player so that it will always be up-to-date. This is, of course, configurable via a set of parameters.</li>
</ul>
</li>
<li><strong>Versatile</strong>
<ul>
<li>Loomiere/Stream is able to serve MP4 and FLV files (flv, f4v, mp4, m4v, mov&#8230;) as well as image files (jpg, png, gif, bmp). Images are supported because you may have images to be served along with your movies on the same machine so you won&#8217;t have to install a second webserver to access them (however, see the recommendations further down).</li>
<li>The starting seek point can be given in bytes or seconds (only MP4 supports seconds yet, but FLV players always seek by byte position anyway).</li>
<li>The whole streaming system is very configurable via &#8216;/etc/loomiere/stream.conf&#8217;, and in real-time (you don&#8217;t have to restart the server for new settings to become active).</li>
</ul>
</li>
<li><strong>Open source</strong>
<ul>
<li>Loomiere/Stream is released under the GPLv3 license with an important amendment: <span style="color: #ff0000;">one can never use this software for streaming pornographic or sexual content of any kind!</span> Aside from that, you&#8217;re clear <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</li>
</ul>
</li>
</ul>
<h3><span style="color: #ff0000;">D</span>id you test this anywhere?</h3>
<p>The Loomiere/Stream server entered full production on <em>Friday 29th of January, 2010</em> at <em>14:31</em> on all the content streaming servers of the <a href="http://peteava.ro" target="_blank">peteava.ro</a> website. Until now it has been running <strong>flawlessly</strong>.</p>
<p>A random check (while I&#8217;m writing this post) on one of the most strained servers yielded 653 simutaneous clients and a workload of: ﻿﻿﻿﻿8.81, 9.03, 22.47. The old streamer served at most 150 clients with extreme difficulty (the machine was almost frozen). The bandwidth usage dropped from the initial 1300MB/s to about 900 MB/s (approximate values), even though there were many more clients served in parallel.</p>
<h3><span style="color: #ff0000;">E</span>verything sounds good but do you think it could be better?</h3>
<p>I know it can! <strong>Right now the server is in beta state!</strong> I can not guarantee anything at this moment (even unofficially) since I am still testing it myself under very heavy load. I will get back with more detailed statistics (and graphs), I promise!</p>
<h3><a name="download"></a><span style="color: #ff0000;">F</span>antastic, where do I get it from?</h3>
<p><strong>ATTENTION: Due to the fact that me and my company are not yet satisfied with some issues regarding the legal terms of Loomiere/Stream, I think it is wise to take it (temporarily) offline until we resolve our concerns!</strong></p>
<h3><span style="color: #ff0000;">G</span>iving any support?</h3>
<p>I plan to provide <strong>commercial support</strong> for all Loomiere components (just the streamer for now), so yes! Soon I promise! How soon depends on how many people will use this server and request this specifically.</p>
<p>Until then, the support is basically open and free to anyone who wants to get involved. Practically, if you will have a problem with it and need my help, I&#8217;ll be here, I promise!</p>
<p><span style="color: #ff0000;"><strong><br />
</strong></span></p>
<h3><span style="color: #ff0000;">H</span>ow do we use it?</h3>
<p>The server: I don&#8217;t have a proper documentation written yet (that will be coming) but there is a &#8220;DETAILS&#8221; file in the source archive (above) that explains (in short) what you need to do to get it working. However you should have some knowledge about how <a href="http://smarden.org/ipsvd/" target="_blank">ipsvd</a> and <a href="http://smarden.org/runit/" target="_blank">runit</a> work before tackling the streamer.</p>
<p>The clients: That&#8217;s easy, from any flash video player, you simply use the following url syntax:</p>
<pre>http://yourserver.com/path/to/file.mp4 [ ?start=x.xxx [ &amp;end=y.yyy ]]</pre>
<h3><span style="color: #ff0000;">I</span>s there anything else?</h3>
<p>I did not do any benchmarks against the Nginx and Lighttpd modules provided by the people at code-shop.com (they have renewed their modules as well). However, I hope my streamer will perform better considering that it was written with performance in mind, as a standalone server, thus not  being required to work with existing web-servers. Maybe someone could do some tests (maybe I&#8217;ll get around to it some day).</p>
<p>Well, for now, give me any feedback, bug reports or feature requests as a comment here.</p>
<p>Remember, streaming high-volume video is a <strong>very </strong>tricky business, there are many things involved! So if you have a single server that does other things beside the video streaming, I advise you to use your main web server as a front, redirecting streaming requests to the Loomiere/Stream server or simply stream your videos directly on a different port (like 81, or 8080) so that both servers can live on the same machine.</p>
<p>Although Loomiere/Stream is able to stream images, I only recommend you use it in case of large images and not for very small images that are heavily accessed (which is usually the case on the web). So if you can, use another web server for small images (with caching maybe?). I recommend: <a href="http://www.acme.com/software/thttpd/thttpd.html" target="_blank">thttpd</a>, <a href="http://wiki.nginx.org/Main" target="_blank">nginx</a> or <a href="http://www.fefe.de/fnord/" target="_blank">fnord</a> but any other (even Apache) would do just fine (depending on your requirements).</p>
<p>That&#8217;s it for now, I gotta sleep. Enjoy! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/f8PAOfv7CKU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/445/loomierestream-a-high-performance-streaming-server/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/445/loomierestream-a-high-performance-streaming-server/</feedburner:origLink></item>
		<item>
		<title>Recursive chmod distinguishing files from folders</title>
		<link>http://feedproxy.google.com/~r/valeriu/~3/Gyt1g0muGIo/</link>
		<comments>http://valeriu.palos.ro/422/recursive-chmod-with-discrimination-on-files-or-directories/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 11:22:16 +0000</pubDate>
		<dc:creator>valeriup</dc:creator>
				<category><![CDATA[Command line tools]]></category>
		<category><![CDATA[One-liners]]></category>
		<category><![CDATA[batch chmod]]></category>
		<category><![CDATA[chmod]]></category>
		<category><![CDATA[directory]]></category>
		<category><![CDATA[files]]></category>
		<category><![CDATA[mass chmod]]></category>

		<guid isPermaLink="false">http://valeriu.palos.ro/?p=422</guid>
		<description><![CDATA[Version 3 An even better method is: 12find &#34;$target&#34; -type f -exec chmod -c &#34;$mode_files&#34; &#123;&#125; \; \ &#160; &#160; &#160; -or -type d -exec chmod -c &#34;$mode_dir&#34; &#123;&#125; \; A true one-liner! Version 2 A better method is this: 12find &#34;$target&#34; -type f -exec chmod -c &#34;$mode_files&#34; &#123;&#125; \; find &#34;$target&#34; -type d -exec [...]]]></description>
			<content:encoded><![CDATA[<h3><span style="color: #ff0000;">Version 3<br />
</span></h3>
<p>An even better method is:</p>
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$target</span>&quot;</span> <span style="color: #660033;">-type</span> f <span style="color: #660033;">-exec</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mode_files</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> \; \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-or</span> <span style="color: #660033;">-type</span> d <span style="color: #660033;">-exec</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mode_dir</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> \;</div></td></tr></tbody></table></div>
<p>A true one-liner! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<h3><span style="color: #ff0000;">Version 2</span></h3>
<p>A better method is this:</p>
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$target</span>&quot;</span> <span style="color: #660033;">-type</span> f <span style="color: #660033;">-exec</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mode_files</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> \;<br />
<span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$target</span>&quot;</span> <span style="color: #660033;">-type</span> d <span style="color: #660033;">-exec</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$mode_dir</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> \;</div></td></tr></tbody></table></div>
<p>This one can also be used from the command line.</p>
<h3><span style="color: #ff0000;">Version 1</span></h3>
<p>Many times I needed to apply certain permissions recursively on a given path but with different permissions on files than on directories (i.e. I want 0644 for files and 0744 for directories). This behaviour is not provided by the chmod tool so here is a simple and effective bash function to do just that:</p>
<div class="codecolorer-container bash mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Recursively apply chmod to path.</span><br />
<span style="color: #666666; font-style: italic;"># If mode_files is missing then apply mode_dir to files too.</span><br />
<span style="color: #666666; font-style: italic;"># Params: target mode_dir [mode_files]</span><br />
<span style="color: #000000; font-weight: bold;">function</span> deep_chmod<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">function</span> _walk<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">local</span> F<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> F <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #ff0000;">&quot;$1&quot;</span><span style="color: #000000; font-weight: bold;">`</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #007800;">M</span>=<span style="color: #ff0000;">&quot;$3&quot;</span>; <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #660033;">-b</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$F</span>&quot;</span><span style="color: #000000; font-weight: bold;">`</span> == <span style="color: #ff0000;">&quot;directory&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">M</span>=<span style="color: #ff0000;">&quot;$2&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$M</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$F</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000;">2</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _walk <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #ff0000;">&quot;$2&quot;</span> <span style="color: #ff0000;">&quot;$3&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-Rc</span> <span style="color: #ff0000;">&quot;$2&quot;</span> <span style="color: #ff0000;">&quot;$1&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>I&#8217;m looking for a way to improve on this since it is quite costly for large directories: for each file or directory at least two programs are executed (file and chmod) which is not very efficient! For now, it gets the job done.<br />
Enjoy! <img src='http://valeriu.palos.ro/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/valeriu/~4/Gyt1g0muGIo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://valeriu.palos.ro/422/recursive-chmod-with-discrimination-on-files-or-directories/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://valeriu.palos.ro/422/recursive-chmod-with-discrimination-on-files-or-directories/</feedburner:origLink></item>
	</channel>
</rss>
