<?xml version='1.0' encoding='utf-8' ?>
<rss version="2.0">
  <channel>
    <title>Shitware</title>
    <link>http://www.shitware.nl</link>
    <description>Shitware? On the double!</description>
    <language>nl-nl</language>
    <managingEditor>rob@shitware.nl (Rob Thomassen)</managingEditor>
    <webMaster>rob@shitware.nl (Rob Thomassen)</webMaster>
    <copyright>Royal Shitware Inc. (RSI) / Rob Thomassen</copyright>
    <generator>Shitware Blog ft. DSE toolkit</generator>
    <image>
      <title>Shitware</title>
      <link>http://www.shitware.nl</link>
      <url>http://shitware.nl/blog/feedlogo.gif</url>
      <description>Shitware? On the double!</description>
    </image>
    <pubDate>Sun, 12 Apr 2026 11:22:33 +0200</pubDate>
    <item>
      <title>Fast and simple PHP diff method</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=600</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=600</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=600#Comments</comments>
      <description><![CDATA[The "diff" is done in the diff() function (only 25 LoC - although some might call this "too compact"); the rest is for presentation purpose (plain-text or HTML, side-by-side = horizontal, or diff lines above eachother = vertical):
<div class="PHP"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">namespace&nbsp;</span><span style="color: #0000BB">Rsi</span><span style="color: #007700">;<br /><br />class&nbsp;</span><span style="color: #0000BB">Diff</span><span style="color: #007700">{<br /><br />&nbsp;&nbsp;const&nbsp;</span><span style="color: #0000BB">TYPE_EQUAL&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'e'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;A&nbsp;and&nbsp;B&nbsp;are&nbsp;equal.<br />&nbsp;&nbsp;</span><span style="color: #007700">const&nbsp;</span><span style="color: #0000BB">TYPE_DIFF&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'x'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;A&nbsp;and&nbsp;B&nbsp;differ.<br />&nbsp;&nbsp;</span><span style="color: #007700">const&nbsp;</span><span style="color: #0000BB">TYPE_SPACE&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'s'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;A&nbsp;and&nbsp;B&nbsp;differ&nbsp;only&nbsp;in&nbsp;leading&nbsp;and&nbsp;trailing&nbsp;white-space.<br />&nbsp;&nbsp;</span><span style="color: #007700">const&nbsp;</span><span style="color: #0000BB">TYPE_DIFF_A&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'a'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;A&nbsp;is&nbsp;not&nbsp;present&nbsp;in&nbsp;B.<br />&nbsp;&nbsp;</span><span style="color: #007700">const&nbsp;</span><span style="color: #0000BB">TYPE_DIFF_B&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'b'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;B&nbsp;is&nbsp;not&nbsp;present&nbsp;in&nbsp;A.<br /><br />&nbsp;&nbsp;</span><span style="color: #007700">const&nbsp;</span><span style="color: #0000BB">HTML_MODE_VERTICAL&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'vertical'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Show&nbsp;A&nbsp;above&nbsp;B&nbsp;in&nbsp;HTML&nbsp;view&nbsp;(when&nbsp;different).<br />&nbsp;&nbsp;</span><span style="color: #007700">const&nbsp;</span><span style="color: #0000BB">HTML_MODE_HORIZONTAL&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'horizontal'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Show&nbsp;A&nbsp;left&nbsp;and&nbsp;B&nbsp;right&nbsp;in&nbsp;HTML&nbsp;view.<br /><br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$defaultHead&nbsp;</span><span style="color: #007700">=&nbsp;[</span><span style="color: #DD0000">'A'</span><span style="color: #007700">,</span><span style="color: #DD0000">'B'</span><span style="color: #007700">];&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Default&nbsp;header&nbsp;for&nbsp;the&nbsp;HTML&nbsp;table.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$extra&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Extra,&nbsp;unchanged&nbsp;lines&nbsp;to&nbsp;show&nbsp;around&nbsp;changes.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$extraAllThreshold&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Show&nbsp;all&nbsp;code&nbsp;when&nbsp;there&nbsp;is&nbsp;max&nbsp;this&nbsp;number&nbsp;of&nbsp;lines&nbsp;to&nbsp;be&nbsp;hidden.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$styleFile&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">__DIR__&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #DD0000">'/diff.css'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Stylsheet&nbsp;filename.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$htmlMode&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">HTML_MODE_VERTICAL</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;See&nbsp;HTML_MODE_*&nbsp;constants.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$whiteSpaceThreshold&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0.2</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Only&nbsp;show&nbsp;"white-space&nbsp;only"&nbsp;changes&nbsp;if&nbsp;they&nbsp;are&nbsp;more&nbsp;then&nbsp;this&nbsp;part&nbsp;of&nbsp;the&nbsp;(maximum)<br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;number&nbsp;of&nbsp;lines&nbsp;in&nbsp;the&nbsp;block.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$lineDiffMaxLines&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Only&nbsp;show&nbsp;detailed&nbsp;diff&nbsp;info&nbsp;if&nbsp;the&nbsp;difference&nbsp;in&nbsp;line&nbsp;count&nbsp;is&nbsp;equal&nbsp;or&nbsp;below&nbsp;this&nbsp;amount.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$lineDiffThreshold&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0.6</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Only&nbsp;show&nbsp;detailed&nbsp;diff&nbsp;info&nbsp;if&nbsp;more&nbsp;than&nbsp;this&nbsp;part&nbsp;of&nbsp;the&nbsp;block&nbsp;stayed&nbsp;the&nbsp;same.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$skipTemplate&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'*&nbsp;lines'</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Template&nbsp;for&nbsp;skipped&nbsp;lines&nbsp;(asterisk&nbsp;is&nbsp;replaced&nbsp;with&nbsp;number&nbsp;of&nbsp;lines).<br /><br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;</span><span style="color: #0000BB">$_a&nbsp;</span><span style="color: #007700">=&nbsp;[];&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Lines&nbsp;for&nbsp;side&nbsp;A.<br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;</span><span style="color: #0000BB">$_b&nbsp;</span><span style="color: #007700">=&nbsp;[];&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Lines&nbsp;for&nbsp;side&nbsp;B.<br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;</span><span style="color: #0000BB">$_diff&nbsp;</span><span style="color: #007700">=&nbsp;[];&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Diff&nbsp;results&nbsp;(array&nbsp;of&nbsp;blocks&nbsp;with&nbsp;keys:&nbsp;t&nbsp;=&nbsp;type,&nbsp;sa&nbsp;=&nbsp;start&nbsp;of&nbsp;block&nbsp;in&nbsp;A,&nbsp;ca&nbsp;=&nbsp;line&nbsp;count&nbsp;for<br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;block&nbsp;in&nbsp;A,&nbsp;sb&nbsp;=&nbsp;start&nbsp;of&nbsp;block&nbsp;in&nbsp;B,&nbsp;cb&nbsp;=&nbsp;line&nbsp;count&nbsp;for&nbsp;block&nbsp;in&nbsp;B).<br /><br />&nbsp;&nbsp;/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Create&nbsp;diff.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$a&nbsp;&nbsp;Text&nbsp;for&nbsp;A.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$b&nbsp;&nbsp;Text&nbsp;for&nbsp;B.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;bool&nbsp;&nbsp;Set&nbsp;to&nbsp;true&nbsp;if&nbsp;A&nbsp;and&nbsp;B&nbsp;are&nbsp;both&nbsp;local&nbsp;filenames.&nbsp;Besides&nbsp;loading&nbsp;the&nbsp;files,&nbsp;this&nbsp;will&nbsp;also&nbsp;set&nbsp;the&nbsp;default<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;head&nbsp;to&nbsp;the&nbsp;filenames,&nbsp;combined&nbsp;with&nbsp;the&nbsp;modification&nbsp;date&nbsp;(and&nbsp;time,&nbsp;when&nbsp;changed&nbsp;within&nbsp;24&nbsp;hours&nbsp;of&nbsp;eachother).<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">__construct</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">,</span><span style="color: #0000BB">$b</span><span style="color: #007700">,</span><span style="color: #0000BB">$files&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$files</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ta&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">filemtime</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$tb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">filemtime</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$format&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'Y-m-d'&nbsp;</span><span style="color: #007700">.&nbsp;((</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">abs</span><span style="color: #007700">(</span><span style="color: #0000BB">$ta&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$tb</span><span style="color: #007700">))&nbsp;&lt;&nbsp;</span><span style="color: #0000BB">86400&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">'&nbsp;H:i'&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">60&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">':s'&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">defaultHead&nbsp;</span><span style="color: #007700">=&nbsp;[</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #DD0000">'&nbsp;@&nbsp;'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">date</span><span style="color: #007700">(</span><span style="color: #0000BB">$format</span><span style="color: #007700">,</span><span style="color: #0000BB">$ta</span><span style="color: #007700">),</span><span style="color: #0000BB">$b&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #DD0000">'&nbsp;@&nbsp;'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">date</span><span style="color: #007700">(</span><span style="color: #0000BB">$format</span><span style="color: #007700">,</span><span style="color: #0000BB">$tb</span><span style="color: #007700">)];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$b&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">diff</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">),</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_b&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">));<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(</span><span style="color: #0000BB">$str</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$str&nbsp;</span><span style="color: #007700">===&nbsp;</span><span style="color: #0000BB">null&nbsp;</span><span style="color: #007700">?&nbsp;[]&nbsp;:&nbsp;</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">$str</span><span style="color: #007700">);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Calculate&nbsp;the&nbsp;difference&nbsp;between&nbsp;two&nbsp;blocks.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;array&nbsp;$a&nbsp;&nbsp;Lines&nbsp;of&nbsp;block&nbsp;A.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;array&nbsp;$b&nbsp;&nbsp;Lines&nbsp;of&nbsp;block&nbsp;B.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;$oa&nbsp;&nbsp;Offset&nbsp;of&nbsp;block&nbsp;A&nbsp;in&nbsp;relation&nbsp;to&nbsp;the&nbsp;comlete&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;$ob&nbsp;&nbsp;Offset&nbsp;of&nbsp;block&nbsp;B&nbsp;in&nbsp;relation&nbsp;to&nbsp;the&nbsp;comlete&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;array&nbsp;&nbsp;Array&nbsp;with&nbsp;a&nbsp;record&nbsp;per&nbsp;comparison&nbsp;block&nbsp;('t'&nbsp;=&nbsp;block&nbsp;type&nbsp;-&nbsp;see&nbsp;TYPE_*&nbsp;constants,&nbsp;'sa'&nbsp;=&nbsp;start&nbsp;of&nbsp;block&nbsp;in<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;A,&nbsp;'ca'&nbsp;=&nbsp;number&nbsp;of&nbsp;lines&nbsp;in&nbsp;A,&nbsp;'sb'&nbsp;=&nbsp;start&nbsp;of&nbsp;block&nbsp;in&nbsp;B,&nbsp;'cb'&nbsp;=&nbsp;number&nbsp;of&nbsp;lines&nbsp;in&nbsp;B).<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;function&nbsp;</span><span style="color: #0000BB">diff</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">,</span><span style="color: #0000BB">$b</span><span style="color: #007700">,</span><span style="color: #0000BB">$oa&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">,</span><span style="color: #0000BB">$ob&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//prefixes:&nbsp;o&nbsp;=&nbsp;offset,&nbsp;c&nbsp;=&nbsp;count,&nbsp;s&nbsp;=&nbsp;start,&nbsp;i&nbsp;=&nbsp;index<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$cache&nbsp;</span><span style="color: #007700">=&nbsp;[];<br />&nbsp;&nbsp;&nbsp;&nbsp;for(</span><span style="color: #0000BB">$ia&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$ia&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$ia</span><span style="color: #007700">++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach((</span><span style="color: #0000BB">$cache</span><span style="color: #007700">[</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$ia</span><span style="color: #007700">]]&nbsp;??&nbsp;(</span><span style="color: #0000BB">$cache</span><span style="color: #007700">[</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$ia</span><span style="color: #007700">]]&nbsp;=&nbsp;</span><span style="color: #0000BB">array_keys</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">,</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$ia</span><span style="color: #007700">],</span><span style="color: #0000BB">true</span><span style="color: #007700">)))&nbsp;as&nbsp;</span><span style="color: #0000BB">$ib</span><span style="color: #007700">)&nbsp;if(</span><span style="color: #0000BB">$ib&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(</span><span style="color: #0000BB">$c&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$c&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">++)&nbsp;if(</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$ia&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">]&nbsp;!==&nbsp;</span><span style="color: #0000BB">$b</span><span style="color: #007700">[</span><span style="color: #0000BB">$ib&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">])&nbsp;continue&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while((</span><span style="color: #0000BB">$ia&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$c&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">)&nbsp;&amp;&amp;&nbsp;(</span><span style="color: #0000BB">$ib&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$c&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">)&nbsp;&amp;&amp;&nbsp;(</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$ia&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">]&nbsp;===&nbsp;</span><span style="color: #0000BB">$b</span><span style="color: #007700">[</span><span style="color: #0000BB">$ib&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">]))&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$c</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$ia</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$ib</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$count<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">array_merge</span><span style="color: #007700">(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">diff</span><span style="color: #007700">(</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">,</span><span style="color: #0000BB">0</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">),</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">,</span><span style="color: #0000BB">0</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">),</span><span style="color: #0000BB">$oa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ob</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[[</span><span style="color: #DD0000">'t'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">,</span><span style="color: #DD0000">'sa'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$oa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #DD0000">'ca'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">,</span><span style="color: #DD0000">'sb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$ob&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #DD0000">'cb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">]],<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">diff</span><span style="color: #007700">(</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">),</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$b</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">),</span><span style="color: #0000BB">$oa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">,</span><span style="color: #0000BB">$ob&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;(</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">||&nbsp;</span><span style="color: #0000BB">$b&nbsp;</span><span style="color: #007700">?&nbsp;[[<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'t'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;(</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;</span><span style="color: #0000BB">$b</span><span style="color: #007700">)&nbsp;?&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_DIFF&nbsp;</span><span style="color: #007700">:&nbsp;(</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_DIFF_A&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_DIFF_B</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'sa'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$oa</span><span style="color: #007700">,</span><span style="color: #DD0000">'ca'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'sb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$ob</span><span style="color: #007700">,</span><span style="color: #DD0000">'cb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$cb<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">]]&nbsp;:&nbsp;[]);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Count&nbsp;the&nbsp;number&nbsp;of&nbsp;blocks&nbsp;of&nbsp;a&nbsp;certain&nbsp;type.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$type&nbsp;&nbsp;Diff&nbsp;type&nbsp;(see&nbsp;DIFF_*&nbsp;constants).&nbsp;Set&nbsp;to&nbsp;null&nbsp;to&nbsp;count&nbsp;all&nbsp;"not&nbsp;equal"&nbsp;blocks.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;foreach(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">)&nbsp;if(</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">===&nbsp;</span><span style="color: #0000BB">null&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;!=&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;==&nbsp;</span><span style="color: #0000BB">$type</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Maximum&nbsp;line&nbsp;number.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;bool&nbsp;$chars&nbsp;&nbsp;Return&nbsp;the&nbsp;number&nbsp;of&nbsp;characters&nbsp;for&nbsp;the&nbsp;largest&nbsp;line&nbsp;number.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int&nbsp;&nbsp;Largest&nbsp;line&nbsp;number&nbsp;(or&nbsp;characters).<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">maxLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$chars&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$lines&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">max</span><span style="color: #007700">(</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a</span><span style="color: #007700">),</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_b</span><span style="color: #007700">));<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$chars&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">ceil</span><span style="color: #007700">(</span><span style="color: #0000BB">log</span><span style="color: #007700">(</span><span style="color: #0000BB">$lines</span><span style="color: #007700">,</span><span style="color: #0000BB">10</span><span style="color: #007700">))&nbsp;:&nbsp;</span><span style="color: #0000BB">$lines</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">textLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$type</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//prefixes:&nbsp;s&nbsp;=&nbsp;start,&nbsp;c&nbsp;=&nbsp;count<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;switch(</span><span style="color: #0000BB">$type</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++)&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #DD0000">"&nbsp;"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a</span><span style="color: #007700">[</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">]&nbsp;.&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++)&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #DD0000">"-"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a</span><span style="color: #007700">[</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">]&nbsp;.&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++)&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #DD0000">"+"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_b</span><span style="color: #007700">[</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">]&nbsp;.&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$text</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Classic,&nbsp;textual&nbsp;diff&nbsp;output&nbsp;(A&nbsp;above&nbsp;B).<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;mixed&nbsp;$head&nbsp;&nbsp;Header&nbsp;for&nbsp;the&nbsp;text&nbsp;(string).&nbsp;Set&nbsp;to&nbsp;true&nbsp;for&nbsp;a&nbsp;default&nbsp;head,&nbsp;or&nbsp;provide&nbsp;an&nbsp;array&nbsp;with&nbsp;the&nbsp;A&nbsp;and&nbsp;B<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;description.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">asText</span><span style="color: #007700">(</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//prefixes:&nbsp;c&nbsp;=&nbsp;count,&nbsp;p&nbsp;=&nbsp;prefix,&nbsp;q&nbsp;=&nbsp;suffix&nbsp;(unchanged&nbsp;lines&nbsp;before&nbsp;and&nbsp;after&nbsp;the&nbsp;diff)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if(</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">===&nbsp;</span><span style="color: #0000BB">true</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">defaultHead</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">is_array</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">))&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"+++&nbsp;"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">"\n---&nbsp;"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$head</span><span style="color: #DD0000">\n"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;while(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">)&nbsp;if(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">[</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$index</span><span style="color: #007700">][</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;!=&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$blocks&nbsp;</span><span style="color: #007700">=&nbsp;[];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while((</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">)&nbsp;&amp;&amp;&nbsp;(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">][</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;!=&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">)&nbsp;||<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">][</span><span style="color: #DD0000">'ca'</span><span style="color: #007700">]&nbsp;&lt;=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extra&nbsp;</span><span style="color: #007700">*&nbsp;</span><span style="color: #0000BB">2&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extraAllThreshold</span><span style="color: #007700">)&nbsp;</span><span style="color: #FF8000">//relativly&nbsp;small&nbsp;equal&nbsp;block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">))&nbsp;</span><span style="color: #0000BB">$blocks</span><span style="color: #007700">[]&nbsp;=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">++];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$pa&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">min</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extra</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$blocks</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'sa'</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$qa&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">min</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extra</span><span style="color: #007700">,</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a</span><span style="color: #007700">)&nbsp;-&nbsp;(</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;(</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_sum</span><span style="color: #007700">(</span><span style="color: #0000BB">array_column</span><span style="color: #007700">(</span><span style="color: #0000BB">$blocks</span><span style="color: #007700">,</span><span style="color: #DD0000">'ca'</span><span style="color: #007700">)))));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$pb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">min</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extra</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$blocks</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'sb'</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$qb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">min</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extra</span><span style="color: #007700">,</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_b</span><span style="color: #007700">)&nbsp;-&nbsp;(</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;(</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_sum</span><span style="color: #007700">(</span><span style="color: #0000BB">array_column</span><span style="color: #007700">(</span><span style="color: #0000BB">$blocks</span><span style="color: #007700">,</span><span style="color: #DD0000">'cb'</span><span style="color: #007700">)))));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">.=<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">"@@&nbsp;-"&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$pa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">","&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$pa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$qa</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">"&nbsp;+"&nbsp;</span><span style="color: #007700">.&nbsp;&nbsp;(</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$pb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">","&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$pb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$qb</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">"&nbsp;@@\n"&nbsp;</span><span style="color: #007700">.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">textLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">[</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">][</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;??&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$pa</span><span style="color: #007700">,</span><span style="color: #0000BB">$pa</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$pb</span><span style="color: #007700">,</span><span style="color: #0000BB">$pb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach(</span><span style="color: #0000BB">$blocks&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">)&nbsp;if(</span><span style="color: #0000BB">extract</span><span style="color: #007700">(</span><span style="color: #0000BB">$block</span><span style="color: #007700">))&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">textLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$text&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">textLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">][</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;??&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$qa</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">,</span><span style="color: #0000BB">$qb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;</span><span style="color: #0000BB">$index</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$text</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Style&nbsp;block&nbsp;for&nbsp;the&nbsp;HTML&nbsp;diff.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">htmlStyle</span><span style="color: #007700">(){<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #DD0000">"&lt;style&gt;"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">str_replace</span><span style="color: #007700">(</span><span style="color: #DD0000">'var(--diff-max-line)'</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">maxLine</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">),</span><span style="color: #0000BB">file_get_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">styleFile</span><span style="color: #007700">))&nbsp;.&nbsp;</span><span style="color: #DD0000">"&lt;/style&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">htmlLineBlock</span><span style="color: #007700">(</span><span style="color: #0000BB">$type</span><span style="color: #007700">,</span><span style="color: #0000BB">$chars</span><span style="color: #007700">,</span><span style="color: #0000BB">$start</span><span style="color: #007700">,</span><span style="color: #0000BB">$count</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;if(!</span><span style="color: #0000BB">$count</span><span style="color: #007700">)&nbsp;return&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$prefix&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">null&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">"&lt;span&nbsp;class='text-</span><span style="color: #0000BB">$type</span><span style="color: #DD0000">'&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$suffix&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">null&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">"&lt;/span&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$prefix&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">str_replace</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$suffix</span><span style="color: #DD0000">\n</span><span style="color: #0000BB">$prefix</span><span style="color: #DD0000">"</span><span style="color: #007700">,</span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$chars</span><span style="color: #007700">,</span><span style="color: #0000BB">$start</span><span style="color: #007700">,</span><span style="color: #0000BB">$count</span><span style="color: #007700">))))&nbsp;.&nbsp;</span><span style="color: #0000BB">$suffix</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">htmlLineSpace</span><span style="color: #007700">(</span><span style="color: #0000BB">$chars</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$html&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;foreach(</span><span style="color: #0000BB">$chars&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$char</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'other'</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch(</span><span style="color: #0000BB">$char</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #DD0000">'&nbsp;'</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'space'</span><span style="color: #007700">;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #DD0000">"\t"</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'tab'</span><span style="color: #007700">;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #DD0000">"\r"</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'cr'</span><span style="color: #007700">;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$html&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #DD0000">"&lt;span&nbsp;class='space&nbsp;type-</span><span style="color: #0000BB">$type</span><span style="color: #DD0000">'&gt;</span><span style="color: #0000BB">$char</span><span style="color: #DD0000">&lt;/span&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$html</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">htmlLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$index</span><span style="color: #007700">,</span><span style="color: #0000BB">$type</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//prefixes:&nbsp;h&nbsp;=&nbsp;HTML&nbsp;for&nbsp;code,&nbsp;s&nbsp;=&nbsp;start,&nbsp;c&nbsp;=&nbsp;count,&nbsp;y&nbsp;=&nbsp;char&nbsp;array,&nbsp;p&nbsp;=&nbsp;prefix&nbsp;chars,&nbsp;q&nbsp;=&nbsp;suffix&nbsp;chars<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ha&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$hb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$b&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_b</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;switch(</span><span style="color: #0000BB">$type</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_DIFF</span><span style="color: #007700">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">abs</span><span style="color: #007700">(</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">)&nbsp;&lt;=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lineDiffMaxLines</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">diff</span><span style="color: #007700">(</span><span style="color: #0000BB">$ya&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">str_split</span><span style="color: #007700">(</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">$a</span><span style="color: #007700">)),</span><span style="color: #0000BB">$yb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">str_split</span><span style="color: #007700">(</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">$b</span><span style="color: #007700">)));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$same&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach(</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">)&nbsp;if(</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;==&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$same&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'ca'</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$same&nbsp;</span><span style="color: #007700">/&nbsp;</span><span style="color: #0000BB">max</span><span style="color: #007700">(</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$ya</span><span style="color: #007700">),</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$yb</span><span style="color: #007700">))&nbsp;&gt;=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lineDiffThreshold</span><span style="color: #007700">)&nbsp;foreach(</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">){&nbsp;</span><span style="color: #FF8000">//show&nbsp;char&nbsp;diff<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ha&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLineBlock</span><span style="color: #007700">(</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'t'</span><span style="color: #007700">],</span><span style="color: #0000BB">$ya</span><span style="color: #007700">,</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'sa'</span><span style="color: #007700">],</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'ca'</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$hb&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLineBlock</span><span style="color: #007700">(</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'t'</span><span style="color: #007700">],</span><span style="color: #0000BB">$yb</span><span style="color: #007700">,</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'sb'</span><span style="color: #007700">],</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'cb'</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_SPACE</span><span style="color: #007700">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">++){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$common&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">trim</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list(</span><span style="color: #0000BB">$pa</span><span style="color: #007700">,</span><span style="color: #0000BB">$qa</span><span style="color: #007700">)&nbsp;=&nbsp;</span><span style="color: #0000BB">array_map</span><span style="color: #007700">(</span><span style="color: #DD0000">'str_split'</span><span style="color: #007700">,</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #0000BB">$common</span><span style="color: #007700">,</span><span style="color: #0000BB">$a</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">],</span><span style="color: #0000BB">2</span><span style="color: #007700">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list(</span><span style="color: #0000BB">$pb</span><span style="color: #007700">,</span><span style="color: #0000BB">$qb</span><span style="color: #007700">)&nbsp;=&nbsp;</span><span style="color: #0000BB">array_map</span><span style="color: #007700">(</span><span style="color: #DD0000">'str_split'</span><span style="color: #007700">,</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #0000BB">$common</span><span style="color: #007700">,</span><span style="color: #0000BB">$b</span><span style="color: #007700">[</span><span style="color: #0000BB">$i</span><span style="color: #007700">],</span><span style="color: #0000BB">2</span><span style="color: #007700">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(</span><span style="color: #0000BB">$pa&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;</span><span style="color: #0000BB">$pb&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;(</span><span style="color: #0000BB">end</span><span style="color: #007700">(</span><span style="color: #0000BB">$pa</span><span style="color: #007700">)&nbsp;==&nbsp;</span><span style="color: #0000BB">end</span><span style="color: #007700">(</span><span style="color: #0000BB">$pb</span><span style="color: #007700">))&nbsp;&amp;&amp;&nbsp;</span><span style="color: #0000BB">array_pop</span><span style="color: #007700">(</span><span style="color: #0000BB">$pa</span><span style="color: #007700">))&nbsp;</span><span style="color: #0000BB">$common&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_pop</span><span style="color: #007700">(</span><span style="color: #0000BB">$pb</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$common</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(</span><span style="color: #0000BB">$qa&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;</span><span style="color: #0000BB">$qb&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;(</span><span style="color: #0000BB">$qa</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]&nbsp;==&nbsp;</span><span style="color: #0000BB">$qb</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">])&nbsp;&amp;&amp;&nbsp;</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$qa</span><span style="color: #007700">))&nbsp;</span><span style="color: #0000BB">$common&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$qb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ha&nbsp;</span><span style="color: #007700">.=&nbsp;(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"\n"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLineSpace</span><span style="color: #007700">(</span><span style="color: #0000BB">$pa</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">$common</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLineSpace</span><span style="color: #007700">(</span><span style="color: #0000BB">$qa</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$hb&nbsp;</span><span style="color: #007700">.=&nbsp;(</span><span style="color: #0000BB">$i&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"\n"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLineSpace</span><span style="color: #007700">(</span><span style="color: #0000BB">$pb</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">$common</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLineSpace</span><span style="color: #007700">(</span><span style="color: #0000BB">$qb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//prefixes:&nbsp;l&nbsp;=&nbsp;line&nbsp;number&nbsp;column,&nbsp;c&nbsp;=&nbsp;code&nbsp;column<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$tr&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;tr&nbsp;class='block-</span><span style="color: #0000BB">$index</span><span style="color: #DD0000">&nbsp;type-</span><span style="color: #0000BB">$type</span><span style="color: #DD0000">'&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$la&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;td&nbsp;class='line'&gt;"&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">range</span><span style="color: #007700">(</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">))&nbsp;:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">"&lt;/td&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;td&nbsp;class='code&nbsp;side-a'&gt;"&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$ha&nbsp;</span><span style="color: #007700">?:&nbsp;</span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">$a</span><span style="color: #007700">)))&nbsp;.&nbsp;</span><span style="color: #DD0000">"\n&lt;/td&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$lb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;td&nbsp;class='line'&gt;"&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">range</span><span style="color: #007700">(</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">))&nbsp;:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #DD0000">"&lt;/td&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;td&nbsp;class='code&nbsp;side-b'&gt;"&nbsp;</span><span style="color: #007700">.&nbsp;(</span><span style="color: #0000BB">$hb&nbsp;</span><span style="color: #007700">?:&nbsp;</span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">,</span><span style="color: #0000BB">$b</span><span style="color: #007700">)))&nbsp;.&nbsp;</span><span style="color: #DD0000">"\n&lt;/td&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$td&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;td&nbsp;class='line'&gt;&lt;/td&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;switch(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlMode</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">HTML_MODE_VERTICAL</span><span style="color: #007700">:&nbsp;return&nbsp;</span><span style="color: #0000BB">$type&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$tr$la$lb$ca</span><span style="color: #DD0000">&lt;/tr&gt;"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">:&nbsp;(</span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$tr$la$td$ca</span><span style="color: #DD0000">&lt;/tr&gt;"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;.&nbsp;(</span><span style="color: #0000BB">$b&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$tr$td$lb$cb</span><span style="color: #DD0000">&lt;/tr&gt;"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;return&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$tr$la$ca$lb$cb</span><span style="color: #DD0000">&lt;/tr&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;HTML&nbsp;diff&nbsp;with&nbsp;markup.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;mixed&nbsp;$head&nbsp;&nbsp;Table&nbsp;head&nbsp;(string;&nbsp;table&nbsp;row&nbsp;with&nbsp;4&nbsp;columns:&nbsp;line&nbsp;A,&nbsp;code&nbsp;A,&nbsp;line&nbsp;B,&nbsp;code&nbsp;B).&nbsp;Set&nbsp;to&nbsp;true&nbsp;for&nbsp;a<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;default&nbsp;head,&nbsp;or&nbsp;provide&nbsp;an&nbsp;array&nbsp;with&nbsp;the&nbsp;column&nbsp;headers&nbsp;(2&nbsp;=&nbsp;only&nbsp;for&nbsp;code&nbsp;columns,&nbsp;or&nbsp;4&nbsp;=&nbsp;all&nbsp;columns).<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;&nbsp;HTML&nbsp;table.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">asHtml</span><span style="color: #007700">(</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">===&nbsp;</span><span style="color: #0000BB">true</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">defaultHead</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">is_array</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">)){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_values</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">))&nbsp;&lt;&nbsp;</span><span style="color: #0000BB">4</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;[</span><span style="color: #DD0000">'#'</span><span style="color: #007700">,</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">),</span><span style="color: #DD0000">'#'</span><span style="color: #007700">,</span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$head</span><span style="color: #007700">)];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$la&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;th&nbsp;class='line'&gt;</span><span style="color: #007700">{</span><span style="color: #0000BB">$head</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]}</span><span style="color: #DD0000">&lt;/th&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;th&nbsp;class='code'&gt;</span><span style="color: #007700">{</span><span style="color: #0000BB">$head</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]}</span><span style="color: #DD0000">&lt;/th&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$lb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;th&nbsp;class='line'&gt;</span><span style="color: #007700">{</span><span style="color: #0000BB">$head</span><span style="color: #007700">[</span><span style="color: #0000BB">2</span><span style="color: #007700">]}</span><span style="color: #DD0000">&lt;/th&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;th&nbsp;class='code'&gt;</span><span style="color: #007700">{</span><span style="color: #0000BB">$head</span><span style="color: #007700">[</span><span style="color: #0000BB">3</span><span style="color: #007700">]}</span><span style="color: #DD0000">&lt;/th&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$th&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;th&nbsp;class='line'&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlMode</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">HTML_MODE_VERTICAL</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;tr&gt;</span><span style="color: #0000BB">$la$th</span><span style="color: #DD0000">&lt;/th&gt;</span><span style="color: #0000BB">$ca</span><span style="color: #DD0000">&lt;/tr&gt;&lt;tr&gt;</span><span style="color: #0000BB">$th$lb$cb</span><span style="color: #DD0000">&lt;/tr&gt;"</span><span style="color: #007700">;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;</span><span style="color: #0000BB">$head&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;tr&gt;</span><span style="color: #0000BB">$la$ca$lb$cb</span><span style="color: #DD0000">&lt;/tr&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$cols&nbsp;</span><span style="color: #007700">=&nbsp;[</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">HTML_MODE_VERTICAL&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">3</span><span style="color: #007700">][</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlMode</span><span style="color: #007700">]&nbsp;??&nbsp;</span><span style="color: #0000BB">4</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$skip&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"&lt;tr&nbsp;class='skip'&gt;&lt;td&nbsp;colspan='</span><span style="color: #0000BB">$cols</span><span style="color: #DD0000">'&gt;</span><span style="color: #007700">{</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">skipTemplate</span><span style="color: #007700">}</span><span style="color: #DD0000">&lt;/td&gt;&lt;/tr&gt;\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$last&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff</span><span style="color: #007700">)&nbsp;-&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$body&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;foreach(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_diff&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">=&gt;&nbsp;[</span><span style="color: #DD0000">'t'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #DD0000">'sa'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #DD0000">'ca'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #DD0000">'sb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #DD0000">'cb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">])&nbsp;switch(</span><span style="color: #0000BB">$t</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$body&nbsp;</span><span style="color: #007700">.=&nbsp;(</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">&lt;=&nbsp;(</span><span style="color: #0000BB">$x&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extra</span><span style="color: #007700">)&nbsp;*&nbsp;</span><span style="color: #0000BB">2&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">extraAllThreshold</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$index</span><span style="color: #007700">,</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">)&nbsp;</span><span style="color: #FF8000">//show&nbsp;complete&nbsp;equal&nbsp;block&nbsp;since&nbsp;it&nbsp;is&nbsp;relativly&nbsp;small<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">:&nbsp;(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$index</span><span style="color: #007700">,</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$x</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$x</span><span style="color: #007700">)&nbsp;:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">str_replace</span><span style="color: #007700">(</span><span style="color: #DD0000">'*'</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">-&nbsp;(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">$x&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">)&nbsp;-&nbsp;(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$last&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">$x&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">),&nbsp;</span><span style="color: #0000BB">$skip</span><span style="color: #007700">)&nbsp;.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$last&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$index</span><span style="color: #007700">,</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$ca&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$x</span><span style="color: #007700">,</span><span style="color: #0000BB">$x</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">$cb&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$x</span><span style="color: #007700">,</span><span style="color: #0000BB">$x</span><span style="color: #007700">)&nbsp;:&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_DIFF</span><span style="color: #007700">:&nbsp;</span><span style="color: #FF8000">//check&nbsp;for&nbsp;white-space-only&nbsp;diffs&nbsp;inside&nbsp;this&nbsp;block<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach((</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">diff</span><span style="color: #007700">(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">array_map</span><span style="color: #007700">(</span><span style="color: #DD0000">'trim'</span><span style="color: #007700">,</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_a</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">)),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">array_map</span><span style="color: #007700">(</span><span style="color: #DD0000">'trim'</span><span style="color: #007700">,</span><span style="color: #0000BB">array_slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_b</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">)),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">))&nbsp;as&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">)&nbsp;if(</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'t'</span><span style="color: #007700">]&nbsp;==&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">$block</span><span style="color: #007700">[</span><span style="color: #DD0000">'ca'</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">/&nbsp;</span><span style="color: #0000BB">max</span><span style="color: #007700">(</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">)&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">whiteSpaceThreshold</span><span style="color: #007700">){&nbsp;</span><span style="color: #FF8000">//show&nbsp;white-space&nbsp;blocks&nbsp;differently<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">foreach(</span><span style="color: #0000BB">$diff&nbsp;</span><span style="color: #007700">as&nbsp;</span><span style="color: #0000BB">$sub&nbsp;</span><span style="color: #007700">=&gt;&nbsp;[</span><span style="color: #DD0000">'t'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #DD0000">'sa'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #DD0000">'ca'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #DD0000">'sb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #DD0000">'cb'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$cb</span><span style="color: #007700">])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$body&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #DD0000">'-'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$sub</span><span style="color: #007700">,</span><span style="color: #0000BB">$t&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_EQUAL&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">TYPE_SPACE&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #FF8000">//else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">default:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$body&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlLine</span><span style="color: #007700">(</span><span style="color: #0000BB">$index</span><span style="color: #007700">,</span><span style="color: #0000BB">$t</span><span style="color: #007700">,</span><span style="color: #0000BB">$sa</span><span style="color: #007700">,</span><span style="color: #0000BB">$ca</span><span style="color: #007700">,</span><span style="color: #0000BB">$sb</span><span style="color: #007700">,</span><span style="color: #0000BB">$cb</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #DD0000">"&lt;table&nbsp;class='diff&nbsp;</span><span style="color: #007700">{</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">htmlMode</span><span style="color: #007700">}</span><span style="color: #DD0000">'&gt;&lt;thead&gt;</span><span style="color: #0000BB">$head</span><span style="color: #DD0000">&lt;/thead&gt;&lt;tbody&gt;</span><span style="color: #0000BB">$body</span><span style="color: #DD0000">&lt;/tbody&gt;&lt;/table&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">__toString</span><span style="color: #007700">(){<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">asText</span><span style="color: #007700">()&nbsp;?:&nbsp;</span><span style="color: #DD0000">''</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /><br />}</span>
</span>
</code></div>]]></description>
      <pubDate>Sat, 06 Sep 2025 20:54:18 +0200</pubDate>
      <category>nerd</category>
      <category>prog</category>
    </item>
    <item>
      <title>Waarom ik liever met stroom werk dan met water</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=599</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=599</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=599#Comments</comments>
      <description><![CDATA[Als je de stroom er af haalt (specifieke groep), dan is de stroom er af (op die specifieke groep; de rest van de apparaten doet het dus nog). Je doet je ding (zonder een opdonder te krijgen), en schakelt de stroom weer in. Klus geklaard.<br>
<br>
Met water:
<ul>
<li>Je sluit de specifieke groep af (we hebben hier twee "takken" vanaf de watermeter), maar dan blijft het water gewoon stromen, omdat het "groepskraantje" al zo oud is, dat het leertje helemaal versleten is.</li>
<li>Dan dus toch maar de hoofdkraan afsluiten (niemand naar de WC, douchen, enz) - die spontaan begint te lekken, omdat ie maar 1x/jaar gebruikt wordt. Dat duurt weer een paar weken voordat dat lekken weer helemaal weg is.</li>
<li>Vervolgens komt er nog steeds overal water uit. Niet zo hard meer, maar nog wel een redelijke straal. D'r staat hier een zonneboiler op zolder, en de wasmachine kraan (op zolder) ontlucht automatich, dus dat gaat net zo lang door totdat de zonneboiler helemaal leeg is ...</li>
<li>Daar wil/kun je niet op wachten, dus dan ga je toch maar met een nalekkende leiding aan de gang. Snel de oude koppeling er af, en de nieuwe er op (gelukkig knel - solderen kun je nu wel vergeten, dat krijg je niet warm met doorlekkend water). Aandraaien, hoofdkraan weer open, klaar.</li>
<li>Nee, natuurlijk niet. Nu lekt het altijd nog een dag of wat na. Hoeveel teflon tape je er ook tussen doet, hoe hard je de knelkoppelingen ook aandraait, het lekt altijd. Ook hier gaan een paar dagen overheen, totdat alle kleine gaatjes uiteindelijk dicht zitten met het beetje verontreiniging wat er in leidingwater zit (een beetje vet er tussen wil ook wel helpen, maar dan moet je de boel weer open draaien - hoofdkraan dicht, floderen met restwater, enz).</li>
</ul>]]></description>
      <pubDate>Sat, 05 Apr 2025 15:10:23 +0200</pubDate>
      <category>klus</category>
      <category>rant</category>
    </item>
    <item>
      <title>De $HITWARE meme coin</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=598</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=598</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=598#Comments</comments>
      <description><![CDATA[Ik heb net een miljoen random tekenreeksen aangemaakt. Bijvoorbeeld deze <code>LZ2PVZhI9eFb4xrFU8ANT1NM7qTUvH5o</code>, deze <code>JuFszNqoeTuTNcrRIUAyCESdTJ0p4ETA</code>, en deze <code>AfIaoLCl78gbpDINzm7sl0U7Z0ax41Hw</code>. Die staan allemaal op mijn naam. Deze <code>oDDPrM3FCblvFeUx66gMwvr4nbRB3mAj</code> heb ik net aan mevrouw verkocht voor &euro; 1,-. Dus op papier ben ik nu miljonair - <a href="" title="">of zoiets</a> ...<br>
<br>
<small>Instant update: ik heb de computer nog even laten rammelen: nu zijn het er een miljard; en ik heb er nog een verkocht voor &euro; 10,-: multi-miljardair FTW w00t w00t!</small>]]></description>
      <pubDate>Tue, 21 Jan 2025 19:49:37 +0100</pubDate>
    </item>
    <item>
      <title>Backup</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=597</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=597</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=597#Comments</comments>
      <description><![CDATA[Op zolder staat nog een Windows 10 "server" (een <a href="&quot;https://en.wikipedia.org/wiki/Next_Unit_of_Computing" title="" target="_blank">NUC</a> zonder toetsenbord en beeldscherm),
die <a href="https://learn.microsoft.com/en-us/lifecycle/announcements/windows-10-22h2-end-of-support-update" title="" target="_blank">eind dit jaar</a> geen updates meer gaat krijgen.
Tijd om er ook een <a href="/blog/578/nieuwe_server" title="">Linux server</a> van te maken. Het ding heeft tegenwoordig (oude main server) nog een paar "bijbaantjes":<ul>
<li>Unifi controller</li>
<li>Virtual Machines (Hyper-V) om een beetje te rommelen met Linux</li>
<li>Stalling voor de backup</li>
</ul><br>
Dat laatste is de reden voor dit hele relaas. Ik maak namelijk een backup van de backup ...<ul>
<li>De laptops van de kinderen <a href="https://www.resilio.com/sync/" title="" target="_blank">synchroniseren live</a> met hun "Documenten" map op de server (ze kunnen dus naadloos wisselen tussen laptop en desktop thuis).</li>
<li>Elke nacht ZIP ik naast deze "Documenten" mappen (ook de onze), ook nog de server mappen, database dumps, en e-mail data in een dag-van-de-week backup map. Als je iets verkloot kun je dus nog altijd een week "terug kijken".</li>
<li>Van bovenstaande bestanden, en ook nog onze gedeelde documenten mappen (foto's, enz) maak ik dan elke nacht een kopie naar de Windows server. Deze server is niet "van buiten" benaderbaar, en ook niet vanuit de main server (deze server benadert de main server, en niet andersom). Theoretisch kan er dus niemand bij.</li>
<li>Wekelijks maak ik ook nog een backup op een portable disk. Behalve tijdens het maken van de backup is deze disk altijd helemaal losgekoppeld (power + data). Een of ander worm-virus, of een blikseminslag heeft dus geen invloed op deze backup. Tevens houd ik op deze disk een archief bij: van gewijzigde of verwijderde bestanden wordt de oude versie bewaard - je kunt dus tot jaren terug zien hoe en wanneer een bestand precies is gewijzigd.</li>
<li>Dit zijn allemaal lokale backups, die hier dus in huis liggen. Als de brand er nou een keer in gaat is nog steeds alles weg. Daarom is er ook nog een off-site backup. Eén keer in de maand maak ik een backup op een (encrypted) portable disk die dus buitenshuis bewaard wordt.</li>
<ul><br>
In dat laatste zit nu het probleem, want dit gaat via VPN en <a href="https://en.wikipedia.org/wiki/Remote_Desktop_Protocol" title="" target="_blank">remote-desktop</a> naar de Windows server. En die is er dus zometeen niet meer. De server nog wel, waar ook nog gewoon de nachtelijke backup op gestald gaat worden, maar het is geen Windows meer. En het maken van die maandelijkse off-site backup gaat nu eenmaal het makkelijkst via Windows/RDP.<br>
<br>
En daarom ben ik nu dus al een week aan het "klungelen" om de boel helemaal te automatiseren, en volledig platform onafhankelijk te maken (script dat zowel onder Linux als Windows is te gebruiken). Ja mensen, soms is "de cloud" ook wel zo makkelijk (als je het <i>niet</i> erg vindt om al je data bij een ander te stallen) ...]]></description>
      <pubDate>Mon, 06 Jan 2025 22:51:45 +0100</pubDate>
      <category>admin</category>
      <category>nerd</category>
    </item>
    <item>
      <title>Nieuwe vriezer</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=596</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=596</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=596#Comments</comments>
      <description><![CDATA[Na <a href="/blog/452/energieverbuik" title="">14,5 jaar</a> heeft de vriezer het uiteindelijk dan toch begeven (op de respectabele leeftijd van zo'n 30 jaar). En aangezien we nog geen nieuwe keuken nodig hebben (gewoon op tijd repareren, voordat het echt "helemaal stuk" is), hebben we toch maar een nieuwe gekocht. Vooral omdat de oude vriezer heel langzaam de geest aan het geven was, was "snel leverbaar" een van de belangrijkste kenmerken. En aangezien dit Nederland is, werd dat "vandaag voor 23:00 besteld, morgen in huis". Terwijl de oude, reeds uitgebouwde vriezer buiten op de stoep heel langzaam stond te ontdooien, werd de nieuwe gemonteerd (zelfde inbouwmaat, dus die "schuif je er zo in"), en kon het meeste spul nog net in bevroren toestand worden overgeheveld.<br>
<br>
Maar dan de belangrijkste vraag: wat is het energieverbruik; is dat nu echt zoveel beter (categorie E - dat is <a href="https://www.consumentenbond.nl/koelkast/energielabel" title="" target="_blank">recentelijk opnieuw ingedeeld</a>, omdat alles in A+++++ zat)?<br>
<br>
<img src="/blog/2024/11/Id596/app-graph-vriezer.png" style="width:100%" alt="grafiek van stroomverbruik over de dag (rood, linker schaal) en totaal (blauw, rechter schaal)"><br>
<br>
<ul>
<li>Op vrijdag de 25<sup>e</sup> heeft iemand de deur niet goed dicht gedaan, of zijn er boodschappen gedaan (die ingevroren moesten worden).</li>
<li>Op maandag de 28<sup>e</sup> begint de vriezer dan langzamerhand te falen. Hij moet steeds langer draaien om de boel op temperatuur te houden, en rond een uur of 18:00 's avond staat ie gewoon non-stop te ploeteren.</li>
<li>Dinsdag en woensdag gaat dat nog redelijk goed, maar donderdag komen we er achter dat ie het echt niet meer trekt - ook niet na nog wat met de instellingen gepield te hebben. Achteraf gezien hadden we dat natuurlijk al aan bovenstaande grafiek kunnen zien, maar omdat het stroomverbruik heel langzaam toenam kwam er geen waarschuwingsmailtje.</li>
<li>Donderdagavond de nieuwe vriezer besteld. Vrijdag rond een uur of 13:00 de oude uitgebouwd en buiten gezet. Nieuwe vriezer rond 14:00 geleverd, ingebouwd, en om 19:00 ingeschakeld.</li>
<li>Op zaterdag moet ie er dan nog even flink aan trekken om alles weer onder nul te krijgen, en vanaf zondag staat ie gewoon "in bedrijf" te pendelen.</li>
</ul><br>
Het huidige stroomverbruik is ongeveer 25 tot 30% van de oude (die slurpte gemiddeld 1 kWh/dag). Een enorme besparing dus van zo'n 265 kWh/jaar. Met de huidige terugleververgoeding (zonnepanelen), in combinatie met de salderingsregeling (opbrengsten in de zomer mogen met verbruik in de winter verrekend worden), levert een teruggeleverde kWh (we produceren <a href="/blog/587/we-want-more" title="">meer dan we verbruiken</a>) nog maar 2,884 cent op. Die enorme afname van het verbruik levert op jaarbasis dus maar &euro;7,65 op. Valt een beetje tegen ...<br>
<br>
(wat ook een beetje tegen valt: de nieuwe vriezer is zo goed geïsoleerd, dat er door die dikke wanden veel minder in past)]]></description>
      <pubDate>Wed, 06 Nov 2024 22:12:13 +0100</pubDate>
      <category>nerd</category>
    </item>
    <item>
      <title>Gratis postcode tabel</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=595</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=595</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=595#Comments</comments>
      <description><![CDATA[Je kent het wel van de webshop: alleen postcode en huisnummer invoeren, en de site voegt vanzelf je woonplaats en straatnaam in. Super makkelijk, geen spelfouten. Deze data komt uit een "postcode tabel". Vroeger moest je daar voor betalen, en waren er allerlei initiatieven om deze data bij elkaar te harken door overal adressen te scrapen (bijvoorbeeld het adres op de website van een bedrijf).<br>
<br>
Tegenwoordig kun je deze data "in principe" gratis verkrijgen door de data van het Kadaster te downloaden en uit te pluizen. Gewoon alle data over de bebouwing negeren, en nog even combineren met de (eveneens gratis) lijst van gemeentes van het CBS. Overal lees je dan dat dit wel een erg ingewikkelde klus is (veel data, grote bestanden - 3,5Gb ZIP, met daarin <i>weer</i> meerdere ZIP bestanden, met <i>daarin</i> weer een trits XML bestanden). Dat klinkt als een uitdaging ;-)<br>
<br>
Bij deze dus: de <a href="https://mist.shitware.nl/postcode">Royal Shitware Inc postcode tabel</a>. Gratis in gebruik, en inclusief PHP code om het helemaal zelf te doen (en naar eigen inzicht in een database te gieten). Garantie tot de deur. Als er onverwacht teveel gebruik van gemaakt wordt kan het zijn dat ik de deur weer dicht gooi.]]></description>
      <pubDate>Wed, 06 Nov 2024 22:01:29 +0100</pubDate>
      <category>prog</category>
    </item>
    <item>
      <title>Don't do drugs kids</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=594</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=594</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=594#Comments</comments>
      <description><![CDATA[<center><img title="moeder, vader, broertje, broer" src="http://shitware.nl/blog/2024/10/Id594/1977-07-03.jpg" alt=""></center><br>
Vandaag een jaar geleden is m'n broer(tje*) overleden <small>(* hij was een kop groter en een meter breder dan ik)</small>. Ik vermoed dat niemand dit 90's design weblog leest, maar ik ga er toch een stukje over schrijven.<br>
<br>
Al vanaf het begin waren m'n broertje en ik anders. Niet alleen qua doen en laten, maar ook qua uiterlijk. Als we samen op pad waren geloofde niemand dat we broers waren.
Vanaf de middelbare school was m'n broertje het feestbeest - daar waar ik de "serieuze student" was. Hij regelde de meiden, en ik zorgde ervoor dat onze "vissersboot met veel te grote motor" (waterskiën) volgetankt in het water lag.
Op een gegeven moment moest al dat feesten steeds vaker en steeds langer duren. En daar hoorde uiteraard "een pilletje" bij - anders houd je het niet vol.
Het pilletje werd een buisje, en vervolgens nog een hele sloot aan andere "geestverruimende middelen". En ook weer dozen vol weet ik veel wat voor andere pillen. Voor elk kwaaltje of "lichamelijke wens" was er wel een pil.
Dat kon uiteraard niet eeuwig goed gaan, en na een paar kwakkelende jaren is ie vorig jaar aan een hartstilstand overleden. Lichamelijk nog niet helemaal "naar de klote", maar de rikketik gewoon even stil gevallen onder die continue hoge belasting.
Ietwat onverwacht dus, maar toch ook niet helemaal onverwacht.<br>
<br>
46 jaar - 23 in elke eeuw. Altijd voor 200% geleefd, dus wel het maximale er uit gehaald, maar toch een beetje aan de vroege kant.
Nu, een jaar later, weet ik nog steeds niet hoe ik 'm moet missen: Z'n ongeremde enthousiasme, altijd vol met wilde ideeën (ook gewoon praktisch, zoals de inrichting van z'n woonkamer - niet alles was altijd drugs gerelateerd). Of "het gedoe"; als ie weer een terugval had, en je de scherven weer op moest rapen, en <i>weer</i> opnieuw beginnen (iedereen in z'n omgeving: familie, hulpverleners, enz). Het was een leuke, mooie, grappige jongen - maar wat kon ie er toch een puinhoop van maken ...<br>
<br>
<center><img src="http://shitware.nl/blog/2024/10/Id594/mark.jpg" alt=""></center>]]></description>
      <pubDate>Wed, 23 Oct 2024 12:00:00 +0200</pubDate>
    </item>
    <item>
      <title>JSON lines file handler (in PHP)</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=593</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=593</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=593#Comments</comments>
      <description><![CDATA[Werktechnisch zit ik met bakken data (denk terabyte) te kijken die we bijna nooit nodig hebben - alleen om bij "problemen" dingen uit te zoeken. Daarnaast is het ook nog niet in een vast formaat (geen vaste veldindeling). Teveel en te onhandig dus om een database mee lastig te vallen, maar alles zomaar in een file dumpen maakt het gestructureerd doorzoeken er ook niet handiger op. Enter <a href="https://jsonlines.org/" title="" target="_blank">JSON lines</a>: een text based format met op elke regel een JSON object. Een beetje een soort CSV zonder vaste kolomindeling. En daar moet je dan wat mee:<br>
<br>
<div class="PHP"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">namespace&nbsp;</span><span style="color: #0000BB">Rsi</span><span style="color: #007700">\</span><span style="color: #0000BB">Object</span><span style="color: #007700">;<br /><br /></span><span style="color: #FF8000">/**<br />&nbsp;*&nbsp;Manipulate&nbsp;a&nbsp;JSON&nbsp;lines&nbsp;file.<br />&nbsp;*/<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">JsonLinesFile</span><span style="color: #007700">{<br /><br />&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$delimiter&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Line&nbsp;delimiter.<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">$assoc&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">true</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//!&lt;&nbsp;Return&nbsp;data&nbsp;as&nbsp;assoc.array.<br /><br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;</span><span style="color: #0000BB">$_filename&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">__construct</span><span style="color: #007700">(</span><span style="color: #0000BB">$filename</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$filename</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Append&nbsp;data&nbsp;to&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;mixed&nbsp;$data<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;bool&nbsp;&nbsp;True&nbsp;on&nbsp;success.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">append</span><span style="color: #007700">(</span><span style="color: #0000BB">$data</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">file_put_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename</span><span style="color: #007700">,</span><span style="color: #0000BB">json_encode</span><span style="color: #007700">(</span><span style="color: #0000BB">$data</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">delimiter</span><span style="color: #007700">,</span><span style="color: #0000BB">LOCK_EX&nbsp;</span><span style="color: #007700">|&nbsp;</span><span style="color: #0000BB">FILE_APPEND</span><span style="color: #007700">)&nbsp;!==&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Clear&nbsp;(empty)&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;bool&nbsp;&nbsp;True&nbsp;on&nbsp;success.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">clear</span><span style="color: #007700">(){<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">file_put_contents</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename</span><span style="color: #007700">,</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;!==&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Walk&nbsp;through&nbsp;all&nbsp;lines&nbsp;in&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;callable&nbsp;$callback&nbsp;&nbsp;Function&nbsp;to&nbsp;call&nbsp;for&nbsp;each&nbsp;line.&nbsp;The&nbsp;line&nbsp;is&nbsp;in&nbsp;the&nbsp;first&nbsp;parameter,&nbsp;and&nbsp;the&nbsp;index&nbsp;in&nbsp;the&nbsp;file<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;(base-0)&nbsp;in&nbsp;the&nbsp;second.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;function&nbsp;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">is_file</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename</span><span style="color: #007700">)){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$f&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename</span><span style="color: #007700">,</span><span style="color: #DD0000">'r'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(!</span><span style="color: #0000BB">feof</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">))&nbsp;if(</span><span style="color: #0000BB">strlen</span><span style="color: #007700">(</span><span style="color: #0000BB">$line&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">fgets</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">))&nbsp;&amp;&amp;&nbsp;(</span><span style="color: #0000BB">call_user_func</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,</span><span style="color: #0000BB">$line</span><span style="color: #007700">,</span><span style="color: #0000BB">$index</span><span style="color: #007700">++)&nbsp;===&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">))&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">fclose</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Number&nbsp;of&nbsp;records&nbsp;in&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;int<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">count</span><span style="color: #007700">(){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(function()&nbsp;use&nbsp;(&amp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Decode&nbsp;a&nbsp;line.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$line&nbsp;&nbsp;Encoded&nbsp;JSON&nbsp;line.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;mixed&nbsp;&nbsp;Decoded&nbsp;data.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;function&nbsp;</span><span style="color: #0000BB">decode</span><span style="color: #007700">(</span><span style="color: #0000BB">$line</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;if(((</span><span style="color: #0000BB">$data&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">json_decode</span><span style="color: #007700">(</span><span style="color: #0000BB">$line</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">assoc</span><span style="color: #007700">))&nbsp;===&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">)&nbsp;&amp;&amp;&nbsp;(</span><span style="color: #0000BB">json_last_error</span><span style="color: #007700">()&nbsp;!=&nbsp;</span><span style="color: #0000BB">JSON_ERROR_NONE</span><span style="color: #007700">))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;\</span><span style="color: #0000BB">Exception</span><span style="color: #007700">(</span><span style="color: #0000BB">json_last_error_msg</span><span style="color: #007700">());<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$data</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Walk&nbsp;through&nbsp;all&nbsp;records&nbsp;in&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;callable&nbsp;$callback&nbsp;&nbsp;Function&nbsp;to&nbsp;call&nbsp;for&nbsp;each&nbsp;record.&nbsp;The&nbsp;data&nbsp;is&nbsp;in&nbsp;the&nbsp;first&nbsp;parameter,&nbsp;and&nbsp;the&nbsp;index&nbsp;in&nbsp;the&nbsp;file<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;(base-0)&nbsp;in&nbsp;the&nbsp;second.&nbsp;Return&nbsp;false&nbsp;to&nbsp;break.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">each</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(function(</span><span style="color: #0000BB">$line</span><span style="color: #007700">,</span><span style="color: #0000BB">$index</span><span style="color: #007700">)&nbsp;use&nbsp;(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">call_user_func</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">decode</span><span style="color: #007700">(</span><span style="color: #0000BB">$line</span><span style="color: #007700">),</span><span style="color: #0000BB">$index</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Retrieve&nbsp;a&nbsp;slice&nbsp;of&nbsp;the&nbsp;records&nbsp;in&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;$offset&nbsp;int&nbsp;&nbsp;Record&nbsp;to&nbsp;start&nbsp;from.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;$length&nbsp;int&nbsp;&nbsp;Number&nbsp;of&nbsp;records&nbsp;to&nbsp;return&nbsp;(when&nbsp;available).<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;array&nbsp;&nbsp;The&nbsp;selected&nbsp;records&nbsp;(key&nbsp;=&nbsp;index,&nbsp;value&nbsp;=&nbsp;data).<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">slice</span><span style="color: #007700">(</span><span style="color: #0000BB">$offset</span><span style="color: #007700">,</span><span style="color: #0000BB">$length</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$length&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">$offset</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$result&nbsp;</span><span style="color: #007700">=&nbsp;[];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(function(</span><span style="color: #0000BB">$line</span><span style="color: #007700">,</span><span style="color: #0000BB">$index</span><span style="color: #007700">)&nbsp;use&nbsp;(</span><span style="color: #0000BB">$offset</span><span style="color: #007700">,</span><span style="color: #0000BB">$length</span><span style="color: #007700">,&amp;</span><span style="color: #0000BB">$result</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&gt;=&nbsp;</span><span style="color: #0000BB">$offset</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$result</span><span style="color: #007700">[</span><span style="color: #0000BB">$index</span><span style="color: #007700">]&nbsp;=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">decode</span><span style="color: #007700">(</span><span style="color: #0000BB">$line</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;return&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//break<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">}<br />&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$result</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Filter&nbsp;the&nbsp;records&nbsp;in&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;callable&nbsp;$callback&nbsp;&nbsp;If&nbsp;this&nbsp;function&nbsp;returns&nbsp;true,&nbsp;the&nbsp;record&nbsp;is&nbsp;preserved.&nbsp;The&nbsp;data&nbsp;is&nbsp;in&nbsp;the&nbsp;first&nbsp;parameter,&nbsp;and<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;the&nbsp;index&nbsp;in&nbsp;the&nbsp;file&nbsp;(base-0)&nbsp;in&nbsp;the&nbsp;second.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;bool&nbsp;&nbsp;True&nbsp;on&nbsp;success.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">filter</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$f&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #0000BB">$temp&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #DD0000">'-'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">bin2hex</span><span style="color: #007700">(</span><span style="color: #0000BB">random_bytes</span><span style="color: #007700">(</span><span style="color: #0000BB">16</span><span style="color: #007700">)),</span><span style="color: #DD0000">'w'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;try{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(function(</span><span style="color: #0000BB">$line</span><span style="color: #007700">,</span><span style="color: #0000BB">$index</span><span style="color: #007700">)&nbsp;use&nbsp;(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,</span><span style="color: #0000BB">$f</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">call_user_func</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">decode</span><span style="color: #007700">(</span><span style="color: #0000BB">$line</span><span style="color: #007700">),</span><span style="color: #0000BB">$index</span><span style="color: #007700">))&nbsp;</span><span style="color: #0000BB">fputs</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">,</span><span style="color: #0000BB">$line</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">fclose</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">rename</span><span style="color: #007700">(</span><span style="color: #0000BB">$temp</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;catch(\</span><span style="color: #0000BB">Exception&nbsp;$e</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #0000BB">$temp</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;</span><span style="color: #0000BB">$e</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Edit&nbsp;the&nbsp;records&nbsp;in&nbsp;the&nbsp;file.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;callable&nbsp;$callback&nbsp;&nbsp;Function&nbsp;that&nbsp;returns&nbsp;the&nbsp;modified&nbsp;record.&nbsp;The&nbsp;original&nbsp;data&nbsp;is&nbsp;in&nbsp;the&nbsp;first&nbsp;parameter,&nbsp;and&nbsp;the<br />&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;index&nbsp;in&nbsp;the&nbsp;file&nbsp;(base-0)&nbsp;in&nbsp;the&nbsp;second.&nbsp;Return&nbsp;false&nbsp;to&nbsp;remove&nbsp;the&nbsp;record,&nbsp;or&nbsp;true&nbsp;to&nbsp;keep&nbsp;the&nbsp;original&nbsp;record.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;bool&nbsp;&nbsp;True&nbsp;on&nbsp;success.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">edit</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$f&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #0000BB">$temp&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #DD0000">'-'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">bin2hex</span><span style="color: #007700">(</span><span style="color: #0000BB">random_bytes</span><span style="color: #007700">(</span><span style="color: #0000BB">16</span><span style="color: #007700">)),</span><span style="color: #DD0000">'w'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;try{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">lines</span><span style="color: #007700">(function(</span><span style="color: #0000BB">$line</span><span style="color: #007700">,</span><span style="color: #0000BB">$index</span><span style="color: #007700">)&nbsp;use&nbsp;(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,</span><span style="color: #0000BB">$f</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((</span><span style="color: #0000BB">$data&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">call_user_func</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">decode</span><span style="color: #007700">(</span><span style="color: #0000BB">$line</span><span style="color: #007700">),</span><span style="color: #0000BB">$index</span><span style="color: #007700">))&nbsp;!==&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">fputs</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">,</span><span style="color: #0000BB">$data&nbsp;</span><span style="color: #007700">===&nbsp;</span><span style="color: #0000BB">true&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">$line&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">json_encode</span><span style="color: #007700">(</span><span style="color: #0000BB">$data</span><span style="color: #007700">)&nbsp;.&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">delimiter</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">fclose</span><span style="color: #007700">(</span><span style="color: #0000BB">$f</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">rename</span><span style="color: #007700">(</span><span style="color: #0000BB">$temp</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">_filename</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;catch(\</span><span style="color: #0000BB">Exception&nbsp;$e</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #0000BB">$temp</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;</span><span style="color: #0000BB">$e</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br /><br />}</span>
</span>
</code></div>]]></description>
      <pubDate>Sat, 27 Apr 2024 22:18:03 +0200</pubDate>
      <category>prog</category>
    </item>
    <item>
      <title>Vrij ingewikkelde hotel wisselschakeling</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=592</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=592</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=592#Comments</comments>
      <description><![CDATA[In het kader van de <a href="https://shitware.nl/blog/590/afstandsbediening" title="" target="_blank">home automation</a> had ik de keukenlamp al via een <a href="https://www.shelly.com/en/products/shop/shelly-1" title="" target="_blank">Shelly1</a> gekoppeld. Daar kun je leuke, maar ook gewoon handige dingen mee doen. Zo zit de schakelaar van de keukenlamp hier aan de wooonkamerzijde, dus als je door de buitendeur binnen komt (met je vieze schoenen; aan de andere kant van de keuken) moet je eerst in het donker je schoenen uittrekken, voordat je de lamp aan kunt doen. Via de Shelly heb ik dit ondervangen door de keukenlamp ook automatisch aan te doen als de bewegingsmelder in de achtertuin aan gaat (en het donker is).<br>
<br>
Dat lost het probleem echter "van buiten naar binnen" op. Als je naar buiten gaat, met de lamp aan, en smerige schoenen aan je voeten, kun je de lamp niet meer uit doen. Hiervoor moet je dan een thuisblijver aanwijzen, of de Shelly even "via de app" schakelen (gedoe als je al handschoenen aan hebt). Enorm first world problem dus. Gelukkig zitten er bij de keukendeur een viertal schakelaars voor de buitenlampen, waarvan er een niet gebruikt werd. Deze laatste heb ik nu aan <i>nog</i> een Shelly gehangen, en weer teruggekoppeld naar de eerste Shelly. Nu kunnen we de keukenlamp dus vanaf twee plekken bedienen - hoezee! Eigenlijk net zoiets als de gemiddelde <a href="https://nl.wikipedia.org/wiki/Wisselschakeling" title="" target="_blank">wisselschakeling</a> voor het trappengat, maar dan stukken nodeloos complexer.<br>
<br>
Alhoewel: het biedt natuurlijk ook wel weer meer mogelijkheden. Zo kun je nu met "dubbel klik" (snel aan/uit) de "flood light" onder de dakgoot bedienen, en zullen er binnenkort vast nog wel meer "handigheidjes" volgen. Tijd om de handleiding voor het huis weer eens bij te werken ...]]></description>
      <pubDate>Sat, 27 Apr 2024 17:52:11 +0200</pubDate>
    </item>
    <item>
      <title>Base-N encoding en decoding (in PHP)</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=591</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=591</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=591#Comments</comments>
      <description><![CDATA[Omdat (o.a.) Marktplaats de onhebbelijkheid heeft om URL's standaard naar lower case ("kleine letters") te drukken kun je daar niet met <a href="https://nl.wikipedia.org/wiki/Base64" title="" target="_blank">base-64 encoding</a> werken (die gebruikt zowel hoofd- als kleine letters - wat daardoor dus onbruikbaar wordt). Maar om nou meteen terug te schakelen naar <a href="https://nl.wikipedia.org/wiki/Hexadecimaal_talstelsel" title="" target="_blank">hexadecimaal</a> is ook zo wat. PHP biedt zelf geen ondersteuning voor andere encodings, dus dan moet je het zelf maar doen (online is van alles te vinden, maar niet zo geheugen/processor-efficiënt als deze!):<br>
<div class="PHP"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Base&nbsp;encode&nbsp;parameters.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$base&nbsp;&nbsp;Base&nbsp;characters.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;$length&nbsp;&nbsp;Number&nbsp;of&nbsp;characters&nbsp;in&nbsp;base.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;$bits&nbsp;&nbsp;Number&nbsp;of&nbsp;bits&nbsp;possible&nbsp;in&nbsp;character&nbsp;range&nbsp;(rounded&nbsp;up).<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;int&nbsp;$max&nbsp;&nbsp;Maximum&nbsp;value&nbsp;in&nbsp;base&nbsp;without&nbsp;data&nbsp;loss.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;bool&nbsp;$oversize&nbsp;&nbsp;True&nbsp;when&nbsp;the&nbsp;bit&nbsp;size&nbsp;is&nbsp;too&nbsp;large&nbsp;for&nbsp;the&nbsp;base.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">protected&nbsp;static&nbsp;function&nbsp;</span><span style="color: #0000BB">baseParams</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">$base</span><span style="color: #007700">,&amp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">,&amp;</span><span style="color: #0000BB">$bits</span><span style="color: #007700">,&amp;</span><span style="color: #0000BB">$max</span><span style="color: #007700">,&amp;</span><span style="color: #0000BB">$oversize</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;if((</span><span style="color: #0000BB">$length&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">strlen</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">))&nbsp;&lt;&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">)&nbsp;throw&nbsp;new&nbsp;\</span><span style="color: #0000BB">ValueError</span><span style="color: #007700">(</span><span style="color: #DD0000">'Not&nbsp;enough&nbsp;characters&nbsp;in&nbsp;base'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">count</span><span style="color: #007700">(</span><span style="color: #0000BB">array_unique</span><span style="color: #007700">(</span><span style="color: #0000BB">$base&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">str_split</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">)))&nbsp;&lt;&nbsp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">)&nbsp;throw&nbsp;new&nbsp;\</span><span style="color: #0000BB">ValueError</span><span style="color: #007700">(</span><span style="color: #DD0000">'Duplicate&nbsp;characters&nbsp;in&nbsp;base'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$bits&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;while((</span><span style="color: #0000BB">$max&nbsp;</span><span style="color: #007700">=&nbsp;(</span><span style="color: #0000BB">1&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;++</span><span style="color: #0000BB">$bits</span><span style="color: #007700">))&nbsp;&lt;&nbsp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$oversize&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$max&nbsp;</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$max&nbsp;</span><span style="color: #007700">&gt;&gt;=&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Encode&nbsp;a&nbsp;string&nbsp;with&nbsp;a&nbsp;base&nbsp;set&nbsp;of&nbsp;characters.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$base&nbsp;&nbsp;Base&nbsp;characters.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$str&nbsp;&nbsp;String&nbsp;to&nbsp;encode.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;&nbsp;String&nbsp;encoded&nbsp;with&nbsp;characters&nbsp;from&nbsp;base.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;static&nbsp;function&nbsp;</span><span style="color: #0000BB">baseEncode</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">,</span><span style="color: #0000BB">$str</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$result&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">strlen</span><span style="color: #007700">(</span><span style="color: #0000BB">$str</span><span style="color: #007700">)){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">baseParams</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">,</span><span style="color: #0000BB">$length</span><span style="color: #007700">,</span><span style="color: #0000BB">$bits</span><span style="color: #007700">,</span><span style="color: #0000BB">$max</span><span style="color: #007700">,</span><span style="color: #0000BB">$oversize</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$fill&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$position&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//bit&nbsp;buffer,&nbsp;buffer&nbsp;size,&nbsp;fillers&nbsp;in&nbsp;buffer,&nbsp;position&nbsp;in&nbsp;string<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">while((</span><span style="color: #0000BB">$position&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">)&nbsp;||&nbsp;(</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">&gt;&nbsp;</span><span style="color: #0000BB">$fill</span><span style="color: #007700">)){&nbsp;</span><span style="color: #FF8000">//still&nbsp;bytes&nbsp;or&nbsp;bits&nbsp;to&nbsp;process<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if(</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$bits</span><span style="color: #007700">){&nbsp;</span><span style="color: #FF8000">//add&nbsp;next&nbsp;byte&nbsp;(or&nbsp;filler)&nbsp;to&nbsp;buffer<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">&lt;&lt;=&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$position&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">ord</span><span style="color: #007700">(</span><span style="color: #0000BB">$str</span><span style="color: #007700">[</span><span style="color: #0000BB">$position</span><span style="color: #007700">++]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;</span><span style="color: #0000BB">$fill&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">&gt;&gt;&nbsp;(</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">-&nbsp;(</span><span style="color: #0000BB">$gone&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$bits</span><span style="color: #007700">));&nbsp;</span><span style="color: #FF8000">//get&nbsp;bits&nbsp;from&nbsp;buffer<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if(</span><span style="color: #0000BB">$oversize&nbsp;</span><span style="color: #007700">&amp;&amp;&nbsp;((</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$max</span><span style="color: #007700">)&nbsp;||&nbsp;(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&gt;=&nbsp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">))){&nbsp;</span><span style="color: #FF8000">//not&nbsp;in&nbsp;extra&nbsp;chars&nbsp;-&nbsp;take&nbsp;1&nbsp;bit&nbsp;less.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&gt;&gt;=&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$gone</span><span style="color: #007700">--;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$result&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">$base</span><span style="color: #007700">[</span><span style="color: #0000BB">$index</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">&amp;=&nbsp;(</span><span style="color: #0000BB">1&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;(</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">-=&nbsp;</span><span style="color: #0000BB">$gone</span><span style="color: #007700">))&nbsp;-&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$result</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;*&nbsp;Decode&nbsp;a&nbsp;string&nbsp;encoded&nbsp;with&nbsp;a&nbsp;base&nbsp;set&nbsp;of&nbsp;characters.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$base&nbsp;&nbsp;Base&nbsp;characters.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;string&nbsp;$str&nbsp;&nbsp;String&nbsp;to&nbsp;decode.<br />&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;string&nbsp;&nbsp;Decoded&nbsp;(original)&nbsp;string.<br />&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;static&nbsp;function&nbsp;</span><span style="color: #0000BB">baseDecode</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">,</span><span style="color: #0000BB">$str</span><span style="color: #007700">){<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$result&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$count&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">strlen</span><span style="color: #007700">(</span><span style="color: #0000BB">$str</span><span style="color: #007700">)){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">baseParams</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">,</span><span style="color: #0000BB">$length</span><span style="color: #007700">,</span><span style="color: #0000BB">$bits</span><span style="color: #007700">,</span><span style="color: #0000BB">$max</span><span style="color: #007700">,</span><span style="color: #0000BB">$oversize</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$map&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">array_flip</span><span style="color: #007700">(</span><span style="color: #0000BB">$base</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//bit&nbsp;buffer,&nbsp;buffer&nbsp;size<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">for(</span><span style="color: #0000BB">$position&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$position&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$count</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$position</span><span style="color: #007700">++){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!</span><span style="color: #0000BB">array_key_exists</span><span style="color: #007700">(</span><span style="color: #0000BB">$char&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$str</span><span style="color: #007700">[</span><span style="color: #0000BB">$position</span><span style="color: #007700">],</span><span style="color: #0000BB">$map</span><span style="color: #007700">))&nbsp;throw&nbsp;new&nbsp;\</span><span style="color: #0000BB">ValueError</span><span style="color: #007700">(</span><span style="color: #DD0000">"Char&nbsp;'</span><span style="color: #0000BB">$char</span><span style="color: #DD0000">'&nbsp;is&nbsp;not&nbsp;in&nbsp;base"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$map</span><span style="color: #007700">[</span><span style="color: #0000BB">$char</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$add&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$bits</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$oversize</span><span style="color: #007700">){&nbsp;</span><span style="color: #FF8000">//bit&nbsp;size&nbsp;larger&nbsp;then&nbsp;char&nbsp;range<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&lt;&nbsp;</span><span style="color: #0000BB">$max</span><span style="color: #007700">)&nbsp;</span><span style="color: #0000BB">$add</span><span style="color: #007700">--;&nbsp;</span><span style="color: #FF8000">//lower&nbsp;range&nbsp;=&nbsp;1&nbsp;bit&nbsp;less<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">elseif(</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&gt;=&nbsp;</span><span style="color: #0000BB">$length</span><span style="color: #007700">){&nbsp;</span><span style="color: #FF8000">//out&nbsp;of&nbsp;range&nbsp;=&nbsp;1&nbsp;bit&nbsp;less<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$index&nbsp;</span><span style="color: #007700">&gt;&gt;=&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$add</span><span style="color: #007700">--;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #FF8000">//else:&nbsp;in&nbsp;extra&nbsp;range&nbsp;=&nbsp;maximum&nbsp;bits&nbsp;used<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">=&nbsp;(</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">$add</span><span style="color: #007700">)&nbsp;|&nbsp;</span><span style="color: #0000BB">$index</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">+=&nbsp;</span><span style="color: #0000BB">$add</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">&gt;=&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">){&nbsp;</span><span style="color: #FF8000">//write&nbsp;bytes&nbsp;from&nbsp;buffer<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$result&nbsp;</span><span style="color: #007700">.=&nbsp;</span><span style="color: #0000BB">chr</span><span style="color: #007700">(</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">&gt;&gt;&nbsp;(</span><span style="color: #0000BB">$size&nbsp;</span><span style="color: #007700">-=&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$buffer&nbsp;</span><span style="color: #007700">&amp;=&nbsp;(</span><span style="color: #0000BB">1&nbsp;</span><span style="color: #007700">&lt;&lt;&nbsp;</span><span style="color: #0000BB">$size</span><span style="color: #007700">)&nbsp;-&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: #0000BB">$result</span><span style="color: #007700">;<br />&nbsp;&nbsp;}<br /></span>
</span>
</code></div><br>
De "base" kan dus van alles zijn. Als het maar meer dan 2 (en minder dan 256) unieke karakters zijn - het precieze aantal maakt niet uit (hoeft geen macht van 2 te zijn).]]></description>
      <pubDate>Sat, 30 Sep 2023 13:22:00 +0200</pubDate>
      <category>nerd</category>
      <category>prog</category>
    </item>
    <item>
      <title>Afstandsbediening</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=590</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=590</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=590#Comments</comments>
      <description><![CDATA[Techniek in huis is leuk, maar het moet ook wel een beetje makkelijk blijven. Dus in plaats van iedereen alles uit te moeten leggen, en/of steeds naar een "device" te moeten grijpen om iets aan/uit te zetten, heb ik een "afstandsbediening" in elkaar geknutseld.<br>
<br>
<center><a class="ImagePopup" href="http://shitware.nl/blog/2023/3/Id590/boven.jpg" title=""><img src="http://shitware.nl/blog/2023/3/Id590/bovent.jpg" alt=""><span class="ImageText">Knoppen aan de bovenkant.</span></a> <a class="ImagePopup" href="http://shitware.nl/blog/2023/3/Id590/onder.jpg" title=""><img src="http://shitware.nl/blog/2023/3/Id590/ondert.jpg" alt=""><span class="ImageText">Techniek (achter een raampje) aan de onderkant.</span></a></center><br>
<br>
Elke knop kan via een "event" dynamisch aan een "actie" in huis gekoppeld worden (lamp aan/uit - evt. voor een bepaalde tijd, TV/versterker bedienen, deurbel, doucheventilator, enz - als het maar op de een of andere manier te "programmeren" is).<br>
<br>
In elke knop zit een lampje, dat op zijn beurt ook weer ergens aan gekoppeld kan worden. Als de "knop" (het indrukken) zelf aan een lamp is gekoppeld, is het natuurlijk het meest logisch om het lampje ook de status van die lamp te laten zien. Want uiteraard kun je de betreffende lamp ook nog gewoon met de wandschakelaar bedienen (en nog op tig andere manieren*), en ook dat zie je terug op de afstandsbediening.<br>
<br>
<small>* Zo hebben we in de keuken een knopje waarmee je de lampen op de kinderkamers een keer kunt laten knipperen. Dat scheelt weer "eten!" gegil door het trappengat.</small>

]]></description>
      <pubDate>Sat, 25 Mar 2023 12:20:49 +0100</pubDate>
      <category>klus</category>
      <category>nerd</category>
      <category>tech</category>
    </item>
    <item>
      <title>Flowmeter fun</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=589</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=589</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=589#Comments</comments>
      <description><![CDATA[Ik kwam een tijdje terug deze <a href="https://www.tinytronics.nl/shop/nl/sensoren/vloeistof/yf-b7-water-flow-sensor-met-temperatuur-sensor-messing-g1-2" title="" target="_blank">flowmeter</a> tegen in m'n favoriete webwinkel. Naast de flow (liter/minuut) kan ie ook de temperatuur meten, en daarmee kun je dus uitrekenen hoeveel energie je <a href="/blog/362/Single?ArticleId=351" title="">zonneboiler</a> aan het koude leidingwater heeft toegevoegd. En <i>daarmee</i> kun je weer uitrekenen hoeveel kuub gas je uitgespaard hebt.<br>
<br>
Goed idee, aan de slag!<br>
<br>
<center>
<a class="ImagePopup" href="http://shitware.nl/blog/2023/3/Id589/testen.jpg" title=""><img src="http://shitware.nl/blog/2023/3/Id589/testent.jpg" alt=""><span class="ImageText">Testen of de uitgelezen waarden wel een beetje kloppen (emmer = 10 liter, aantal seconden bijhouden = flow). en natuurlijk meteen een test voor het programmeer werk.</span></a>
<a class="ImagePopup" href="http://shitware.nl/blog/2023/3/Id589/flowmeter.jpg" title=""><img src="http://shitware.nl/blog/2023/3/Id589/flowmetert.jpg" alt=""><span class="ImageText">De flowmeter met aandraaikoppelingen (voor knelkoppelingen - hij komt op een hoekpunt).</span></a>
<a class="ImagePopup" href="http://shitware.nl/blog/2023/3/Id589/leidingwerk.jpg" title=""><img src="http://shitware.nl/blog/2023/3/Id589/leidingwerkt.jpg" alt=""><span class="ImageText">De flowmeter zit in de warme retourleiding van de zonneboiler. De Arduino links is om het functioneren en het programmeerwerk te testen. De oude leiding ligt nog op de grond, voor het geval de flowmeter mocht lekken en weer verwijderd moet worden.</span></a>
<a class="ImagePopup" href="http://shitware.nl/blog/2023/3/Id589/programmeren.jpg" title=""><img src="http://shitware.nl/blog/2023/3/Id589/programmerent.jpg" alt=""><span class="ImageText">Nogmaals het testprogramma draaien om te kijken wat de flow tijdens douchen is, en of de temperatuurberekening bij hoge temperaturen ook nog klopt.</span></a>
</center>
<br>
Daarna een custom stekkertje knutselen, en alle meetwaarden naar de Arduino voeren die toch al in het CV-hok hangt om het functioneren van de zonneboiler te monitoren, de <a href="/blog/491/filling_hothothot" title="">hotfill</a> van de wasmachine aan te sturen, en als timer voor de badkamerventilator fungeert.<br>
<br> 
Tot zover de hardware zijde van het verhaal. Nu de zachte kant:<ul>
<li>Uiteraard de verbruikscijfers. Momenteel is het takkeweer, maar twee weken geleden was het een paar dagen mooi weer, en toen begon de zonneboiler al aardig op temperatuur te komen. Dagelijks werd er toen zo'n 6 kWh aan warm water aan de zonneboiler onttrokken. Als de CV-ketel dit had moeten doen (en dan ga ik er maar even vanuit gaat dat ie dit met redelijk 100% efficiency weet op te wekken - het is tenslotte een "HR"), dan betekent dat een besparing van zo'n 0,6 kuub gas per dag (op een winterdag!).</li>
<li>Omdat je nu weet wanneer er (lang) warm water wordt getapt = er staat waarschijnlijk iemand te douchen, kan de badkamerventilator automatisch aanspringen (dat moest normaal door <i>na het douchen</i> aan een touwtje te trekken; of <i>via de app</i> - jawel). Uiteraard hoeft dit niet als het buiten mooi weer is, want dan staat het doucheraampje toch al open (lees: even koppelen met de buitentemperatuur).
<li>Data is natuurlijk leuk, maar grafiekjes zijn nog leuker. Nou heb ik al een vrij drukke grafiek met allerlei data rond "invloeden van buitenaf" (het weer) en alles wat we daar aan moeten doen om het binnen behaaglijk te houden. Daar is nu <i>nog</i> een lijntje bij gekomen:<ul>
  <li>Onderaan staat de tijd (de uren van de afgelopen 24 uur). Links de temperatuurschaal, en rechts de windkracht (lichtgroen) en de neerslag schaal.</li>
  <li>De dik gedrukte blauwe lijn is de buitentemperatuur (volgens Buienradar), en de wat lichtblauwe lijn die daar z'n beetje parallel aan loopt de buitentemperatuur volgens het weerstation van de buurman (handig, al die "slimme" apparaten die alle data delen met de rest van de wereld ;-) ).</li>
  <li>De groene pluim is de huidige windsnelheid (onderkant is gemiddeld, en bovenkant is uitschieters). De groene pijlen bovenaan de grafiek geven de windrichting weer.</li>
  <li>De gele "bult" stelt de theoretische positie van de zon voor (de hoek van de zon tov de horizon volgens de graden schaal rond 12 uur 's middags). De geel/oranje lijn geeft aan hoeveel de <i>echte</i> zon instraling was (in W/m²). Het is nu een grijze dag; op een mooie dag loopt dit redelijk parallel aan de "gele bult".</li>
  <li>De blauwe staafjes onderaan geven de hoeveelheid neerslag weer. Ook weer volgens Buienradar (betere meetwaarden) en de buurman (beter beeld van de <i>lokale</i> neerslag).</i>
  <li>De lichtrode vlakken geven de momenten aan waarop de CV aan was, en de rode lijn geeft de werkelijke radiator temperatuur weer (elke blokje vanaf de onderkant van de grafiek komt overeen met 10 °C). Overdag pendelt de CV dus wel wat, maar het echte werk begint pas als 's avonds de thermostaat wordt opgeschroefd (deze info gebruik ik trouwens om een ventilator aan te sturen die de warme lucht geforceerd de kamer in blaast).</li>
  <li>De paarse balken die je tenslotte tussen 13:00 en 14:00 aan de bovenkant van de grafiek ziet hangen zijn de zonneboiler tapwater temperaturen (2x douchen; ook weer 10 °C per blokje). Aan het begin van het douchen was het water dus nog zo'n 40 °C, maar uiteindelijk kakte dat in naar zo'n 25 °C (dan zal het wel bijna "op" zijn). Dit komt overeen met 2,4 kWh aan warmte ~ 0,24 kuub gas.</li>
</ul></li>
</ul>
<br>
<center><img src="http://shitware.nl/blog/2023/3/Id589/cv-graph.png" alt=""></center>
<br>
Als toegift heb ik nu nog deze <a href="https://www.tinytronics.nl/shop/en/lighting/rings-and-modules/sk6812-digital-5050-rgb-led-ring-24-leds-white" title="" target="_blank">LED-ring</a> in de badkamer opgehangen. Normaal geeft deze de tijd aan (rode stip voor de seconden, groene stip voor de minuten, en blauw voor de uren; als de zonneboiler aan is pulseert de seconden stip; als de zonneboiler aan z'n max zit = het hele vat op 90 °C, dan pulseert de blauwe uren stip). Zodra er nu warm water wordt getapt begint op deze cirkel een timer te lopen. Elke LED komt overeen met 1 minuut douchen. De eerste 5 minuten zijn groen, daarna volgen 5 gele stippen, en vervolgens alleen nog maar rood (met om elke 5 minuten nog een paarse LED om het tellen makkelijk te maken). Als je het zo bont weet te maken dat je over de maximale 24 minuten heen gaat gaan de laatste twee LEDs wit knipperen.<br>
<br>
<i>Daarnaast</i> toont ie, als de CV niet aan staat (zo'n beetje van mei tot september - als er meer dan genoeg warm water uit de zonneboiler komt, en de verwarming ook niet meer aan hoeft), de temperatuur van het zonneboiler water (het aantal graden boven de 40 °C - elke graad een LED), zodat je een beetje in kunt schatten hoeveel ruimte er nog is om eens lekker lang onder de douche te staan (of dat de volgende misschien toch maar eerst de CV in moet schakelen voordat ie er onder springt).]]></description>
      <pubDate>Sun, 12 Mar 2023 14:17:39 +0100</pubDate>
      <category>klus</category>
      <category>nerd</category>
      <category>zon</category>
    </item>
    <item>
      <title>Hier heeft iemand ook nog nooit van een URL-shortner gehoord</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=588</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=588</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=588#Comments</comments>
      <description><![CDATA[<center><a class="ImageZoom" href="http://shitware.nl/blog/2022/9/Id588/tandpasta.jpg" title=""><img src="http://shitware.nl/blog/2022/9/Id588/tandpastat.jpg" alt=""><span class="ImageText"></span></a></center>
<br>
Door die lange URL (<u>https://unilever.demdex.net/event?d_event=click&c_brand=prodent&c_brandcode=bh0880&c_retailer=brandwebsite&c_country=nl&c_medium=partner&c_division=personal-care&c_category=oral-care&c_campaignname=prodent_doktersvandewereld&&d_rd=https%3A%2F%2Fwww.prodent.nl%2Fdoktersvandewereld.html%3Futm_campaign%3DProdent_doktersvandewereld%26utm_source%3DQRcode%26utm_medium%3Dpartner</u>) wordt die QR-code zo heel pietepeuterig (ivm "veel data"), en is ie ivm de kwaliteit van het drukwerk bijna niet te scannen. Die had gewoon <a href="https://en.wikipedia.org/wiki/URL_shortening" title="" target="_blank">ingekort</a> moeten worden naar iets van <u>https://unilever.com/go?id=doktervdwereld</u>. Dan had ie er zo uitgezien:<br>
<br>
<center><img src='/blog/2022/9/Id588/qr.png' style='border:5px solid white'></center>

]]></description>
      <pubDate>Tue, 27 Sep 2022 11:27:07 +0200</pubDate>
      <category>rant</category>
    </item>
    <item>
      <title>We want more</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=587</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=587</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=587#Comments</comments>
      <description><![CDATA[De kinderen gebruiken steeds meer stroom, we werken steeds meer thuis, de energieprijzen stijgen momenteel de pan uit, er was nog ruimte op het dak, dus:<br><br>
<center>
<a class="ImageZoom" href="http://shitware.nl/blog/2022/4/Id587/1.jpg" title=""><img src="http://shitware.nl/blog/2022/4/Id587/1t.jpg" alt=""><span class="ImageText"></span></a>
<a class="ImageZoom" href="http://shitware.nl/blog/2022/4/Id587/2.jpg" title=""><img src="http://shitware.nl/blog/2022/4/Id587/2t.jpg" alt=""><span class="ImageText"></span></a>
<a class="ImageZoom" href="http://shitware.nl/blog/2022/4/Id587/3.jpg" title=""><img src="http://shitware.nl/blog/2022/4/Id587/3t.jpg" alt="4x 380Wp"><span class="ImageText"></span></a>
</center><br>
BTW terugvragen heb ik maar even laten zitten (als je dat al eerder gedaan hebt - die rij eronder - wordt het wel heel ingewikkeld, <a href="https://www.eigenhuis.nl/energie/maatregelen/zonne-energie/btw-teruggave-bij-aanschaf-tweede-set-zonnepanelen#/" title="" target="_blank">en levert het mogelijk zelfs niks op</a>). En <a href="https://www.solar-bouwmarkt.nl/" title="" target="_blank">zoveel kosten ze ook niet meer</a>. Met de stroomprijzen van nu zou de terugverdientijd minder dan 3 jaar moeten zijn.<br>
<br>
Nog even een korte review over het <a href="https://www.youtube.com/watch?v=KTGmsVyp8aw" title="" target="_blank">ClickFit montagesysteem</a>: Het werkt wel prettig, ziet er netjes uit, en wordt compleet geleverd, maarrr ...<ul>
<li>Omdat het voor zowel horizontale als verticale (portret/landscape) montage is, ligt het vrij hoog boven de pannen (ook in de "laagste" stand - mijn pannen zijn ook niet zo "curvy" = vrij plat (de vorige panelen waren veel "dikker", maar liggen veel platter op het dak). Hopelijk blijft de wind er onder uit.</li>
<li>In de instructie staat ongeveer "pan omhoog schuiven / haak achter panlat haken / pan terugschuiven". Die haak is vrij degelijk, maar mijn jaren 70 panlat absoluut niet. Daar heb ik dus eerst een extra lat onder moeten monteren (= hele rij pannen eronder weghalen). Als je vervolgens de dakpan terugschuift ligt ie 2cm "los" <a class="ImagePopup" href="http://shitware.nl/blog/2022/4/Id587/dakpan.jpg" title="">van de pan eronder<span class="ImageText"></span></a> (= wind+sneeuw waait er zo onder). Daar moet dus steeds een sleuf uit geslepen worden (ter breedte van de haak; werd wel als "misschien stel dat" genoemd, maar is dus behoorlijk gedoe/meerwerk - dan is het voordeel van het "klikken" wel weer weg).</li>
<li>Als je de haak vastschroeft (de dakpan dus op de panlat klemt), en daarna even aan de haak rammelt, zit ie weer los. Omdat een dakpan alle kanten op rond is, en ook onder een hoek op het dakvlak ligt heb je nooit in 1x het juiste punt te pakken. Soms moet je dit wel 3x herhalen voordat ie echt "vast" zit. Een haak die direct op het dakvlak monteert heeft dus ook z'n voordelen.</li>
<li>De bouten hebben allemaal dezelfde torx sleutel ... alleen heb je voor de bouten om de panelen vast te zetten een torx sleutel nodig <i>met een gaatje er in</i> (zit een puntje in het torx gat). Als je dus op zaterdag de dwarsbalken hebt vastgezet met je vertrouwde torx sleutel, heb je een probleem als je op zondag de panelen gaat monteren (als de lokale bouwmarkt dicht is).</li>
</ul><br>
<br>
<b>Instant update:</b><br>
Zo, <a href="https://nos.nl/artikel/2426225-voor-het-eerst-meer-stroom-opgewekt-met-zonnepanelen-en-windturbines-dan-verbruikt" title="" target="_blank">dat gaat snel</a>. Maar dat spul is ook ontzettend veel beter (en goedkoper) geworden de afgelopen jaren. Deze 4 panelen leveren (iets) meer op dan <a href="/blog/371/energiedwerg" title="">deze 8 uit 2009</a>, en kosten (inclusief omvormer en montagemateriaal) maar 20% daarvan.]]></description>
      <pubDate>Tue, 12 Apr 2022 07:27:27 +0200</pubDate>
      <category>zon</category>
    </item>
    <item>
      <title>Jaaroverzicht</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=586</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=586</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=586#Comments</comments>
      <description><![CDATA[Dit jaar heb ik 50 boeken / 17.621 pagina's gelezen. Ondanks het vele thuiszitten ivm Corona net iets minder als normaal (zowel in aantal als in pagina's).<br>
<br>
De beste (5 sterren):<ul>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789023958017&LID=&AUT=&TI=&DocType=AI_TEXT">Meneer Peacocks paradijs</a> door Syson, Lydia (431 pagina's)</li>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789044613551&LID=&AUT=&TI=&DocType=AI_TEXT">De grot</a> door Krabbé, Tim (180 pagina's)</li>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789046817483&LID=&AUT=&TI=&DocType=AI_TEXT">Tijdmeters</a> door Mitchell, David (591 pagina's)</li>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789401613439&LID=&AUT=&TI=&DocType=AI_TEXT">De spiegel van ons verdriet</a> door Lemaitre, Pierre (446 pagina's)</li>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789402704877&LID=&AUT=&TI=&DocType=AI_TEXT">Middaguur</a> door Hansen, Dörte (302 pagina's)</li>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789403197005&LID=&AUT=&TI=&DocType=AI_TEXT">Meisje zonder leugens</a> door Robotham, Michael (391 pagina's)</li>
</ul>
<br>
En de slechtste van dit jaar (1 ster):<ul>
<li><a href="http://mom.biblion.nl/olifant/olifant.dll?Bibliotheek=obarnhem&PPN=&ISBN=9789044359817&LID=&AUT=&TI=&DocType=AI_TEXT">Het meisje onder de boom</a> door Blædel, Sara (381 pagina's)</li>
</ul>
<br>
En wat betreft <a href="/blog/581/jaarafrekening">dat andere jaaroverzicht</a>:<ul>
<li>Wederom een positief jaarverbruik qua stroom (meer verbruikt dan opgewekt).</li>
<li>De kou hield lang aan (stoken t/m april), en begon ook weer vroeg = relatief veel gas.</li>
<li>Inclusief welkomstkorting en SDE subsidie op de eerste set zonnepanelen kwamen we uit op &euro;7,93/maand (een "positief" bedrag dus; dat is heel lang geleden dat we moesten <i>betalen</i> voor onze energie).</li>
</ul>
<br>
Een welkomstpremie zit er dit jaar niet in (overstappen "was niet mogelijk", of in ieder geval niet lonend), en met die fors gestegen prijzen ben ik benieuwd wat dit jaar gaat brengen ...]]></description>
      <pubDate>Sat, 08 Jan 2022 21:37:37 +0100</pubDate>
    </item>
    <item>
      <title>Mijn uurtje zonder internet</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=585</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=585</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=585#Comments</comments>
      <description><![CDATA[Gisteren was het weer raak: flits, <a href="https://www.gelderlander.nl/renkum/bliksem-zorgt-voor-overlast-in-regio-lamp-valt-van-plafond-na-inslag-in-woning-gemeentehuis-onbereikbaar~a01b841a/?utm_source=twitter&amp;utm_medium=social&amp;utm_campaign=socialsharing_web" title="" target="_blank">boem</a>, computer uit, auto-alarm aan, en een <a href="/Blog/Single?ArticleId=530" title="">een modem die naar z'n grootje was</a>. De laatste keer dat dit gebeurde was al een tijdje terug; enerzijds omdat we in het begin regelmatig de stekker er uit trokken als het onweerde, anderzijds (mogelijkerwijs) omdat er tegenwoordig zo'n spanningspiekbeveiliging tussen zit. Maar: de lijn hapert hier de laatste tijd nog wel eens (verbinding valt weg, verbinding wordt opnieuw opgebouwd = 30 seconden geen internet), dus op advies van XS4all deze er tussenuit gehaald, en de modem weer direct aan de telefoonlijn gehangen (samen met een factory reset van de modem gaf het een kleine verbetering, maar het probleem is/was nog niet helemaal weg). En we waren natuurlijk allemaal thuis aan het werk/school, dus dan wil je de stekker er niet meteen uit trekken (in eerste instantie was het onweer ook nog redelijk ver weg).<br>
<br>
Resultaat: modem toast, een switch die niet meer via PoE wil werken (met de originele voeding - was even zoeken - deed ie het gelukkig nog wel), en twee Arduino's + <a href="https://hackerstore.nl/Artikel/313" title="" target="_blank">ethernet module</a>'s afgeschreven ... Lekker dan. Eerst XS4all maar eens bellen. Die wilden voor die haperende lijn niet meteen een nieuwe modem sturen, maar dat station was nu ruimschoots gepasseerd. Tien minuten in de wacht (dat is extreem lang voor XS4all - mijn ervaring althans), maar vervolgens zonder al teveel poeha een nieuwe modem (morgen binnen).<br>
<br>
Nou krijg je bij een XS4all abo ook een data SIM, zodat je online kunt blijven - ook als de vaste lijn er uit ligt (daarvan werd de data limiet ook even flink opgeschroefd - mooi). Die zit hier in een oude mobiel. Deze mobiel op "mobiele hotspot" gezet, zodat ie z'n eigen WiFi netwerk creëert (gevoed door de 4G verbinding). Dit signaal vervolgens via een <a href="https://shitware.nl/blog/579/het_is_weer_helemaal_uit_de_hand_gelopen" title="die lag toch in de la te niksen" target="_blank">ontvanger</a> weer omgezet naar een fysieke kabel, en die weer in de WAN2 ingang van de Unifi Gateway geprikt. En tadaa: alles werkte weer (uitgaand verkeer tenminste; inkomend verkeer loopt voorlopig even dood) - en doorrr. Toch een mooie vooruitgang al dat spul.<br>
<br>
Binnenkort hebben we hier (ook) <a href="https://shitware.nl/blog/583/glasvezel_qampa" title="" target="_blank">glasvezel</a>, dus dan komt die op die WAN2 (ik houd XS4all er naast, ivm betere diensten, en prijstechnisch maakt het ook niet heel veel uit of je alle toeters en bellen van Delta/Caiway neemt, of gewoon een apart XS4all abo), dus dan hebben we dit probleem helemaal niet meer (glasvezel is natuurlijk al een stuk ongevoeliger voor onweer dan koper). Maar voorlopig is dit een prima oplossing.<br>
<br>
Update: De nieuwe modem is binnen, de lampjes knipperen ... maar geen verbinding. Blijkbaar is er ook iets mis in de wijkcentrale (XS4all kon de lijn van afstand niet doormeten). Morgen gaat er een KPN-monteur aan de slag.]]></description>
      <pubDate>Thu, 20 May 2021 11:06:16 +0200</pubDate>
      <category>admin</category>
      <category>tech</category>
    </item>
    <item>
      <title><![CDATA[Glasvezel Q&amp;A]]></title>
      <link>http://shitware.nl/Blog/Single?ArticleId=583</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=583</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=583#Comments</comments>
      <description><![CDATA[In ons durp gaan ze (eindelijk) glasvezel aanleggen ... als tenminste 30% of meer van de huishoudens zegt over te stappen (en dan gaan ze ook alleen <i>die</i> huishoudens daadwerkelijk van <a href="https://en.wikipedia.org/wiki/Fiber_to_the_x#Definitions" title="" target="_blank">FttH</a> voorzien; wil je later nog meedoen moet je &euro; 650,- aftikken om alsnog een sleuf door je voortuin te krijgen). Nou ben ik op zich tevreden met m'n 50Mbs <a href="https://nl.wikipedia.org/wiki/VDSL" title="" target="_blank">VDSL</a> lijntje, maar af en toe zit er hier eentje te balen omdat ie 20 minuten moet wachten tot Fortnite z'n zoveel gigabyte update weer door de lijn getrokken heeft. En ach, een beetje snelheid is natuurlijk altijd leuk - maar dan moet het verder natuurlijk ook wel "in orde" zijn. Vandaar dat ik een aantal (technische) vragen aan <a href="https://www.deltafibernederland.nl/nl/" title="" target="_blank">Delta</a> had over hoe &amp; wat. Met name omdat m'n huidige provider (XS4all - binnenkort dus KPN) dan weer zijn diensten niet via deze glasvezelboer aan mag/kan/wil bieden, en dit dan dus ook een overstap naar een andere provider zou betekenen.<br>
<br>
Het <i>doorsturen</i> van de antwoorden naar de juiste afdeling (ivm mijn "eisen" als consument moest het naar de zakelijke afdeling) duurde 7 weken (eerste minpuntje). Toen dat eenmaal uitgezocht was waren de antwoorden er vrij vlot. Voor eenieder die ook nog twijfelt (en van een internetaansluiting iets meer verwacht dan "WiFi") hieronder vragen + antwoorden, en soms nog een toelichting:<br>
<br>
Q: <b>Op zich wil/hoef ik geen gebruik te maken van "zakelijk". Wat ik wel wil (als particulier) is een vast IP-adres (en een eigen server draaien). Als ik daarvoor een "zakelijk" abonnement ("Business pack") af moet nemen prima, als dat dan maar wel mogelijk is als particulier (zonder BTW-nummer)?</b><br>
A: <i>Voor vast IP_adres = business pack nodig en dat kun je ook als consument afnemen</i>
<p>Ik wil een vast IP-adres omdat ik <a href="/" title="">een eigen server draai</a> en dan moet je in de DNS (het telefoonboek van het internet) opgeven op welk nummer (IP-adres) ze je kunnen vinden. Als je elke keer dat je je modem herstart (of voor je herstart wordt) een nieuw IP-adres krijgt (dus niet vast) is dat niet handig.</p>
<p>Voor een vast IP-adres moet je echter een zakelijk abo afnemen (daar was ik al achter). Dat is duurder, maar daar krijg je ook allerlei andere diensten bij, zoals een "BTW-factuur". Nou heb ik als gewone consument geen BTW-nummer, dus vandaar mijn vraag of ik als particulier wel een zakelijk abo af <i>kan</i> nemen (dat kun dus - geen probleem dus).</p>

Q: <b>Daarnaast wil ik dan ook gewoon "interactieve TV" en "Bellen basis à 15ct p/m". Is dat ook allemaal nog mogelijk icm een "Business pack"?</b><br>
A: <i>Ja dat kan, het flexpakket kan de klant naar eigen inzicht en voorkeuren inrichten</i>
<p>Ook geen probleem dus.</p>

Q: <b>Kan ik (met een "Business pack") dan ook een eigen server draaien? Maw: blokkeren jullie bepaalde poorten, of is het gewoon mogelijk om alles van buitenaf door te prikken?</b><br>
A: <i>Ja, dat kan</i>
<p>Sommige provider blokkeren bepaalde poorten. Een poort correspondeert meestal met een bepaalde dienst op internet: HTTP-verkeer (= "websites bekijken") gaat standaard over poort 80 (of 443 voor een beveiligde website), en zo zijn er nog wat standaarden. Sommige providers blokkeren "uit veiligheidsoverwegingen" bepaalde poorten (maar het is natuurlijk ook wel lekker als een klant thuis geen servertje kan draaien, want dat scheelt in het door te sluizen verkeer). Vandaar dus deze vraag (en wederom geen probleem).</p>

Q: <b>Bieden jullie ook IPv6? En heb ik dan met een "Business pack" niet alleen een vast IPv4 adres, maar ook een vast IPv6 adres/prefix (en wat is dan de prefix lengte)?</b><br>
A: <i>Nog niet, dit volgt, maar een specifieke datum kunnen we hier niet aan meegeven</i>
<p><a href="https://en.wikipedia.org/wiki/IPv6" title="" target="_blank">IPv6</a> is de toekomst van het internet. Net als glasvezel. Maar blijkbaar gaan deze twee (nog) niet samen.</p>
<p>Nou draait hier alles al sinds een jaar of 5 (ook) via IPv6, dus dit zou een stapje terug in de tijd zijn. Voor normaal internetgebruik nog geen showstopper (IPv4 doet het nog steeds prima), maar voor hobby en werk is het toch wel eens handig om een native IPv6 verbinding te hebben (dit is wel op allerlei maniere te simuleren, maar dat blijft toch behelpen).</p>

Q: <b>Hoe wordt deze IPv6 ondersteuning geleverd (dual stack, tunnel, ...)?</b><br>
A: <i>Is op dit moment nog niet ingericht, dus kunnen we nu nog niets over zeggen.</i>
<p>Zie hierboven. Sommige providers "ondersteunen al wel IPv6", maar dan via een <a href="https://en.wikipedia.org/wiki/IPv6#Tunneling" title="" target="_blank">tunnel</a>, en da's toch net niet echt.</p>
<p>Maar dus niet van toepassing, want toch al geen IPv6 ...</p>

Q: <b>Moet de "interactieve tv ontvanger" altijd direct op de modem worden aangesloten (ivm een eigen VLAN of iets dergelijks), of mag daar ook nog een complete netwerklaag (met eigen IP range) tussen zitten (niks bijzonders, gewoon een Unify systeem met gateway, maar ik heb eigenlijk geen zin om extra kabels te trekken)?</b><br>
A: <i>Hoeft niet direct op het modem, en mag dus ergens op het netwerk worden ingeprikt. Belangrijk is wel dat de switches IGMP Snooping ondersteunen.</i>
<p>Vroeger moest "het TV-kastje" vaak (direct) op een specifieke poort (aansluiting) de modem worden aangesloten ("poort 4"). In de modem was het dan zo geregeld dat de betreffende poort direct gekoppeld werd aan een bepaald <a href="https://nl.wikipedia.org/wiki/Virtual_LAN" title="" target="_blank">VLAN</a> van de provider (het "TV netwerk"). Op de andere poorten werkte TV dan niet, en als de TV niet naast de modem stond moest er een extra kabel worden getrokken (parallel aan de normale internet/ethernet kabels).</p>
<p>Momenteel hangt de modem daadwerkelijk achter de TV, dus zou dit geen probleem zijn (maar niet meer nodig). Die locatie is echter "historisch bepaald" omdat daar nou eenmaal de oude telefoonaansluiting zit (is aansluiting voor ADSL/VDSL). Bij een nieuwe modem zou ik die heel graag in de meterkast willen hebben. Dat scheelt weer ongerelateerde kabelbende (en "kastjes") achter de TV.</p>
<p>Geen probleem dus. Overigens geen idee of "normale", low-budget, "unmanaged" switches IGMP snooping ondersteunen, maar bij dat Unify spul is dat geen probleem (naar wens in/uit te schakelen).</p>

Q: <b>Welke modem leveren jullie? Of is het mogelijk (toegestaan) om de Unify Security Gateway direct aan het glasvezel punt te koppelen (en zelf met PPPoE aan de slag te gaan)?</b><br>
A: <i>Wij leveren een <a href="https://genexis.eu/product/platinum" title="" target="_blank">genexis platinum modem</a>. Het is niet mogelijk zelf een modem aan te sluiten.</i>
<p>Zou mooi zijn als dit wel had gekund (had een kastje gescheeld), maar momenteel werkt het ook zo, en dat is geen enkel probleem. Omdat de modem nu enkel als een doorgeefluik fungeert (de USG doet het echte werk) maakt het ook niet zo heel veel uit wat de verder "toeters en bellen" van de modem zijn (wordt toch niet gebruikt).</p>

Q: <b>Is nummerbehoud ook mogelijk met een 087 nummer (VoIP)?</b><br>
A: <i>Nummerbehoud op 087 nummer is niet mogelijk krijg ik terug (waarbij hier nog wel een check op gedaan wordt).</i>
<p>We hebben nu VoIP via een 087 nummer (toen we hier naartoe verhuisden moesten we toch een nieuw nummer; dus dat hoefde dan niet perse eentje met een lokaal netnummer te zijn - waren extra kosten aan verbonden).</p>
<p>Jammer dat dit nummer niet mee is te nemen (ook omdat het grotendeels gelijk is aan mij 06 nummer; dat heb ik toen speciaal zo uitgezocht). Anderzijds is een "vaste lijn" natuurlijk toch al iets van eergisteren, dus misschien ook een mooi moment om 'm er maar gewoon helemaal uit te doen.</p>

<b>Samenvattend</b><br>
Voor het merendeel geen beren op de weg. Alleen dat niet ondersteunen van IPv6 voelt wel als een stap terug. Vooral omdat het merendeel van de providers al jaren aangeeft "hier mee bezig te zijn", maar het tot op heden nog steeds niet uitgerold heeft (en dus ook niet duidelijk is hoeveel jaar dit nog gaat duren ...). Lijkt er dus op dat Mr. Fortnite voorlopig "pech" heeft (sowieso zet ik vrijdagochtend gewoon altijd de Playstation even voor 'm aan, zijn de meeste updates al gewoon binnen voordat ie uit school komt).]]></description>
      <pubDate>Thu, 07 Jan 2021 19:02:02 +0100</pubDate>
    </item>
    <item>
      <title>WiFi dieet</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=582</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=582</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=582#Comments</comments>
      <description><![CDATA[D'r zitten hier af en toe twee van die puber-zombies in de bank die met een geknikt nekje "fillumpjus" zitten te kijken en te swipen (een minuut of langer hetzelfde filmpje <i>af</i>kijken trekt de attentie spanne niet). Omdat ik er genoeg van kreeg om elke keer "leg je dat ding weer eens weg" te roepen (daar geldt de <a href="https://quoteinvestigator.com/2014/11/24/hot-stove/" title="" target="_blank">relativiteitstheorie</a>: 5 minuten huiswerk voelt als een uur / een uur "fillumpjus" voelt als 5 minuten).<br>
<br>
Omdat we hier een bijzonder mooi <a href="https://unifi-network.ui.com/" title="" target="_blank">WiFi netwerk</a> hebben is het mogelijk om <a href="https://github.com/Art-of-WiFi/UniFi-API-client/blob/master/src/Client.php" title="" target="_blank">via de API</a> de verbruiksgegevens per "device" op te halen. Daarmee doe ik dan het volgende:<ul>
<li>Elke 5 minuten het dataverbruik per user (voor alle apparaten gecombineerd) bepalen voor het afgelopen uur.</li>
<li>Maximaal verbruik instellen per uur (grofweg max. 10 tot 15 minuten streaming video).</li>
<li>Indien "over budget" worden <i>alle</i> devices voor de betreffende user voor een uur geblokkeerd (ook weer volledig automatisch via de API).</li>
<li>Na de tweede keer worden alle devices voor de rest van de dag geblokkeerd.</li>
<li>(uitgezonderd tijdens schooltijden: ze zijn er toch niet, of ze hebben video-les; en de hele nacht, om updates en dergelijke de kans te geven - telefoons mogen hier niet mee naar de slaapkamer)</li>
</ul>
<br>
Heerlijk! Ik heb er geen omkijken meer na. Weet dat als ze er "te lang" op zitten het zich "vanzelf" regelt. Ben niet meer de kwaaie pier (<a href="https://en.wikipedia.org/wiki/Computer_says_no" title="" target="_blank">computer says no</a>). En heb zowaar weer kinderen die af en toe even (OK, enigszins geforceerd) gezellig kunnen doen (want geblokkeerd, of in ieder geval bijna aan hun tax). En trust me: je kunt zo vaak zeggen "zullen we een spelletje doen / hond uitlaten / enz", zodra de telefoon het ook doet trekt die toch harder aan ze.]]></description>
      <pubDate>Fri, 01 Jan 2021 11:32:10 +0100</pubDate>
      <category>nerd</category>
    </item>
    <item>
      <title>Jaarafrekening 2020</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=581</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=581</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=581#Comments</comments>
      <description><![CDATA[Het stroomverbruik is het afgelopen jaar flink toegenomen omdat we met z'n vieren thuis zaten te werken (<a href="/blog/559/ik_kocht_een_raspberry_pi__en_verbaasde_me" title="">extra schermen</a>, <a href="/blog/578/nieuwe_server" title="">extra server</a>, <a href="/blog/579/het_is_weer_helemaal_uit_de_hand_gelopen" title="">extra switches</a>). Dit "boekjaar" sinds lange tijd dus weer eens echt stroom <i>verbruikt</i> (= totaal net iets meer verbruikt dan teruggeleverd). Echter, de afgelopen jaren <a href="https://www.gaslicht.com/energievergelijker" title="" target="_blank">stap ik elk jaar over</a> naar een andere energieleverancier. De criteria zijn eenvoudig: "groen", en met een zo laag mogelijke totaalprijs voor het eerste jaar (daarna stap ik toch weer over). Omdat de tarieven mekaar niet zoveel ontwijken, we toch bijna 0,0 gebruiken, en de netwerkkosten voor elke aanbieder zelfs helemaal gelijk zijn, komt het er meestal op neer dat het degene met de hoogste "welkomstpremie" wordt (die pas na een jaar wordt uitgekeerd - meer een "houdoe" premie dus). Daardoor heeft dit "positief verbruik jaar" uiteindelijk (inclusief de nog steeds lopende SDE subsidie voor de <a href="/blog/580/voor_niks_gaat_de_zon_op" title="">reeds volledig terugverdiende</a> zonnepanelen; maar ook inclusief gasverbruik) toch nog &euro; 177,40 opgeleverd. Nice!<br>
<br>
<small>Update 2020-12-13: Omdat de overstap een maand na het verstrijken van het jaarcontract plaatsvond is de "winst" bijna weer volledig verdampt. December is zontechnisch natuurlijk niet zo'n beste maand, en het gas giert door de meter, dus die ene maand moest er nog &euro; 150,10 worden afgetikt. Nog net een "negatief" eindresultaat, maar je kunt er niet meer van <strike>uit eten</strike> afhalen).</small>]]></description>
      <pubDate>Wed, 18 Nov 2020 21:41:41 +0100</pubDate>
      <category>nerd</category>
      <category>zon</category>
    </item>
    <item>
      <title>Voor niks gaat de zon op</title>
      <link>http://shitware.nl/Blog/Single?ArticleId=580</link>
      <guid>http://shitware.nl/Blog/Single?ArticleId=580</guid>
      <comments>http://shitware.nl/Blog/Single?ArticleId=580#Comments</comments>
      <description><![CDATA[Alle investeringen in zonnepanelen (panelen, montage, kabels, enz) hebben zich zojuist tot op de cent terug verdiend 
(die <a href="/blog/489/solar_powerrr" title="">10 jaar</a> werden dus uiteindelijk 8,5 jaar - ook omdat het later toch mogelijk bleek om de BTW terug te vragen).
Vanaf nu is de stroom dus echt gratis in huize Shitware (en loopt de subsidieregeling voor de <a href="/blog/371/energiedwerg" title="">eerste set</a> nog 4 jaar door!).
<br><br>
Alhoewel: tot voor kort hielden we per jaar nog wel <a href="/blog/523/Jaarafrekening+2013" title="">een paar honderd kWh</a> over op de eindafrekening. Maar dit jaar zal het redelijk op 0 uitkomen.
Door al dat <a href="https://nl.wikipedia.org/wiki/Coronapandemie" title="" target="_blank">thuiswerken</a> is het stroomverbuik voor mijn eigen werkplek (ja, dat <a href="/blog/479/plugwise" title="">meet</a> ik) in ieder geval verdubbeld (van 10 naar 20kWh/maand).
En ook de rest van de collega's hier thuis zitten natuurljk vaker achter een beeldscherm gekluisterd.
En uiteraard is er nog de nodige 24/7 hardware (het lijkt hier onderhand wel een <a href="/blog/578/nieuwe_server" title="">datacenter</a>) naar binnen gekruid om alles aan elkaar te knopen (waarom zitten die switches altijd zo snel "vol"?). Even oppassen dus dat we uiteindelijk niet alsnog stroom moeten "inkopen".<br>
<br>
De zonneboiler heb ik geen exacte cijfers van, maar met de uren die de kinderen tegenwoordig onder de douche staan (of een paar jaar terug nog het buitenzwembadje met een emmer of 10 bijna kokend water aanwarmen - kost toch niks) kan ik me haast niet voorstellen dat die nog niet "afbetaald" is. Heerlijk!]]></description>
      <pubDate>Thu, 03 Sep 2020 13:45:14 +0200</pubDate>
      <category>klus</category>
      <category>nerd</category>
      <category>ons-ben-zuunig</category>
      <category>zon</category>
    </item>
  </channel>
</rss>