<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
  <title>Harry Jeffery</title>
  <link href="https://harry.pm/" />
  <subtitle>Recent content on Harry Jeffery</subtitle>
  <generator>Hugo -- gohugo.io</generator>
  <author>
    <name>Harry Jeffery</name>
  </author>
  <updated>2022-02-03T22:42:55+00:00</updated>
  <link href="https://harry.pm/index.atom.xml" rel="self" type="application/atom+xml" />
  <id>https://harry.pm/</id>
  
  <entry>
    <title type="html"><![CDATA[Book review: Modern x86 Assembly Language Programming]]></title>
    <link href="https://harry.pm/blog/book_review_modern_x86/" />
    <published>2022-01-27T00:00:00+00:00</published>
    <updated>2022-01-27T00:00:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/book_review_modern_x86/</id>
    <content type="html"><![CDATA[<p>Over Christmas, I got a copy of Daniel Kusswurm&rsquo;s <em>Modern X86 Assembly Language
Programming</em>, 2nd edition.  It promises to cover the fundamentals of x86 64-bit
assembly, with coverage of the modern extensions such as AVX-512.</p>
<p>I was quite excited to read it, as I&rsquo;ve been enjoying reverse engineering quite
a bit lately, so also wanted to try doing some software development directly in
assembly to sharpen my skills a bit.  Unfortunately, I&rsquo;d have to describe my
experience of reading it as disappointing. Within 10 minutes of reading I had
found several errors, and sadly the trend continued through the rest of the
book.</p>
<p>An example of one of the errors I found was in a table on page 16, listing
common instructions: <code>cupid -  Query CPU identification and feature information</code>, which should read <code>cpuid</code>.</p>
<p>I also didn&rsquo;t gel with the teaching style of this book. I was hoping for and
expecting a thorough guide of the fundamentals of x86 64-bit assembly language.
Perhaps starting with a high level look at how functions from C or C++ are
represented in assembly, what a stack frame is, what the most common calling
conventions are, before drilling down into topics like floating point
operations, common string manipulations, best practices, and so on.</p>
<p>Instead, this book shares about a page of C++ code, followed by a hand-written
equivalent in assembly (with comments) and then some prose describing what the
program does. Any new instructions introduced are given barely a sentence of
explanation. There&rsquo;s no consistent synopsis for new instructions being
introduced, just what feels like hand waving.</p>
<p>Perhaps for some that&rsquo;s a useful format, but to me it seemed to add very little
value to just reading the output of <code>gcc -s</code> by itself, and using google to look
up any instructions I was unfamiliar with.</p>
<p>The comments in the assembly code also doesn&rsquo;t seem to have been proof read very
thoroughly, containing numerous inconsistencies.</p>
<p>Just by flicking through the book now and inspecting random pages I can find
examples easily.</p>
<p>On page 56: <code>inc edx; edx = i + i</code>. Actually inc increments a register, it does
not add i to itself.</p>
<p>On page 76:</p>
<pre tabindex="0"><code>mov rax,r8          ; rax = 'src'
mov rdi,[rax+r11*8] ; rdi = src[i]
</code></pre><p>Why is <code>src</code> in quotes? <code>rax</code> isn&rsquo;t pointing to a string containing <code>src</code>.
Elsewhere <code>src</code> isn&rsquo;t quoted.</p>
<p>Other errors I remember, but can&rsquo;t be bothered to back and find were the
comments using <code>+</code> and <code>+=</code> interchangeably. That is, sometimes you&rsquo;d see
<code>count += 1</code> to mean increment count, and sometimes you&rsquo;d see <code>count + 1</code>
for the same operation. Sometimes the comments would even refer to different
variable names than the code was even using.</p>
<p>Perhaps this sounds fussy, but I didn&rsquo;t go into this book with a nitpicking
attitude at all. In my casual read I just started spotting errors, and couldn&rsquo;t
stop spotting them. I can&rsquo;t emphasise enough that this is a second edition,
with experienced and respectable engineers listed as the author and technical
reviewer of this book. I don&rsquo;t really understand how so many errors made it in,
survived review, and survived to the second edition.</p>
<p>Moving on from the topic of errors, I&rsquo;d like to comment a little more on the
way that key concepts are covered.  I&rsquo;m by no means an expert on assembly
programming but I&rsquo;d still consider calling conventions to be an absolutely
critical area to cover, lest a beginner be confused by contradictory examples
found across different books and the internet.</p>
<p>This book casually introduces them as an aside on page 31, buried under the
header of <em>Advanced Integer Arithmetic</em>.  It&rsquo;s mentioned because the author is
giving an example that accepts a non-trivial number of parameters and has
realised the way they&rsquo;re passed to the function might be non-obvious to a
beginner. So on page 33 the author gives a brief summary of which parameters
are passed in which registers in Visual C++ and that for other compilers and
operating systems the reader should go and read their respective manuals.
<em>What?</em>. At the very minimum the author ought to provide the most common
calling convention around: the SysV x86-64 ABI, but they don&rsquo;t. In 600 pages
not one paragraph is spared to summarise any x86 calling conventions other than
Visual C++&rsquo;s.</p>
<p>Consider this, if someone is writing assembly language by hand what context are
they going to be using it in?  Most likely to write server software that is
almost certain to be running on a unix-like operating system. Have you heard of
any high frequency trading shops using Windows Server? I haven&rsquo;t. Or perhaps
they&rsquo;re working on a AAA video game that&rsquo;ll indeed be running on Windows 10
x64, but also very likely on a console like the PlayStation that runs on a
FreeBSD derivative.</p>
<p>But no, this book leaves the most common environments high and dry on such a
critical aspect of assembly programming.  &ldquo;That&rsquo;s not fair,&rdquo; you might say,
&ldquo;the author is assuming a more experienced audience.&rdquo; No, they&rsquo;re not. On page
21 the author felt it necessary to explain to the reader what a Visual Studio
solution and project are, and how to open one by double clicking on it. I
cannot reconcile the decision to explain how to use Visual Studio in an
assembly book but not to cover a non Windows ABI.</p>
<p>Another concept that I thought was introduced and explained far too late in the
text is stack frames.  Stack frames are taught on page 143. Page one hundred
and forty-three, under the subheading of <em>Calling Convention</em>, which yet again
only describes Visual C++. Another thing you won&rsquo;t find an explanation of in
this book: <code>__stdcall</code> vs <code>__cdecl</code> vs <code>__fastcall</code>. Despite being extremely
common calling conventions on Windows that you will encounter and have to deal
with, they&rsquo;re not covered. It&rsquo;s all implicitly <code>__fastcall</code> here. I appreciate
that this book is focused on 64-bit programming but giving the reader some
awareness of that potential difference could save them hours of confusion in
the future.</p>
<p>I wish I could have written something nicer about this book, but I really did
feel let down by it.  It doesn&rsquo;t cover core concepts and best practices in a
clear, methodical way.  Instead it dumps sample programs on the reader with
dubious code comments and hand-waving prose. I just can&rsquo;t see myself
recommending it to anyone. It&rsquo;s not clear or thorough enough to recommend to
beginners. Meanwhile I suspect experts would be better off improving their
knowledge by just reading the manuals published by Intel and AMD.</p>
<p>If someone knows of a better book covering this topic I&rsquo;d love to hear recommendations.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Let's write a hashmap in C]]></title>
    <link href="https://harry.pm/blog/lets_write_a_hashmap/" />
    <published>2022-01-02T00:00:00+00:00</published>
    <updated>2022-01-02T00:00:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/lets_write_a_hashmap/</id>
    <content type="html"><![CDATA[<p>I&rsquo;ve been writing C as my preferred language for many years now, but
in the kinds of projects I&rsquo;ve worked on I&rsquo;ve never needed to use
a <a href="https://en.wikipedia.org/wiki/Hash_table">hashmap</a>. That&rsquo;s
not because I&rsquo;ve never encountered a use case where it makes sense,
but because the software I&rsquo;ve worked on has always been dealing with
a few thousand elements at the very most, and not doing too many
searches of those elements.</p>
<p>With so few elements, any processor with a cache and prefetcher
worth its salt will yield excellent performance using just a plain
dynamic array, which are trivial to implement as needed. So that&rsquo;s
what I&rsquo;ve used.</p>
<p>However, on <a href="https://adventofcode.com/2021/day/23">day 23</a>
of 2021&rsquo;s advent of code I finally had need of a hashmap as an
optimisation. For that programming problem I found myself dealing
with hundreds of thousands of elements and doing (probably) millions
of lookups. Switching from a dynamic array to a hashmap improved the
runtime of my solution from 10 seconds to 0.3 seconds. For that I
used klib&rsquo;s excellent
<a href="https://github.com/attractivechaos/klib/blob/master/khash.h">hashmap implementation</a>.</p>
<p>While I know how it works conceptually, there&rsquo;s a huge difference between
reading about how something works and implementing it yourself, so I wanted
to finally learn how to implement my own hashmap from scratch. In this
blog post, I&rsquo;ll be sharing what I came up with.</p>
<h2 id="design-considerations">Design considerations</h2>
<p>As Wikipedia will tell you, there&rsquo;s a lot of ways to build a hashmap,
each with its own sets of pros and cons. I&rsquo;ll be focusing on the
simplest possible approach, just to get something working. I can
always make more sophisticated optimisations later as needed.</p>
<h3 id="hashing">Hashing</h3>
<p>A hash map needs a hash function, but I&rsquo;ve never actually written a
hash function before either. I don&rsquo;t know what a good hash function
for this use case would actually be, since I&rsquo;ve only ever heard of
checksums and cryptographically secure hashes.</p>
<p>After asking some friends on irc, I settled on
<a href="http://www.cse.yorku.ca/~oz/hash.html">djb2</a>,
a very simple, but apparently effective, hash function by the famous
DJB.</p>
<p>The function is very simple:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#078;font-weight:bold">unsigned</span> <span style="color:#078;font-weight:bold">int</span> <span style="color:#c0f">djb2</span>(<span style="color:#069;font-weight:bold">const</span> <span style="color:#078;font-weight:bold">char</span> <span style="color:#555">*</span>bytes, size_t len)
{
  <span style="color:#078;font-weight:bold">unsigned</span> <span style="color:#078;font-weight:bold">int</span> hash <span style="color:#555">=</span> <span style="color:#f60">5381</span>;
  <span style="color:#069;font-weight:bold">for</span> (size_t i <span style="color:#555">=</span> <span style="color:#f60">0</span>; i <span style="color:#555">&lt;</span> len; <span style="color:#555">++</span>i)
    hash <span style="color:#555">=</span> hash <span style="color:#555">*</span> <span style="color:#f60">33</span> <span style="color:#555">+</span> bytes[i];
  <span style="color:#069;font-weight:bold">return</span> hash;
}
</code></pre></td></tr></table>
</div>
</div><p>That&rsquo;s actually simple enough that I could pull it from memory if the
need should ever arise in future. Nice!</p>
<h3 id="collision-resolution">Collision resolution</h3>
<p>So what happens if two keys hashes point to the same bucket? The two
most common solutions seem to be <em>separate chaining</em> and
<em>open addressing</em>. The former means each bucket holding a linked list
containing all the key-value pairs that live in that bucket. The
latter says to just roll over onto the next adjacent bucket until you
find one that has space.</p>
<p>In the interests of simplicity I&rsquo;m going to use open addressing. That
way I won&rsquo;t also have to much around with linked lists, I&rsquo;ll just have
a big array of buckets to oversee.</p>
<p>Open addressing does have an issue though. Let&rsquo;s look at what happens if
a conflict occurs but then the key that &lsquo;won&rsquo; the conflict is deleted:</p>
<ol>
<li>The hashmap is initially empty</li>
<li><code>fizz</code> is looked up, which maps to bucket 1
<ul>
<li>Bucket 1 is empty, so the lookup fails</li>
</ul>
</li>
<li><code>foo=bar</code> is inserted, mapping to bucket 1</li>
<li><code>fizz=buzz</code> is inserted, also mapping to bucket 1
<ul>
<li>Bucket 1 is occupied, so it goes into bucket 2 instead</li>
</ul>
</li>
<li><code>fizz</code> is looked up
<ul>
<li>Bucket 1 is occupied but has the wrong key</li>
<li>Bucket 2 is occupied and has the right key, so the lookup succeeds</li>
</ul>
</li>
<li><code>foo</code> is deleted, leaving bucket 1 empty</li>
<li><code>fizz</code> is looked up, which maps to bucket 1
<ul>
<li>Bucket 1 is empty, so the lookup fails</li>
</ul>
</li>
</ol>
<p>The key for <code>fizz</code> is now in the wrong bucket with no indication
that there was ever a conflict. We could check the next bucket
just in case, but what if there were two conflicts and <code>fizz</code> is
actually in bucket 3? We don&rsquo;t want to fall back to a full search
of the entire hashmap for a missing key. So what do we do?</p>
<p>A peek at klib&rsquo;s code gives the solution. When deleting a value,
instead of marking its bucket as empty, mark it as &lsquo;deleted&rsquo; instead.
When writing, treat a deleted bucket the same as an empty one. When
reading, skip over deleted buckets but don&rsquo;t stop searching until an
empty non-deleted bucket is found.</p>
<p>That way, even though <code>fizz</code> is in the wrong bucket, the search will
still move past the &lsquo;deleted&rsquo; bucket onto the one <code>fizz</code> is actually
stored in.</p>
<h3 id="load-factor">Load factor</h3>
<p>How full should we allow the hashmap to get before increasing its size?
If we let it get too full then we&rsquo;ll start to have many collisions and
long chains of contiguous entries that have to be searched linearly,
losing that O(1) performance we&rsquo;re looking for.</p>
<p>If we oversize it, we waste memory.</p>
<p>Wikipedia suggests a factor of 0.6-0.75 is good. I&rsquo;m going to keep the
maths simple and double the size of the hashmap any time we get beyond
a load factor of 0.75, and halve the size of the hashmap any time that
it drops below 0.25.</p>
<h3 id="type-specialisation">Type specialisation</h3>
<p>I quite like klib&rsquo;s approach of using macros to generate type specific
versions of its hashmap as needed, similar to how C++&rsquo;s templating
works. I&rsquo;m not going to incorporate that in my first attempt though.
Instead I&rsquo;ll use hardcoded key and value types for now, but typedef
them so that they&rsquo;re easy to change out later.</p>
<h2 id="the-types">The types</h2>
<p>With those decisions made, we&rsquo;re ready to begin:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">typedef</span> <span style="color:#078;font-weight:bold">char</span><span style="color:#555">*</span> hm_key;
<span style="color:#069;font-weight:bold">typedef</span> <span style="color:#078;font-weight:bold">char</span><span style="color:#555">*</span> hm_value;

<span style="color:#069;font-weight:bold">enum</span> hm_state {
  HM_EMPTY <span style="color:#555">=</span> <span style="color:#f60">0</span>,
  HM_VALID <span style="color:#555">=</span> <span style="color:#f60">1</span>,
  HM_DELETED <span style="color:#555">=</span> <span style="color:#f60">2</span>,
};

<span style="color:#069;font-weight:bold">struct</span> hashmap {
  size_t len; <span style="color:#09f;font-style:italic">// number of buckets in use, for tracking load
</span><span style="color:#09f;font-style:italic"></span>  size_t cap; <span style="color:#09f;font-style:italic">// number of buckets allocated
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">enum</span> hm_state <span style="color:#555">*</span>states; <span style="color:#09f;font-style:italic">// array of bucket states
</span><span style="color:#09f;font-style:italic"></span>  hm_key <span style="color:#555">*</span>keys; <span style="color:#09f;font-style:italic">// array of bucket keys
</span><span style="color:#09f;font-style:italic"></span>  hm_value <span style="color:#555">*</span>values; <span style="color:#09f;font-style:italic">// array of bucket values
</span><span style="color:#09f;font-style:italic"></span>};
</code></pre></td></tr></table>
</div>
</div><p>So first we typedef some custom types for easy replacement later.
Then we create an enum for tracking the state of each bucket in
our hashmap. Lastly we define the hashmap struct itself.</p>
<h2 id="the-functions">The functions</h2>
<h3 id="initialisation">Initialisation</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> <span style="color:#078;font-weight:bold">void</span> <span style="color:#c0f">hashmap_init</span>(<span style="color:#069;font-weight:bold">struct</span> hashmap <span style="color:#555">*</span>hm)
{
  memset(hm, <span style="color:#f60">0</span>, <span style="color:#069;font-weight:bold">sizeof</span> <span style="color:#555">*</span>hm);
}
</code></pre></td></tr></table>
</div>
</div><p>I&rsquo;m a fan of data structures that are valid when zeroed out. That
allows me to instantiate them on the stack effortlessly like so:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> hashmap hmap <span style="color:#555">=</span> {<span style="color:#f60">0</span>};
</code></pre></td></tr></table>
</div>
</div><p>But users of it shouldn&rsquo;t <em>need</em> to know that, so if they <code>malloc</code> the
hashmap it&rsquo;s good to have the <code>hashmap_init</code> function for them to use
without needing to know about the design choices I&rsquo;ve made.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> <span style="color:#078;font-weight:bold">void</span> <span style="color:#c0f">hashmap_free</span>(<span style="color:#069;font-weight:bold">struct</span> hashmap <span style="color:#555">*</span>hm)
{
  <span style="color:#069;font-weight:bold">if</span> (<span style="color:#555">!</span>hm)
    <span style="color:#069;font-weight:bold">return</span>;
  <span style="color:#069;font-weight:bold">if</span> (hm<span style="color:#555">-&gt;</span>cap) {
    free(hm<span style="color:#555">-&gt;</span>keys);
    free(hm<span style="color:#555">-&gt;</span>values);
    free(hm<span style="color:#555">-&gt;</span>states);
  }
  memset(hm, <span style="color:#f60">0</span>, <span style="color:#069;font-weight:bold">sizeof</span> <span style="color:#555">*</span>hm);
}
</code></pre></td></tr></table>
</div>
</div><p>Next is the <code>hashmap_free</code> which again is nothing exciting, just some
good housekeeping. Zeroing itself out isn&rsquo;t strictly necessary but will
help generate nice clean crashes if misused. A null pointer is way more
obvious than a stale one in a core dump.</p>
<h3 id="hashing-1">Hashing</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> size_t <span style="color:#c0f">hashmap_hash_key</span>(hm_key key)
{
  size_t v <span style="color:#555">=</span> <span style="color:#f60">5381</span>;
  <span style="color:#069;font-weight:bold">for</span> (size_t i <span style="color:#555">=</span> <span style="color:#f60">0</span>; key[i]; <span style="color:#555">++</span>i)
    v <span style="color:#555">=</span> v <span style="color:#555">*</span> <span style="color:#f60">33</span> <span style="color:#555">+</span> key[i];
  <span style="color:#069;font-weight:bold">return</span> v;
}
</code></pre></td></tr></table>
</div>
</div><p>This is exactly as I described before, except that it&rsquo;s now returning a
<code>size_t</code>. This is just done as a convenience since I know I&rsquo;ll be
using it as an index into my buckets, albeit with the modulo operator.
It saves me some casting but I also know that it&rsquo;ll be 64-bits wide
most everywhere, unlike <code>unsigned int</code>.</p>
<h3 id="getter--setters">Getter &amp; Setters</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#099">#define hashmap_begin(hm) ((size_t)(0))
</span><span style="color:#099">#define hashmap_end(hm) (((hm)-&gt;cap))
</span><span style="color:#099">#define hashmap_states(hm, it) ((hm)-&gt;states[(it)])
</span><span style="color:#099">#define hashmap_key(hm, it) ((hm)-&gt;keys[(it)])
</span><span style="color:#099">#define hashmap_value(hm, it) ((hm)-&gt;values[(it)])
</span><span style="color:#099">#define hashmap_exists(hm, it) ((it) &lt; (hm)-&gt;cap &amp;&amp; hashmap_states((hm), (it)) == HM_VALID)
</span></code></pre></td></tr></table>
</div>
</div><p>Again inspired by klib, I decided to make these accessor functions
preprocessor macros, to give the compiler the best opportunity to
optimise them. These could just be <code>static inline</code> functions in the
header arguably, but for the key and value macros there is one nice
advantage:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> hashmap hm; <span style="color:#09f;font-style:italic">// our hashmap
</span><span style="color:#09f;font-style:italic"></span>size_t it; <span style="color:#09f;font-style:italic">// assume it is a valid index or &#39;iterator&#39; into the hashmap
</span><span style="color:#09f;font-style:italic"></span>hashmap_value(<span style="color:#555">&amp;</span>hm, it) <span style="color:#555">=</span> <span style="color:#c30">&#34;value&#34;</span>; <span style="color:#09f;font-style:italic">// assign a value
</span></code></pre></td></tr></table>
</div>
</div><p>That kind of assignment can be done without having to dance around
pointers.</p>
<h3 id="insertion">Insertion</h3>
<p>With the boilerplate done, we can get onto the meat of the hashmap.</p>
<p>Insertion is a nice simple operation conceptually:</p>
<ol>
<li>Hash the key, modulo by the number of buckets to get the bucket index</li>
<li>If the bucket is occupied with a different key, try the next bucket.</li>
<li>Write the key and value into the bucket, mark it as valid, and update
<code>len</code>.</li>
</ol>
<p>In code, this only takes a few minutes to whip up:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> size_t <span style="color:#c0f">hashmap_insert</span>(<span style="color:#069;font-weight:bold">struct</span> hashmap <span style="color:#555">*</span>hm, hm_key key, <span style="color:#078;font-weight:bold">bool</span> <span style="color:#555">*</span>existed)
{
  <span style="color:#09f;font-style:italic">// First see if we need to resize the hashmap
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// If that fails, abort and return an invalid iterator
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (<span style="color:#555">!</span>hashmap_resize(hm))
    <span style="color:#069;font-weight:bold">return</span> hm<span style="color:#555">-&gt;</span>cap;

  <span style="color:#09f;font-style:italic">// Hash the key, modulo by the number of buckets
</span><span style="color:#09f;font-style:italic"></span>  size_t it <span style="color:#555">=</span> hashmap_hash_key(key) <span style="color:#555">%</span> hm<span style="color:#555">-&gt;</span>cap;

  <span style="color:#09f;font-style:italic">// Skip over full buckets until we find an available one,
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// either empty or deleted is fine. We know this can&#39;t get
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// into an infinite loop due to lack of space since we limi
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// the load factor to 0.75.
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">while</span> (hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">==</span> HM_VALID <span style="color:#555">&amp;&amp;</span> strcmp(key, hm<span style="color:#555">-&gt;</span>keys[it]))
    it <span style="color:#555">=</span> (it <span style="color:#555">+</span> <span style="color:#f60">1</span>) <span style="color:#555">%</span> hm<span style="color:#555">-&gt;</span>cap;

  <span style="color:#09f;font-style:italic">// If we&#39;re not overwriting an existing value with the same key then
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// to increment the count of how many buckets are in use
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">!=</span> HM_VALID)
    hm<span style="color:#555">-&gt;</span>len <span style="color:#555">+=</span> <span style="color:#f60">1</span>;
  <span style="color:#09f;font-style:italic">// If we&#39;ve been given a valid pointer, use it to report whether the
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// key already existed in the hashmap or not.
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (existed)
    <span style="color:#555">*</span>existed <span style="color:#555">=</span> hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">==</span> HM_VALID;
  <span style="color:#09f;font-style:italic">// Lastly, mark the bucket as in use and set its key and value.
</span><span style="color:#09f;font-style:italic"></span>  hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">=</span> HM_VALID;
  hm<span style="color:#555">-&gt;</span>keys[it] <span style="color:#555">=</span> key;
  hm<span style="color:#555">-&gt;</span>values[it] <span style="color:#555">=</span> value;
  <span style="color:#09f;font-style:italic">// And return an iterator to the bucket
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">return</span> it;
}
</code></pre></td></tr></table>
</div>
</div><p>One operation I didn&rsquo;t mention before is the <code>hashmap_resize</code> function
that I call. That is going to be the most difficult part of the hashmap
so I&rsquo;ll save it for last. We can just assume that if it returns true
then the hashmap has buckets allocated and a reasonable load factor.</p>
<h3 id="removal">Removal</h3>
<p>Compared to insertion, removal is trivial. We&rsquo;re going to assume that
the caller already has an iterator to the bucket they wish to remove,
so we just need to check it&rsquo;s a valid iterator, mark the bucket
deleted if so, and then shrink the hashmap if necessary.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> <span style="color:#078;font-weight:bold">void</span> <span style="color:#c0f">hashmap_remove</span>(<span style="color:#069;font-weight:bold">struct</span> hashmap <span style="color:#555">*</span>hm, size_t it)
{
  <span style="color:#069;font-weight:bold">if</span> (hashmap_exists(hm, it)) {
    hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">=</span> HM_DELETED;
    hm<span style="color:#555">-&gt;</span>len <span style="color:#555">-=</span> <span style="color:#f60">1</span>;
  }
  hashmap_resize(hm);
}
</code></pre></td></tr></table>
</div>
</div><h3 id="lookup">Lookup</h3>
<p>Now for the most useful function of all: looking up a value in the hashmap
by key. Conceptually it&rsquo;s quite similar to what we do for insertion. We
hash the key and modulo it to get the bucket index the value should live in.
If it&rsquo;s the right bucket, return its index. If not, but the bucket is populated
or deleted, try the next bucket in case there was a collision.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> size_t <span style="color:#c0f">hashmap_find</span>(<span style="color:#069;font-weight:bold">const</span> <span style="color:#069;font-weight:bold">struct</span> hashmap <span style="color:#555">*</span>hm, hm_key key)
{
  <span style="color:#09f;font-style:italic">// Avoid dereferencing null pointers if we&#39;ve not allocated any buffers yet
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (hm<span style="color:#555">-&gt;</span>cap <span style="color:#555">==</span> <span style="color:#f60">0</span>)
    <span style="color:#069;font-weight:bold">return</span> hm<span style="color:#555">-&gt;</span>cap;

  <span style="color:#09f;font-style:italic">// Calculate the bucket the key corresponds to
</span><span style="color:#09f;font-style:italic"></span>  size_t it <span style="color:#555">=</span> hashmap_hash_key(key) <span style="color:#555">%</span> hm<span style="color:#555">-&gt;</span>cap;

  <span style="color:#09f;font-style:italic">// Search for a bucket with a matching key.
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// Keep going for deleted buckets, in case there was a collision
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// but then the original entry was deleted.
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">while</span> (hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">==</span> HM_DELETED <span style="color:#555">||</span> (hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">==</span> HM_VALID <span style="color:#555">&amp;&amp;</span> strcmp(key, hm<span style="color:#555">-&gt;</span>keys[it])))
    it <span style="color:#555">=</span> (it <span style="color:#555">+</span> <span style="color:#f60">1</span>) <span style="color:#555">%</span> hm<span style="color:#555">-&gt;</span>cap;

  <span style="color:#09f;font-style:italic">// If we found the right bucket, return the index. Otherwise return an invalid iterator
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (hm<span style="color:#555">-&gt;</span>states[it] <span style="color:#555">!=</span> HM_VALID)
    <span style="color:#069;font-weight:bold">return</span> hm<span style="color:#555">-&gt;</span>cap;
  <span style="color:#069;font-weight:bold">return</span> it;
}
</code></pre></td></tr></table>
</div>
</div><h3 id="resizing">Resizing</h3>
<p>We can read from and write to the hashmap, but we&rsquo;ve yet to provide
that resize function we called before.</p>
<p>Resizing is going to be an expensive operation, since it involves
allocating memory, iterating through every element in the hashmap and
rehashing all their keys. So we don&rsquo;t want to do it regularly.
The first thing we want to determine then is whether we should resize
or not. Most of the time we won&rsquo;t, which will be when our load factor
is between 0.25 and 0.75. If our load factor is less than 0.25 we
should maintain a minimum size. I&rsquo;ve picked 128 somewhat arbitrarily.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#099">#define HM_MIN_CAP 128
</span></code></pre></td></tr></table>
</div>
</div><p>Once we&rsquo;ve decided to resize, we need to know what the new size will
be. We want this to be a large enough increment to avoid having to
resize regularly but without growing too large or too small too
rapidly. I&rsquo;ve settled on doubling and halving in size respectively,
which seems to be fairly standard.</p>
<p>Knowing the new size we can allocate a new set of buckets. Then we
simply have to iterate through all the existing buckets and for any
populated ones, rehash the key modulo the new capacity, and write
the key-value pairs to the new buckets.</p>
<p>I&rsquo;ve made this slightly more complicated by defining my key, value,
and states arrays separately. They could have been grouped together
under a <code>struct hashmap_bucket</code> struct, but this is how I&rsquo;ve done
it. Arguably this way should have better performance since the states
array is going to be accessed and iterated through frequently, so
keeping it densely packed in memory will be more cache friendly.
This is absolutely a premature and untested optimisation, but so be
it.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">static</span> <span style="color:#078;font-weight:bold">bool</span> <span style="color:#c0f">hashmap_resize</span>(<span style="color:#069;font-weight:bold">struct</span> hashmap <span style="color:#555">*</span>hm)
{
  size_t oldCap <span style="color:#555">=</span> hm<span style="color:#555">-&gt;</span>cap;
  size_t newCap;

  <span style="color:#09f;font-style:italic">// Calculate the new capacity depending on our current load
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// factor
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (<span style="color:#555">!</span>hm<span style="color:#555">-&gt;</span>cap <span style="color:#555">||</span> hm<span style="color:#555">-&gt;</span>len <span style="color:#555">*</span> <span style="color:#f60">4</span> <span style="color:#555">&gt;</span> hm<span style="color:#555">-&gt;</span>cap <span style="color:#555">*</span> <span style="color:#f60">3</span>) {
    newCap <span style="color:#555">=</span> oldCap <span style="color:#555">&gt;</span> <span style="color:#f60">0</span> <span style="color:#555">?</span> oldCap <span style="color:#555">*</span> <span style="color:#f60">2</span> <span style="color:#555">:</span> HM_MIN_CAP;
  } <span style="color:#069;font-weight:bold">else</span> <span style="color:#069;font-weight:bold">if</span> (hm<span style="color:#555">-&gt;</span>cap <span style="color:#555">&gt;</span> HM_MIN_CAP <span style="color:#555">&amp;&amp;</span> hm<span style="color:#555">-&gt;</span>len <span style="color:#555">*</span> <span style="color:#f60">4</span> <span style="color:#555">&lt;</span> hm<span style="color:#555">-&gt;</span>cap) {
    newCap <span style="color:#555">=</span> oldCap <span style="color:#555">/</span> <span style="color:#f60">2</span>;
  } <span style="color:#069;font-weight:bold">else</span> {
    <span style="color:#09f;font-style:italic">// Or if no resizing required, return success early
</span><span style="color:#09f;font-style:italic"></span>    <span style="color:#069;font-weight:bold">return</span> <span style="color:#366">true</span>;
  }

  <span style="color:#09f;font-style:italic">// Allocate our new buckets
</span><span style="color:#09f;font-style:italic"></span>  hm_key <span style="color:#555">*</span>newKeys <span style="color:#555">=</span> calloc(newCap, <span style="color:#069;font-weight:bold">sizeof</span> <span style="color:#555">*</span>hm<span style="color:#555">-&gt;</span>keys);
  hm_value <span style="color:#555">*</span>newValues <span style="color:#555">=</span> calloc(newCap, <span style="color:#069;font-weight:bold">sizeof</span> <span style="color:#555">*</span>hm<span style="color:#555">-&gt;</span>values);
  <span style="color:#069;font-weight:bold">enum</span> hm_state <span style="color:#555">*</span>newStates <span style="color:#555">=</span> calloc(newCap, <span style="color:#069;font-weight:bold">sizeof</span> <span style="color:#555">*</span>hm<span style="color:#555">-&gt;</span>states);
  <span style="color:#09f;font-style:italic">// If any of the allocations failed, we need to clean them up
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// and abort. free on a null pointer is a no-op, helpfully.
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">if</span> (<span style="color:#555">!</span>newStates <span style="color:#555">||</span> <span style="color:#555">!</span>newKeys <span style="color:#555">||</span> <span style="color:#555">!</span>newValues) {
    free(newStates);
    free(newKeys);
    free(newValues);
    <span style="color:#069;font-weight:bold">return</span> <span style="color:#366">false</span>;
  }

  <span style="color:#09f;font-style:italic">// Now rehash all the old buckets, keeping only those
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// holding a value
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#069;font-weight:bold">for</span> (size_t i <span style="color:#555">=</span> <span style="color:#f60">0</span>; i <span style="color:#555">&lt;</span> oldCap; <span style="color:#555">++</span>i) {
    <span style="color:#069;font-weight:bold">if</span> (hm<span style="color:#555">-&gt;</span>states[i] <span style="color:#555">!=</span> HM_VALID)
      <span style="color:#069;font-weight:bold">continue</span>;
    size_t it <span style="color:#555">=</span> hashmap_hash_key(hm<span style="color:#555">-&gt;</span>keys[i]) <span style="color:#555">%</span> newCap;
    <span style="color:#069;font-weight:bold">while</span> (newStates[it] <span style="color:#555">==</span> HM_VALID)
      it <span style="color:#555">=</span> (it <span style="color:#555">+</span> <span style="color:#f60">1</span>) <span style="color:#555">%</span> newCap;
    newStates[it] <span style="color:#555">=</span> HM_VALID;
    newKeys[it] <span style="color:#555">=</span> hm<span style="color:#555">-&gt;</span>keys[i];
    newValues[it] <span style="color:#555">=</span> hm<span style="color:#555">-&gt;</span>values[i];
  }

  <span style="color:#09f;font-style:italic">// Clean up the old buckets and finally install our new ones
</span><span style="color:#09f;font-style:italic"></span>  free(hm<span style="color:#555">-&gt;</span>keys);
  free(hm<span style="color:#555">-&gt;</span>values);
  free(hm<span style="color:#555">-&gt;</span>states);
  hm<span style="color:#555">-&gt;</span>keys <span style="color:#555">=</span> newKeys;
  hm<span style="color:#555">-&gt;</span>values <span style="color:#555">=</span> newValues;
  hm<span style="color:#555">-&gt;</span>states <span style="color:#555">=</span> newStates;
  hm<span style="color:#555">-&gt;</span>cap <span style="color:#555">=</span> newCap;

  <span style="color:#069;font-weight:bold">return</span> <span style="color:#366">true</span>;
}
</code></pre></td></tr></table>
</div>
</div><h2 id="putting-it-all-together">Putting it all together</h2>
<p>With all of the above combined, we have a fully functioning hashmap,
and that item is checked off my bucket list. Pardon the pun.</p>
<p>There&rsquo;s many many improvements that could be made to this in terms
of versatility, robustness, and performance, but in my rough testing
using my advent of code solution as a benchmark, I found this
performed within 10% of the much more mature klib implementation.</p>
<p>As a first stab at a hashmap I&rsquo;m very happy with that. I hope that
you found this exercise as helpful as I did. It turns out that hashmaps
are very easy to build so long as you have a decent hash function to use.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Happy New Year 2022]]></title>
    <link href="https://harry.pm/blog/happy_new_year_2022/" />
    <published>2022-01-01T00:00:00+00:00</published>
    <updated>2022-01-01T00:00:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/happy_new_year_2022/</id>
    <content type="html"><![CDATA[<p>Happy new year everyone. I&rsquo;ve never been one for new year&rsquo;s resolutions
in the past but I thought I might finally give it a go this year.</p>
<p>So in 2022 I plan to become to learn to touch type &ldquo;properly&rdquo;. I
currently type using eight out of ten fingers, neglecting my pinkies.
I type this way at a decent speed, around 90-110 WPM, but with poor
accuracy.</p>
<p>I technically started learning to touch type a few days ago, but
new years seems like a convenient way to give myself some accountability
for sticking with it and trying to cement the new muscle memory.</p>
<p>So far I&rsquo;m able to get 60-80 WPM with the proper ten finger touch
typing style but only when focusing and mostly typing lower case
prose. When programming or typing text with a lot of capital letters
or symbols, things get much harder.</p>
<p>I&rsquo;ve also ordered a new keyboard, the
<a href="https://ultimatehackingkeyboard.com/">UHK 60 v2</a>.
It looks very well made, and I&rsquo;m hoping that the split layout will
aid my posture and ever suffering back. Unfortunately it won&rsquo;t ship
until April, so I have the personal goal of typing at 100+ WPM
by then using the proper style.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Phone Wishlist]]></title>
    <link href="https://harry.pm/blog/phone_wishlist/" />
    <published>2021-12-28T00:00:00+00:00</published>
    <updated>2021-12-28T00:00:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/phone_wishlist/</id>
    <content type="html"><![CDATA[<p>I&rsquo;ve run Linux on my personal laptop as a daily driver for many years now,
and have grown to love the freedom and flexibility it has given me.
Specifically how customisable it is, being able to trust that all the
software running on it has my best interests as a user at heart, and the
wonderful daily development experience offered by a unix environment.</p>
<p>The only device to perhaps get more use is my phone. My phone is like my
laptop in many ways. It&rsquo;s portable, runs the Linux kernel, and is a
critical component of my daily computing needs. However, it is built
and programmed by what is probably the largest advertising company on
Earth, and one whose reputation for respecting privacy has been on a
continuous decline for at least 10 years.</p>
<p>So why do I do most of my communication on a device I&rsquo;m unable to fully
inspect or customise, when that device is replaced more frequently
than my laptop and probably costs more? Lack of choice is the obvious
answer, which is why I&rsquo;ve been excitedly monitoring the
<a href="https://www.pine64.org/pinephone/">PinePhone</a>
from a distance for a while now.</p>
<p>I want to have a phone that I can trust fully, but it needs to work as
a daily driver in 2021 for someone who isn&rsquo;t willing to be cut off from
modern conveniences.</p>
<p>The hardware side of the PinePhone Pro is coming along very nicely but
the software sadly isn&rsquo;t ready for me to daily drive it. So I&rsquo;ve been
thinking a bit lately about what it would take for an open source phone
to be ready for me to daily drive.</p>
<p>These are the requirements I&rsquo;ve come up with:</p>
<h2 id="1-phone-calls">1. Phone calls</h2>
<p>On most handsets, or at least the ones I have spare, the leading Linux
distributions aimed at phones do not support making phone calls. This
isn&rsquo;t laziness on the part of the developers, but down to the
myriad of undocumented GSM chips in modern hardware and a lack of open
source drivers for them.</p>
<h2 id="2-common-instant-messaging-platforms">2. Common instant messaging platforms</h2>
<p>I love irc, and I wish it were still the standard for instant messaging, or
that xmpp were still loved and supported by the walled garden builders,
but unfortunately most people I message on a daily basis through my phone
are using Signal or WhatsApp. I want to use an open source device but if
that means dropping out of family chats, that&rsquo;s a deal breaker. I&rsquo;m not
prepared to ostracise myself from non-FOSS communities over this.</p>
<h2 id="3-web-browsing">3. Web browsing</h2>
<p>I&rsquo;m going to be missing out on a bunch of common apps. That&rsquo;s a given, but
fortunately most services that I use also provide a mobile web interface.
So having a decent web browser, preferably with an ad-blocker is a must
have workaround.</p>
<h2 id="4-email-client">4. Email client</h2>
<p>Like most people, mobile access to my email is critical, whether that&rsquo;s for
accessing theatre tickets or looking up appointment details on the go,
it&rsquo;s mandatory. The client needs to support IMAP and SMTP, and cache my
inbox locally so that I can still pull up tickets or similar when I don&rsquo;t
have signal.</p>
<h2 id="5-full-disk-encryption">5. Full disk encryption</h2>
<p>This is also a requirement on my laptop. These devices contain a lot of
sensitive information, like our email inboxes or recently taken photos,
and are easily stolen or lost. If that should ever happen, I want the
peace of mind to know that whatever data is on the device is secure.</p>
<h2 id="stretch-goals">Stretch goals</h2>
<p>The following items are nice to have but I wouldn&rsquo;t require them before
switching to such a device:</p>
<ul>
<li>Offline copy of OpenStreetMap</li>
<li>A decent camera</li>
<li>More than 24 hours battery life</li>
<li>Automatic recording of all phone calls</li>
<li>Good integration with password managers</li>
</ul>
<h2 id="pinetime">PineTime</h2>
<p>I also want to spare an honourable mention for the
<a href="https://www.pine64.org/pinetime/">PineTime watch</a>
which I have been using for a couple of months now. I&rsquo;ve not worn a watch for
most of my life, and my only previous experience of a smart watch was a
Motorola 360G I was once gifted.</p>
<p>I really like the PineTime, for the price it&rsquo;s a very nice piece of
hardware and the fully open source nature of the operating system appeals
to me greatly. There&rsquo;s a few things I&rsquo;d like to tweak about it if I ever
find the time to dig into its guts, but for now that can just be the subject of
a future blog post.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Compressing coordinate systems]]></title>
    <link href="https://harry.pm/blog/compressing_coordinate_systems/" />
    <published>2021-12-23T23:31:00+00:00</published>
    <updated>2021-12-23T23:31:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/compressing_coordinate_systems/</id>
    <content type="html"><![CDATA[<p>The infamous YouTube algorithm recommended me a very interesting
<a href="https://www.youtube.com/watch?v=YKpViLcTp64">video</a>
recently, in which Neal Wu was the first person to complete
Advent of Code 2021
<a href="https://adventofcode.com/2021/day/22">day 22</a>.</p>
<p>I&rsquo;ve never watched a competitive programmer in action before, so it was
fascinating to watch his thought process and methods, since the values being
optimised for are vastly different than when building software you intend to
maintain for years.</p>
<p>The gist of the problem being solved is:
You are given a series of axis-aligned bounding boxes and on/off states.
Apply these boxes to a 3D grid, turning on or off all the cells within each
bounding box as instructed.
After applying all the bounding boxes, count how many cells are switched on.</p>
<p>The first twenty or so bounding boxes are easy enough, sitting within +-50
units from the origin. However, the remainder cover a much larger area,
+-100,000 units from the origin. The obvious implication being that the naive
solution of constructing the grid in memory isn&rsquo;t feasible.
200,000 x 200,000 x 200,000 is far too many cells to iterate over in a
reasonable amount of time.</p>
<p>My solution for this was to borrow from my hobby game-dev programming
experience and manipulate the bounding boxes directly, rather than the
cells that they affect.</p>
<p>My algorithm was roughly:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">regionList = []
input = [bounding boxes + on/off state]

for isOn,box in input:
  for region in regionList:
    if region fully within box:
      remove region
    if region partially within box:
      region_a, region_b = split region along an edge of box
      remove region from regionList
      add region_a and region_b to regionList
  repeat above until no further changes made to regionList
  if isOn:
    add box to regionList
result = sum of volumes of regions in regionList
</code></pre></td></tr></table>
</div>
</div><p>What I&rsquo;m quite pleased about with this algorithm is that it does not
have special logic to deal with all the different ways that two
AABBs can overlap with each other. The only edge case, pardon the pun,
is when two AABBs partially overlap but one is not fully contained by the
other. By picking any intersection edge, we can split one of the AABBs in two.
With enough passes the intersection will eventually simplify to the complete
overlap case.</p>
<p>This is the pure maths approach and I thought it was quite neat, but
when I watched Neal&rsquo;s video I couldn&rsquo;t figure out what his approach
was until he explained it afterwards.</p>
<p>His approach is something I&rsquo;d never heard of before, and I don&rsquo;t
think I&rsquo;d ever have thought of it. It&rsquo;s beautiful in its simplicity.</p>
<p>Build a grid, much like the naive solution, but not out of 1x1x1 cells.
Instead, put cell boundaries at all boundaries that the input AABBs
will sit on. Let me try to clarify through the medium of ascii art:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">Dense grid of 1x1x1 cells.
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+

Sparse grid of differently sized cells.
+-+-+-+-+-+-+-+-+-+-+-+-+
|     |   |     |   |   |
|     |   |     |   |   |
|     |   |     |   |   |
+-+-+-+-+-+-+-+-+-+-+-+-+
|     |   |     |   |   |
|     |   |     |   |   |
+-+-+-+-+-+-+-+-+-+-+-+-+
|     |   |     |   |   |
|     |   |     |   |   |
+-+-+-+-+-+-+-+-+-+-+-+-+
</code></pre></td></tr></table>
</div>
</div><p>When turning cells on and off by the given AABBs, both grids will give
the same answer. By placing boundaries only where absolutely necessary
based on the AABBs, the dimensions of the grid and memory requirements
for it are vastly reduced. A 5x4x8 region in the dense grid requires
a whopping 160 bits of memory to keep track of. In the sparse grid
it&rsquo;s reduced to a single bit, and 5x4x8 would be a <em>very</em> small cell
compared to the ones typically generated by the advent of code input.
So it&rsquo;s obvious how this trick reduces the space and time requirements
of the problem by orders of magnitude.</p>
<p>These kinds of neat hacks are exactly the sort of thing I&rsquo;d love to
know more of. I don&rsquo;t know where Neal learned this, but I&rsquo;m going
to be sure to watch more of his competitive programming videos in
future to see what other tricks I can pinch from his toolbox.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Exceptions and flow control]]></title>
    <link href="https://harry.pm/blog/exceptions_and_flow_control/" />
    <published>2021-12-23T22:30:00+00:00</published>
    <updated>2021-12-23T22:30:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/exceptions_and_flow_control/</id>
    <content type="html"><![CDATA[<p>Yesterday&rsquo;s Advent of Code
<a href="https://adventofcode.com/2021/day/22">problem</a>
was about efficiently performing boolean operations on
<a href="https://en.wikipedia.org/wiki/Minimum_bounding_box">axis-aligned bounding boxes</a>.</p>
<p>While solving it, it reminded me of a significant optimisation I made
some years ago. Around 2014-2015, I was on a placement year away
from my computer science degree. I had a 12 month placement working
for the <em>Science and Technology Facilities Council</em>, a public sector
gig which had me working on
<a href="https://www.mantidproject.org/">Mantid</a>,
an open source data analysis application primarily for use on neutron
scattering experiments. That is, data from their particle
accelerator. It was a fun first experience of professional software
development and a good example of well written and maintained academic
software.</p>
<p>One task I had was to improve the performance of various
processing and filtering operations that Mantid could apply to a
user&rsquo;s dataset. One such operation required determining the
intersection of many pairs of axis-aligned bounding boxes.</p>
<p>This is a very simple calculation, but my profiling informed me that
it was taking the vast majority of the <em>eight minute</em> runtime of this
particular process.</p>
<p>The intersection test was defined like this:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp">
AABB <span style="color:#c0f">findIntersection</span>(<span style="color:#069;font-weight:bold">const</span> AABB <span style="color:#555">&amp;</span>a, <span style="color:#069;font-weight:bold">const</span> AABB <span style="color:#555">&amp;</span>b)
{
  <span style="color:#09f;font-style:italic">// if intersection found, return an AABB of intersected area
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// else, throw an exception
</span><span style="color:#09f;font-style:italic"></span>}
</code></pre></td></tr></table>
</div>
</div><p>This function was being called thousands and thousands of times on
many pairs of axis-aligned bounding boxes that very rarely
overlapped. The result was a deluge of non-stop exception handling.</p>
<p>Fixing that is simple enough fortunately, so I changed the function
to look like this:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#078;font-weight:bold">bool</span> <span style="color:#c0f">findIntersection</span>(<span style="color:#069;font-weight:bold">const</span> AABB <span style="color:#555">&amp;</span>a, <span style="color:#069;font-weight:bold">const</span> AABB <span style="color:#555">&amp;</span>b, AABB <span style="color:#555">&amp;</span>out)
{
  <span style="color:#09f;font-style:italic">// if intersection, write it to out and return true
</span><span style="color:#09f;font-style:italic"></span>  <span style="color:#09f;font-style:italic">// else, return false
</span><span style="color:#09f;font-style:italic"></span>}
</code></pre></td></tr></table>
</div>
</div><p>I knew that this would improve the performance, but I didn&rsquo;t
appreciate just what a difference it would make.</p>
<p>The total runtime for the processing decreased from eight minutes
down to just <strong>eight seconds</strong>. Instead of requiring a tea break,
the user could carry on working in just the time it takes to have
a nice yawn and stretch at their desk.</p>
<p>So when people say exceptions are a terrible way to implement flow
control, they aren&rsquo;t kidding. It doesn&rsquo;t just muddy the internal
flow of your software and make it harder to reason about; it can
have a significant user perceivable impact to the way your software
performs.</p>
<p>To this day, this remains the most satisfying performance fix I&rsquo;ve
made in my professional career.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Binary Tree Arrays]]></title>
    <link href="https://harry.pm/blog/binary_tree_arrays/" />
    <published>2021-12-20T01:21:00+00:00</published>
    <updated>2021-12-20T01:21:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/binary_tree_arrays/</id>
    <content type="html"><![CDATA[<p>This year, I have been taking part in
<a href="https://adventofcode.com">Advent of Code</a>
for the first time.
<a href="https://adventofcode.com/2021/day/18">Day 18&rsquo;s problem</a>
has required the use of binary trees.
Since I&rsquo;m solving these problems in C, binary tree arrays came to mind
as the perfect way to build and manage the binary trees I&rsquo;d be wrangling.</p>
<p>They&rsquo;re a beautifully simple way of positioning the elements in predictable
locations in memory. So I&rsquo;d like to take a few minutes to share what makes
them so great, in my mind.</p>
<p>Think of a binary tree like the following:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">               0
             /   \
           /       \
         /           \
       1               2
     /   \           /   \
    /     \         /     \
   3       4       5       6
  / \     / \     / \     / \
 7   8   9  10  11  12  13  14
</code></pre></td></tr></table>
</div>
</div><p>Excuse the poor proportions. If you lay out the nodes of the binary tree into
an array, using the indices given by the diagram above, then some neat
numerical properties appear:</p>
<ol>
<li>The children of a node at index <code>i</code> can be found at: <code>i*2+1</code> and <code>i*2+2</code>.</li>
<li>The parent of a node at index <code>i</code> can be found at: <code>(i-1)/2</code></li>
</ol>
<p>With these two properties, you can trivially construct a binary tree within
an array. The required size of the array can be inferred from the maximum depth
the tree will have. If you consider a depth of <code>1</code> to be a tree with 3 elements
then the required size of the array will always be <code>1+(1&lt;&lt;depth)</code>.</p>
<ol start="3">
<li>The size of the array for a binary tree of a given depth is <code>1+(1&lt;&lt;depth)</code></li>
</ol>
<p>Breadth first traversal is as simple as a for loop over the array, while depth
first traversal is the same as any other binary tree. In addition, the tree
is densely packed and doesn&rsquo;t waste space on pointers between nodes, making
it very cache friendly.</p>
<p>If you want to iterate through all the nodes at a given depth in the array,
the range of indices to iterate through is trivial to calculate with these
next two properties:</p>
<ol start="4">
<li>The number of nodes (&ldquo;width&rdquo;) at a given depth is <code>1&lt;&lt;depth</code></li>
<li>The first index at a given depth is <code>width-1</code>.</li>
</ol>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#069;font-weight:bold">struct</span> node array[<span style="color:#f60">32</span>];
size_t width <span style="color:#555">=</span> <span style="color:#f60">1</span><span style="color:#555">&lt;&lt;</span>depth;
<span style="color:#069;font-weight:bold">for</span> (size_t i <span style="color:#555">=</span> width<span style="color:#555">-</span><span style="color:#f60">1</span>; i <span style="color:#555">&lt;</span> <span style="color:#f60">2</span><span style="color:#555">*</span>width<span style="color:#555">-</span><span style="color:#f60">1</span>; <span style="color:#555">++</span>i) {
  <span style="color:#069;font-weight:bold">struct</span> node <span style="color:#555">*</span>n <span style="color:#555">=</span> array <span style="color:#555">+</span> i;
}
</code></pre></td></tr></table>
</div>
</div><p>If you want to know the depth of node, the calculation can be derived by
inverting the previous two properties.</p>
<ol start="6">
<li>The depth of a node is <code>log2(i+1)</code></li>
</ol>
<p>If you don&rsquo;t want to rely on a maths library, this is easily calculable by
finding the index of the left-most <code>1</code> bit of <code>i+1</code>.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c">size_t <span style="color:#c0f">depth</span>(size_t i)
{
  size_t d <span style="color:#555">=</span> <span style="color:#f60">0</span>;
  i <span style="color:#555">+=</span> <span style="color:#f60">1</span>;
  <span style="color:#069;font-weight:bold">while</span> (i <span style="color:#555">&gt;&gt;=</span> <span style="color:#f60">1</span>) {
    d<span style="color:#555">++</span>;
  }
  <span style="color:#069;font-weight:bold">return</span> d;
}
</code></pre></td></tr></table>
</div>
</div><p>On x86 there&rsquo;s the <code>bsr</code> instruction that accomplishes the same thing more
efficiently. Though you probably just want to use the <code>__builtin_clz</code> intrinsic
supported by both GCC and clang.</p>
<p>And that&rsquo;s all there really is to this data structure. The beauty of it is that
these properties are all easily rediscovered with a little thought, just by
considering a few examples. As a result, the only thing you <em>need</em> to know is
the first property.</p>
<p>Neat.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Blog refresh]]></title>
    <link href="https://harry.pm/blog/blog_refresh/" />
    <published>2021-12-17T19:00:00+00:00</published>
    <updated>2021-12-17T19:00:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/blog_refresh/</id>
    <content type="html"><![CDATA[<p>Five years ago, I finished university and started work as a software developer
in London. I also stopped blogging.</p>
<p>I&rsquo;ve decided to start blogging again, partly inspired by other blogs that I
enjoy, and partly because there are things I&rsquo;d like to share and discuss in a
more public or permanent format than irc and voip with friends.</p>
<p>I&rsquo;ve also removed several older blog posts, either because the information in
them was out of date, or the tone in which they were written isn&rsquo;t something
I would stand behind today.</p>
<p>Expect to see more here in the future.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Goodbye LaTeX, Hello HTML]]></title>
    <link href="https://harry.pm/blog/goodbye_latex/" />
    <published>2016-04-09T10:01:00+00:00</published>
    <updated>2016-04-09T10:01:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/goodbye_latex/</id>
    <content type="html"><![CDATA[<h2 id="its-not-me-its-you">It&rsquo;s not me, it&rsquo;s you.</h2>
<p>As a 3rd year Computer Science student, I&rsquo;m no stranger to LaTeX and the joys
of typesetting documents. Most of the time I&rsquo;m lazy and I just write my reports
in Markdown and compile them using the excellent <a href="http://pandoc.org">pandoc</a>.
Of course, the moment I need a little more control I have to revert back to
LaTeX, either embedded in the Markdown or by abandoning Markdown all together,
in order to take back control of the document&rsquo;s formatting. And of course, if
I ever need to deviate from LaTeX&rsquo;s oh-so-specific formatting, as I do from
time to time, I enter the seventh circle of hell, with cryptic backdoors and
hacks to get LaTeX to work anywhere close to how you want.</p>
<p>If you don&rsquo;t believe me, find a post-graduate student and hold up a sign that
reads <code>\renewcommand</code>. Chances are they&rsquo;ll have a PTSD induced panic attack.
Either that or they used Microsoft Word.</p>
<h2 id="enter-html">Enter HTML</h2>
<p>In one of my more coherent LaTeX compile failure panic attacks I had an epiphany.
I&rsquo;d just done some work in HTML and CSS, and it&rsquo;d been a great success. What if
I could use HTML and CSS to write documents in for print? Well, it turns out
not to have been such an original idea. Thomas Park built an interesting CSS
framework for academia called <a href="http://thomaspark.co/2015/01/pubcss-formatting-academic-publications-in-html-css/">PubCSS</a>.</p>
<p>Pretty cool work, and the examples are really polished. But in the CS tradition
of <a href="https://en.wikipedia.org/wiki/Not_invented_here">NIH syndrome</a>, I decided
I wanted something bespoke for my needs.</p>
<p>Now, I know what most of you might be thinking. HTML+CSS? What about page numbers,
tables of contents, citations?</p>
<p>Well, it turns out HTML+CSS can actually manage all of those, with the exception
of the table of contents. You can either built that manually and use CSS to
automatically display the correct page numbers for the relevant sections, or
you you can write some JavaScript to generate the table of contents automatically.
Being a programmer, I took the lazy route: I automated it.</p>
<p>So what new magic gives us page numbers, automatic citations, and more? Well,
<a href="https://www.w3.org/TR/css-gcpm-3/">CSS Generated Content for Paged Media</a>. A
deceptively dull title for a really cool feature.</p>
<p>Here&rsquo;s an example of its power:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css">@<span style="color:#069;font-weight:bold">page</span> {
  <span style="color:#309;font-weight:bold">size</span><span style="color:#555">:</span> <span style="color:#309;font-weight:bold">a4</span><span style="color:#555">;</span>
  <span style="color:#309;font-weight:bold">margin</span><span style="color:#555">:</span> <span style="color:#309;font-weight:bold">3</span>.<span style="color:#0a8;font-weight:bold">5cm</span><span style="color:#555">;</span>

  @<span style="color:#069;font-weight:bold">bottom-right-corner</span> {
    <span style="color:#309;font-weight:bold">content</span><span style="color:#555">:</span> <span style="color:#309;font-weight:bold">counter</span><span style="color:#555">(</span><span style="color:#309;font-weight:bold">page</span><span style="color:#555">);</span>
  }
}
</code></pre></td></tr></table>
</div>
</div><p>That simple bit of CSS just let me select a paper size (you can specify exact
dimensions in metric or imperial if you like too), set a margin, and then
put some arbitrary content in the bottom right corner of every page. In this
case, the page number. Oh, and you can control the formatting of the page
number, set and reset the count at any time, or display the current chapter
title, the possibilites are almost endless.</p>
<p>So let&rsquo;s say you have a front cover, some preamble, and then the main content.
Your front cover doesn&rsquo;t want any page numbers, bur your preamble wants page
numbers in lower case roman numerals, and your main content wants page numbers
starting from 1 in our regular arabic numerals. Easy!</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#309;font-weight:bold">body</span>&gt;
&lt;<span style="color:#309;font-weight:bold">div</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">h1</span>&gt;This is my front page! Isn&#39;t it cool.&lt;/<span style="color:#309;font-weight:bold">h1</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">p</span>&gt;I&#39;d like to thank the academy...&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
&lt;/<span style="color:#309;font-weight:bold">div</span>&gt;

&lt;<span style="color:#309;font-weight:bold">div</span> <span style="color:#309">id</span><span style="color:#555">=</span><span style="color:#c30">preamble</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">h1</span>&gt;Abstract&lt;/<span style="color:#309;font-weight:bold">h1</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">p</span>&gt;In here I put all the content for my preamble.&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
&lt;/<span style="color:#309;font-weight:bold">div</span>&gt;

&lt;<span style="color:#309;font-weight:bold">div</span> <span style="color:#309">id</span><span style="color:#555">=</span><span style="color:#c30">main</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">h1</span>&gt;Introduction&lt;/<span style="color:#309;font-weight:bold">h1</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">p</span>&gt;This is the main content. Here I want normal page numbers.&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
&lt;/<span style="color:#309;font-weight:bold">div</span>&gt;
&lt;/<span style="color:#309;font-weight:bold">body</span>&gt;
</code></pre></td></tr></table>
</div>
</div><div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css">#<span style="color:#0cf;font-weight:bold">main</span> {
  <span style="color:#069;font-weight:bold">page</span>: main; <span style="color:#09f;font-style:italic">/* Set current page */</span>
}

#<span style="color:#0cf;font-weight:bold">preamble</span> {
  <span style="color:#069;font-weight:bold">page</span>: preamble;
}

@<span style="color:#069;font-weight:bold">page</span> <span style="color:#309;font-weight:bold">main</span> { <span style="color:#09f;font-style:italic">/* For &#34;main&#34; pages */</span>
  <span style="color:#309;font-weight:bold">reset-counter</span><span style="color:#555">:</span> <span style="color:#309;font-weight:bold">page</span><span style="color:#555">;</span> <span style="color:#09f;font-style:italic">/* Restart the page count */</span>
  @<span style="color:#069;font-weight:bold">bottom-right-corner</span> {
    <span style="color:#309;font-weight:bold">content</span><span style="color:#555">:</span> <span style="color:#309;font-weight:bold">counter</span><span style="color:#555">(</span><span style="color:#309;font-weight:bold">page</span><span style="color:#555">);</span>
  }
}

@<span style="color:#069;font-weight:bold">page</span> <span style="color:#309;font-weight:bold">preamble</span> {
  @<span style="color:#069;font-weight:bold">bottom-right-corner</span> {
    <span style="color:#309;font-weight:bold">content</span><span style="color:#555">:</span> <span style="color:#309;font-weight:bold">counter</span><span style="color:#555">(</span><span style="color:#309;font-weight:bold">page</span><span style="color:#555">,</span> <span style="color:#309;font-weight:bold">lower-roman</span><span style="color:#555">);</span> <span style="color:#09f;font-style:italic">/* lower-roman format this time */</span>
  }
}
</code></pre></td></tr></table>
</div>
</div><h3 id="page-breaks">Page breaks</h3>
<p>So what do we do when we want a page break? Well, there&rsquo;s a useful set of
css properties for influencing them:</p>
<ul>
<li><code>page-break-before</code></li>
<li><code>page-break-after</code></li>
<li><code>page-break-during</code></li>
</ul>
<p>Which we can set to values such as <code>always</code> or <code>avoid</code>. For example, if we
want all <code>&lt;h1&gt;</code>s to start on a new page:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css"><span style="color:#309;font-weight:bold">h1</span> {
  <span style="color:#069;font-weight:bold">page-break-before</span>: <span style="color:#069;font-weight:bold">always</span>;
}
</code></pre></td></tr></table>
</div>
</div><p>It&rsquo;s really that easy.</p>
<p>If you want to force a new page somewhere arbitrary you can always create a
class for that:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css">.<span style="color:#0a8;font-weight:bold">page-break</span> {
  <span style="color:#069;font-weight:bold">page-break-before</span>: <span style="color:#069;font-weight:bold">always</span>;
}
</code></pre></td></tr></table>
</div>
</div><div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#309;font-weight:bold">p</span>&gt;Something at the end of one page&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
&lt;<span style="color:#309;font-weight:bold">div</span> <span style="color:#309">class</span><span style="color:#555">=</span><span style="color:#c30">&#34;page-break&#34;</span> /&gt;
&lt;<span style="color:#309;font-weight:bold">p</span>&gt;This is on a new page!&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
</code></pre></td></tr></table>
</div>
</div><h3 id="section-numbers">Section numbers</h3>
<p>Want to number your sections? That&rsquo;s easy too. Here&rsquo;s an example of a two-level
numbering scheme.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css"><span style="color:#309;font-weight:bold">h1</span> {
  <span style="color:#069;font-weight:bold">counter-increment</span>: section;
  <span style="color:#069;font-weight:bold">counter-reset</span>: subsection;
}

<span style="color:#309;font-weight:bold">h2</span> {
  <span style="color:#069;font-weight:bold">counter-increment</span>: subsection;
}

<span style="color:#309;font-weight:bold">h1</span>::<span style="color:#99f">before</span> {
  <span style="color:#069;font-weight:bold">content</span>: <span style="color:#366">counter</span>(section) <span style="color:#c30">&#34;. &#34;</span>;
}

<span style="color:#309;font-weight:bold">h2</span>::<span style="color:#99f">before</span> {
  <span style="color:#069;font-weight:bold">content</span>: <span style="color:#366">counter</span>(section) <span style="color:#c30">&#34;.&#34;</span> <span style="color:#366">counter</span>(subsection) <span style="color:#c30">&#34;. &#34;</span>;
}
</code></pre></td></tr></table>
</div>
</div><p>And now our sections are numbered automatically for us.</p>
<h3 id="references">References</h3>
<p>This is starting to get a little tricksy, but not much more so than before.
This will give us nice pretty engineering style references. They even act
as intra-document links on a PDF.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css">#<span style="color:#0cf;font-weight:bold">bibliography</span> {
  <span style="color:#069;font-weight:bold">counter-reset</span>: ref;
}

#<span style="color:#0cf;font-weight:bold">bibliography</span> <span style="color:#309;font-weight:bold">li</span> {
  <span style="color:#069;font-weight:bold">margin</span>: <span style="color:#f60">0.5</span><span style="color:#078;font-weight:bold">em</span>;
  <span style="color:#069;font-weight:bold">counter-increment</span>: ref;
}

#<span style="color:#0cf;font-weight:bold">bibliography</span> <span style="color:#309;font-weight:bold">li</span>::<span style="color:#99f">marker</span> {
  <span style="color:#069;font-weight:bold">content</span>: <span style="color:#c30">&#34;[&#34;</span> <span style="color:#366">counter</span>(ref) <span style="color:#c30">&#34;]&#34;</span>;
}

<span style="color:#309;font-weight:bold">a</span>.<span style="color:#0a8;font-weight:bold">ref</span>::<span style="color:#99f">after</span> {
  <span style="color:#069;font-weight:bold">font-style</span>: <span style="color:#069;font-weight:bold">normal</span>;
  <span style="color:#069;font-weight:bold">content</span>: <span style="color:#c30">&#34;[&#34;</span> <span style="color:#c0f">target-counter</span>(<span style="color:#366">attr</span>(href), ref) <span style="color:#c30">&#34;]&#34;</span>;
  <span style="color:#069;font-weight:bold">font-size</span>: <span style="color:#f60">0.7</span><span style="color:#078;font-weight:bold">em</span>;
}
</code></pre></td></tr></table>
</div>
</div><div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#309;font-weight:bold">div</span> <span style="color:#309">id</span><span style="color:#555">=</span><span style="color:#c30">&#34;main&#34;</span>&gt;

&lt;<span style="color:#309;font-weight:bold">p</span>&gt;
  In some cases, foos were found to be quite dangerous&lt;<span style="color:#309;font-weight:bold">a</span> <span style="color:#309">class</span><span style="color:#555">=</span><span style="color:#c30">ref</span> <span style="color:#309">href</span><span style="color:#555">=</span><span style="color:#c30">&#34;#foo&#34;</span>&gt;&lt;/<span style="color:#309;font-weight:bold">a</span>&gt;.
  However, in &lt;<span style="color:#309;font-weight:bold">a</span> <span style="color:#309">class</span><span style="color:#555">=</span><span style="color:#c30">ref</span> <span style="color:#309">href</span><span style="color:#555">=</span><span style="color:#c30">&#34;#bar&#34;</span>&gt;A Study on Bars&lt;/<span style="color:#309;font-weight:bold">a</span>&gt; this was disputed.
&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;

&lt;/<span style="color:#309;font-weight:bold">div</span>&gt;

&lt;<span style="color:#309;font-weight:bold">div</span> <span style="color:#309">id</span><span style="color:#555">=</span><span style="color:#c30">&#34;bibliography&#34;</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">h1</span>&gt;Bibliography&lt;/<span style="color:#309;font-weight:bold">h1</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">ol</span>&gt;
    &lt;<span style="color:#309;font-weight:bold">li</span> <span style="color:#309">id</span><span style="color:#555">=</span><span style="color:#c30">&#34;foo&#34;</span>&gt;
      Foos considered harmful.
      Author Name Here.
      2010.
    &lt;/<span style="color:#309;font-weight:bold">li</span>&gt;
    &lt;<span style="color:#309;font-weight:bold">li</span> <span style="color:#309">id</span><span style="color:#555">=</span><span style="color:#c30">&#34;bar&#34;</span>&gt;
      A talk on foos considered harmful.
      Someone Else
      2012.
    &lt;/<span style="color:#309;font-weight:bold">li</span>&gt;
  &lt;/<span style="color:#309;font-weight:bold">ol</span>&gt;
&lt;/<span style="color:#309;font-weight:bold">div</span>&gt;
</code></pre></td></tr></table>
</div>
</div><p>And the result is perfect. You can use the same technique to number and refer
to figures easily.</p>
<h3 id="footnotes">Footnotes</h3>
<p>These turn out to be even easier. Try it.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css">.<span style="color:#0a8;font-weight:bold">footnote</span> {
  <span style="color:#069;font-weight:bold">float</span>: footnote;
}
</code></pre></td></tr></table>
</div>
</div><div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#309;font-weight:bold">p</span>&gt;This is a sentence&lt;<span style="color:#309;font-weight:bold">span</span> <span style="color:#309">class</span><span style="color:#555">=</span><span style="color:#c30">footnote</span>&gt;As sentences go though, it&#39;s pretty dull.&lt;/<span style="color:#309;font-weight:bold">span</span>&gt;.&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
</code></pre></td></tr></table>
</div>
</div><h3 id="columns">Columns</h3>
<p>Also easy.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-css" data-lang="css">
#<span style="color:#0cf;font-weight:bold">main</span> {
  <span style="color:#069;font-weight:bold">column-count</span>: <span style="color:#f60">3</span>;

}

#<span style="color:#0cf;font-weight:bold">main</span> <span style="color:#309;font-weight:bold">h1</span> {
  <span style="color:#069;font-weight:bold">column-span</span>: <span style="color:#069;font-weight:bold">all</span>; <span style="color:#09f;font-style:italic">/* let &lt;h1&gt;s break through columns */</span>
}
</code></pre></td></tr></table>
</div>
</div><h3 id="images">Images</h3>
<p>This I saved til last because it&rsquo;s what irritated me about LaTeX the most. I
wanted an image in my document scaled by half and aligned to the right, with
a black border and a caption beneath.</p>
<p>In LaTeX it&rsquo;s a nightmare. In HTML it&rsquo;s second nature.</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#309;font-weight:bold">div</span> <span style="color:#309">style</span><span style="color:#555">=</span><span style="color:#c30">&#34;width: 50%; float: right; border: 1px solid black;&#34;</span>&gt;
  &lt;<span style="color:#309;font-weight:bold">img</span> <span style="color:#309">src</span><span style="color:#555">=</span><span style="color:#c30">&#34;img.png&#34;</span> <span style="color:#309">style</span><span style="color:#555">=</span><span style="color:#c30">&#34;width: 100%;&#34;</span> /&gt;
  &lt;<span style="color:#309;font-weight:bold">p</span>&gt;This image is awesome.&lt;/<span style="color:#309;font-weight:bold">p</span>&gt;
&lt;/<span style="color:#309;font-weight:bold">div</span>&gt;
</code></pre></td></tr></table>
</div>
</div><h2 id="compiling">Compiling</h2>
<p>HTML is all very well, but how do you get your glorious PDF output at the end?
The answer is a wonderful tool called <a href="http://www.princexml.com">PrinceXML</a>.
It really is that good.</p>
<p>For commercial use there&rsquo;s a fee, but for non-commercial use you can download
and use it freely. The only caveat is that the free version adds an annotation
to the first page of the output PDF declaring that it was generated by Prince.
The annotation is easily removed using a standard PDF viewer, so it presents
no trouble to an academic. If you&rsquo;re looking to generate PDFs automatically,
I highly recommend you splash out on a license.</p>
<p>And yes, you can invoke it using GNU Make:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-makefile" data-lang="makefile"><span style="color:#c0f">report.pdf</span><span style="color:#555">:</span> report.html style.css
	prince -v -o <span style="color:#033">$@</span> $&lt;
</code></pre></td></tr></table>
</div>
</div>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Websockets with Redux]]></title>
    <link href="https://harry.pm/blog/websockets_with_redux/" />
    <published>2016-03-20T12:03:00+00:00</published>
    <updated>2016-03-20T12:03:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/websockets_with_redux/</id>
    <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Lately, I&rsquo;ve been devoting a fair bit of my time to working on a single page
web application, for which I&rsquo;ve been using the excellent <a href="https://facebook.github.io/react/">React.js</a>
and <a href="http://redux.js.org">Redux</a> frameworks for managing my UI, and the client
side state. An honourable mention goes to <a href="http://material-ui.com">Material UI</a>
for the nice React components I built the interface with.</p>
<p>For various reasons, the server component of this application had to be built in
C++, and it was required that the server could push events or data to the client.
While at first I toyed with the idea of a RESTful HTTP API with either long-polling
or websockets for events, I quickly abandoned this approach in favour of a pure
websocket API.</p>
<p>Combined with the power of React+Redux, using websockets for the application led
to a very smooth, and pain free development experience. The purpose of this post
is to share the approach I took to handling the websocket connection with Redux,
and my experiences developing with this architecture.</p>
<p>This post assumes some rudimentary knowledge of Facebook&rsquo;s Flux architecture,
and how Redux implements that, specifically the unidirectional data flow.</p>
<h2 id="websocket-middleware">Websocket Middleware</h2>
<p>In a Redux based application, the typical path of user interaction is as follows:</p>
<ol>
<li>User presses button</li>
<li>Action is created</li>
<li>Action is delivered to the reducver</li>
<li>The reducer updates the store&rsquo;s state</li>
<li>The UI is updated with the new state</li>
</ol>
<p>For user interactions that have to communicate with the server, a detour is
clearly needed in step 3. Fortunately, Redux provides a way to hook into actions
at that step, namely <a href="http://redux.js.org/docs/advanced/Middleware.html">middleware</a>.</p>
<p>I created a custom middleware responsible for opening a websocket to the server,
maintining it, and intercepting or dispatching actions as appropriate. That is,
any actions that needed to be dealt with by the server were intercepted at
step 3, and the appropriate message sent to the server. When a message is
received from the server, an equivalent action would be dispatched to the reducer
to update the state, as per the new information received from the server.</p>
<p>The new path of user interaction is as follows:</p>
<ol>
<li>User presses button</li>
<li>Action is created</li>
<li>Action is delivered to socket middleware. If needed, the middleware re-routes
the action through the websocket, and does not deliver it to the reducer.
Otherwise, action is given to reducer as usual.</li>
<li>The reducer updates the store&rsquo;s state</li>
<li>The UI is updated with the new state</li>
</ol>
<p>With additional path for when a message is received from the server:</p>
<ol>
<li>The socket middleware receives a message from the websocket</li>
<li>The socket middleware creates an action, and dispatches it to the reducer</li>
<li>The reducer updates the store&rsquo;s state</li>
<li>The UI is updated with the new state</li>
</ol>
<p>This design is clean, and easy to reason about. For both the user and redux, the
detour and interception of remote actions is invisible. Additionally, since all
redux actions are serializable, you can record and replay actions that are
delivered to the reducer, or to the middleware, providing excellent debugging
opportunities.</p>
<p>To help demonstrate this solution, I&rsquo;ve adapted my middleware to provide an
example websocket middleware anyone can base theirs off:</p>
<h3 id="socketmiddlewarejs">socketMiddleware.js</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">65
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">66
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">67
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">68
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">69
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">70
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">71
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">72
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">73
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">74
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">75
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">76
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">77
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript">
<span style="color:#069;font-weight:bold">import</span> actions from <span style="color:#c30">&#39;./actions&#39;</span>

<span style="color:#069;font-weight:bold">const</span> socketMiddleware <span style="color:#555">=</span> (<span style="color:#069;font-weight:bold">function</span>(){ 
  <span style="color:#069;font-weight:bold">var</span> socket <span style="color:#555">=</span> <span style="color:#069;font-weight:bold">null</span>;

  <span style="color:#069;font-weight:bold">const</span> onOpen <span style="color:#555">=</span> (ws,store,token) =&gt; evt =&gt; {
    <span style="color:#09f;font-style:italic">//Send a handshake, or authenticate with remote end
</span><span style="color:#09f;font-style:italic"></span>
    <span style="color:#09f;font-style:italic">//Tell the store we&#39;re connected
</span><span style="color:#09f;font-style:italic"></span>    store.dispatch(actions.connected());
  }

  <span style="color:#069;font-weight:bold">const</span> onClose <span style="color:#555">=</span> (ws,store) =&gt; evt =&gt; {
    <span style="color:#09f;font-style:italic">//Tell the store we&#39;ve disconnected
</span><span style="color:#09f;font-style:italic"></span>    store.dispatch(actions.disconnected());
  }

  <span style="color:#069;font-weight:bold">const</span> onMessage <span style="color:#555">=</span> (ws,store) =&gt; evt =&gt; {
    <span style="color:#09f;font-style:italic">//Parse the JSON message received on the websocket
</span><span style="color:#09f;font-style:italic"></span>    <span style="color:#069;font-weight:bold">var</span> msg <span style="color:#555">=</span> JSON.parse(evt.data);
    <span style="color:#069;font-weight:bold">switch</span>(msg.type) {
      <span style="color:#069;font-weight:bold">case</span> <span style="color:#c30">&#34;CHAT_MESSAGE&#34;</span><span style="color:#555">:</span>
        <span style="color:#09f;font-style:italic">//Dispatch an action that adds the received message to our state
</span><span style="color:#09f;font-style:italic"></span>        store.dispatch(actions.messageReceived(msg));
        <span style="color:#069;font-weight:bold">break</span>;
      <span style="color:#069;font-weight:bold">default</span><span style="color:#555">:</span>
        console.log(<span style="color:#c30">&#34;Received unknown message type: &#39;&#34;</span> <span style="color:#555">+</span> msg.type <span style="color:#555">+</span> <span style="color:#c30">&#34;&#39;&#34;</span>);
        <span style="color:#069;font-weight:bold">break</span>;
    }
  }

  <span style="color:#069;font-weight:bold">return</span> store =&gt; next =&gt; action =&gt; {
    <span style="color:#069;font-weight:bold">switch</span>(action.type) {

      <span style="color:#09f;font-style:italic">//The user wants us to connect
</span><span style="color:#09f;font-style:italic"></span>      <span style="color:#069;font-weight:bold">case</span> <span style="color:#c30">&#39;CONNECT&#39;</span><span style="color:#555">:</span>
        <span style="color:#09f;font-style:italic">//Start a new connection to the server
</span><span style="color:#09f;font-style:italic"></span>        <span style="color:#069;font-weight:bold">if</span>(socket <span style="color:#555">!=</span> <span style="color:#069;font-weight:bold">null</span>) {
          socket.close();
        }
        <span style="color:#09f;font-style:italic">//Send an action that shows a &#34;connecting...&#34; status for now
</span><span style="color:#09f;font-style:italic"></span>        store.dispatch(actions.connecting());

        <span style="color:#09f;font-style:italic">//Attempt to connect (we could send a &#39;failed&#39; action on error)
</span><span style="color:#09f;font-style:italic"></span>        socket <span style="color:#555">=</span> <span style="color:#069;font-weight:bold">new</span> WebSocket(action.url);
        socket.onmessage <span style="color:#555">=</span> onMessage(socket,store);
        socket.onclose <span style="color:#555">=</span> onClose(socket,store);
        socket.onopen <span style="color:#555">=</span> onOpen(socket,store,action.token);

        <span style="color:#069;font-weight:bold">break</span>;

      <span style="color:#09f;font-style:italic">//The user wants us to disconnect
</span><span style="color:#09f;font-style:italic"></span>      <span style="color:#069;font-weight:bold">case</span> <span style="color:#c30">&#39;DISCONNECT&#39;</span><span style="color:#555">:</span>
        <span style="color:#069;font-weight:bold">if</span>(socket <span style="color:#555">!=</span> <span style="color:#069;font-weight:bold">null</span>) {
          socket.close();
        }
        socket <span style="color:#555">=</span> <span style="color:#069;font-weight:bold">null</span>;

        <span style="color:#09f;font-style:italic">//Set our state to disconnected
</span><span style="color:#09f;font-style:italic"></span>        store.dispatch(actions.disconnected());
        <span style="color:#069;font-weight:bold">break</span>;

      <span style="color:#09f;font-style:italic">//Send the &#39;SEND_MESSAGE&#39; action down the websocket to the server
</span><span style="color:#09f;font-style:italic"></span>      <span style="color:#069;font-weight:bold">case</span> <span style="color:#c30">&#39;SEND_CHAT_MESSAGE&#39;</span><span style="color:#555">:</span>
        socket.send(JSON.stringify(action));
        <span style="color:#069;font-weight:bold">break</span>;

      <span style="color:#09f;font-style:italic">//This action is irrelevant to us, pass it on to the next middleware
</span><span style="color:#09f;font-style:italic"></span>      <span style="color:#069;font-weight:bold">default</span><span style="color:#555">:</span>
        <span style="color:#069;font-weight:bold">return</span> next(action);
    }
  }

})();

<span style="color:#069;font-weight:bold">export</span> <span style="color:#069;font-weight:bold">default</span> socketMiddleware
</code></pre></td></tr></table>
</div>
</div><p>Making use of the middleware is also a breeze. More information on this can of
course be found in the documentation for <a href="http://redux.js.org/docs/advanced/Middleware.html">redux middleware</a>.</p>
<h3 id="storejs">store.js</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#069;font-weight:bold">import</span> { createStore, applyMiddleware } from <span style="color:#c30">&#39;redux&#39;</span>
<span style="color:#069;font-weight:bold">import</span> thunk from <span style="color:#c30">&#39;redux-thunk&#39;</span>
<span style="color:#069;font-weight:bold">import</span> reducer from <span style="color:#c30">&#39;./reducer&#39;</span>
<span style="color:#069;font-weight:bold">import</span> socketMiddleware from <span style="color:#c30">&#39;./socketMiddleware&#39;</span>

<span style="color:#069;font-weight:bold">export</span> <span style="color:#069;font-weight:bold">default</span> <span style="color:#069;font-weight:bold">function</span> configureStore(initialState) {
  <span style="color:#069;font-weight:bold">return</span> createStore(reducer, initialState,
      applyMiddleware(thunk, socketMiddleware)
  )
}
</code></pre></td></tr></table>
</div>
</div><p>This fairly straightforward middleware handles our entire websocket with ease.
It produces and consumes actions as needed, and allows us to effortlessly
update the local state based on information received from the server, and to
inform the server of any user actions, all without relying on messy callbacks
or violating the unidirectional data flow.</p>
<p>I have found this approach to be very powerful, and would highly recommend it
to anyone considering building a web application with websockets.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to run a mail server]]></title>
    <link href="https://harry.pm/blog/how_to_run_a_mail_server/" />
    <published>2015-11-25T12:00:00+00:00</published>
    <updated>2015-11-25T12:00:00+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/how_to_run_a_mail_server/</id>
    <content type="html"><![CDATA[<p><strong>2021 Update: I no longer host my own mail server.
If you still want to do it yourself, I found
<a href="https://mailu.io/">Mailu</a>
to be the most practical solution for having things &ldquo;just work&rdquo;.</strong></p>
<h2 id="the-why">The Why</h2>
<p>As a result of the recent public discussion regarding online privacy I decided
to take a few measures to give myself some more privacy online. One such
measure was the creation of a new <a href="https://pgp.mit.edu/pks/lookup?op=vindex&amp;search=0x7BE4075E24AB8942">4096 bit PGP public key</a>
for myself. I also started running my DNS requests through tor for some more
privacy, which was inspired by Drew&rsquo;s excellent <a href="https://drewdevault.com/2015/11/11/Bring-more-tor-into-your-life.html">blog post</a>.</p>
<p>Lastly, I decided it was time to stop letting Google handle all the mail for my
domain. This was partly because it&rsquo;s been costing me roughly the price of a
<a href="http://www.telegraph.co.uk/finance/newsbysector/retailandconsumer/11541536/Is-London-the-most-expensive-city-in-which-to-buy-a-pint.html">pint of beer in London</a>
each month, and partly because it seemed like it would be a <del>fun</del> learning
experience.</p>
<p>As a note to self, and to spare you the <del>fun</del> part of the learning experience
I thought I&rsquo;d share the details of my set up to show how straightforward it can
be to get a solid mail server online.</p>
<h2 id="overview">Overview</h2>
<p>For my mail server there are three key pieces of software at play:</p>
<ul>
<li><a href="http://www.postfix.org">postfix</a> - Provides an SMTP server</li>
<li><a href="http://www.dovecot.org">dovecot</a> - Handles mailboxes, authentication, and IMAP</li>
<li><a href="https://mariadb.org/">MariaDB</a> - SQL database of email accounts</li>
</ul>
<p>Inbound mail is given to postfix via SMTP. Postfix then checks against the SQL
database whether the email address should be accepted, and performs spam
filtering. If the email passes postfix&rsquo;s checks it&rsquo;s passed to dovecot over a
unix socket via LMTP. Dovecot is then responsible for placing the mail in the
correct user&rsquo;s mail directory.</p>
<p>Email are accessed over IMAP using dovecot. Upon connection, users are
authenticated by dovecot against accounts in the SQL database, and on success
are connected to their mail directory.</p>
<p>Outbound mail is also given to postfix, however this time postfix requires
authentication. Postfix sends the login details to dovecot over a unix pipe,
which checks against the SQL database whether the user is permitted to send
mail. If so, postfix is given the approval to do so, and relays the email to
the relevant remote SMTP server.</p>
<h2 id="configuring-mariadb">Configuring MariaDB</h2>
<p>Create a new database. I called mine <code>maildb</code>. Also create a new MariaDB user,
<code>mail</code> with read-only access to <code>maildb</code>.</p>
<p>Within <code>maildb</code> you want to create the following three tables:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#069;font-weight:bold">CREATE</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">TABLE</span><span style="color:#bbb"> </span><span style="color:#555">`</span>aliases<span style="color:#555">`</span><span style="color:#bbb"> </span>(<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#555">`</span>mail<span style="color:#555">`</span><span style="color:#bbb"> </span><span style="color:#366">varchar</span>(<span style="color:#f60">120</span>)<span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NOT</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NULL</span>,<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#555">`</span>destination<span style="color:#555">`</span><span style="color:#bbb"> </span><span style="color:#366">varchar</span>(<span style="color:#f60">120</span>)<span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NOT</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NULL</span>,<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#069;font-weight:bold">UNIQUE</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">KEY</span><span style="color:#bbb"> </span><span style="color:#555">`</span>mail<span style="color:#555">`</span><span style="color:#bbb"> </span>(<span style="color:#555">`</span>mail<span style="color:#555">`</span>)<span style="color:#bbb">
</span><span style="color:#bbb"></span>);<span style="color:#bbb">
</span><span style="color:#bbb">
</span><span style="color:#bbb"></span><span style="color:#069;font-weight:bold">CREATE</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">TABLE</span><span style="color:#bbb"> </span><span style="color:#555">`</span>domains<span style="color:#555">`</span><span style="color:#bbb"> </span>(<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#555">`</span><span style="color:#069;font-weight:bold">domain</span><span style="color:#555">`</span><span style="color:#bbb"> </span><span style="color:#366">varchar</span>(<span style="color:#f60">120</span>)<span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NOT</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NULL</span><span style="color:#bbb">
</span><span style="color:#bbb"></span>);<span style="color:#bbb">
</span><span style="color:#bbb">
</span><span style="color:#bbb"></span><span style="color:#069;font-weight:bold">CREATE</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">TABLE</span><span style="color:#bbb"> </span><span style="color:#555">`</span>users<span style="color:#555">`</span><span style="color:#bbb"> </span>(<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#555">`</span>email<span style="color:#555">`</span><span style="color:#bbb"> </span><span style="color:#366">varchar</span>(<span style="color:#f60">128</span>)<span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NOT</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NULL</span>,<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#555">`</span>crypt<span style="color:#555">`</span><span style="color:#bbb"> </span><span style="color:#366">varchar</span>(<span style="color:#f60">128</span>)<span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NOT</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">NULL</span>,<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#069;font-weight:bold">PRIMARY</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">KEY</span><span style="color:#bbb"> </span>(<span style="color:#555">`</span>email<span style="color:#555">`</span>),<span style="color:#bbb">
</span><span style="color:#bbb">  </span><span style="color:#069;font-weight:bold">UNIQUE</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">KEY</span><span style="color:#bbb"> </span><span style="color:#555">`</span>id<span style="color:#555">`</span><span style="color:#bbb"> </span>(<span style="color:#555">`</span>email<span style="color:#555">`</span>)<span style="color:#bbb">
</span><span style="color:#bbb"></span>);<span style="color:#bbb">
</span></code></pre></td></tr></table>
</div>
</div><h3 id="aliases-table">Aliases Table</h3>
<p>The purpose of <code>aliases</code> is for an email address mapping step performed by
postfix. Every email that is received locally has its address transformed using
this lookup table.</p>
<p>To receive email at an address it is <strong>required</strong> to be covered by this table.
I have <code>harry@exec64.co.uk</code> mapped to <code>harry@exec64.co.uk</code>, which passes my
mail through without changing the destination.</p>
<p>However, if you&rsquo;re the administrator of the server, you&rsquo;ll want to receive mail
for users such as <code>postmaster@example.com</code>, so you&rsquo;d need to map that to
<code>your_address@example.com</code>.</p>
<p>You can also provide a catch-all address for a domain by excluding the name
portion of the email address. In my case that would be mapping <code>@exec64.co.uk</code>
to <code>harry@exec64.co.uk.</code></p>
<h3 id="domains-table">Domains Table</h3>
<p>This table is even simpler to configure. It should simply contains all the
domains for which your server should receive mail for. It&rsquo;s used by postfix to
determine whether to send mail to another server, or to pass it to dovecot.</p>
<p>In my case it simply contains <code>exec64.co.uk</code>.</p>
<h3 id="users-table">Users Table</h3>
<p>This is the most important table, which is used solely by dovecot to authenticate
users. The <code>email</code> column should contain the users full email address, and the
<code>crypt</code> column should contain an encrypted form of their password.</p>
<p>Here&rsquo;s an example query to insert a new user:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#069;font-weight:bold">INSERT</span><span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">INTO</span><span style="color:#bbb"> </span>users<span style="color:#bbb"> </span>(email,crypt)<span style="color:#bbb"> </span><span style="color:#069;font-weight:bold">VALUES</span><span style="color:#bbb"> </span>(<span style="color:#c30">&#39;user@example.com&#39;</span>,encrypt(<span style="color:#c30">&#39;plaintext_password&#39;</span>,<span style="color:#bbb"> </span>CONCAT(<span style="color:#c30">&#39;$5$&#39;</span>,<span style="color:#bbb"> </span>MD5(RAND())))<span style="color:#bbb"> </span>);<span style="color:#bbb">
</span></code></pre></td></tr></table>
</div>
</div><h2 id="configuring-dovecot">Configuring Dovecot</h2>
<p>Now that the SQL database has been set up correctly, the next step is to set up
Dovecot to authenticate users, manage their email directories, and provide an
IMAP server for users to retrieve their mail from.</p>
<p>The recommended way to configure dovecot seems to be to have a main configuration
file at <code>/etc/dovecot/dovecot.conf</code> which includes many other configuration files
from <code>/etc/dovecot/conf.d/</code> but I found that to be an overcomplication for my
needs. Simply having one relatively short config file was perfectly adequate.</p>
<h3 id="create-the-virtual-user">Create the virtual user</h3>
<p>Traditionally email addresses were tied to unix users on servers, and the mail
was stored in each user&rsquo;s home directory. In our case, we want our email
addresses to be independent of the users on the system, so instead all the mail
will be &ldquo;owned&rdquo; by a virtual user named <code>virtual</code>. (Forgive me, I don&rsquo;t study
creative writing.)</p>
<p>To create the user and the mail directory run the following commands:</p>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">sudo mkdir /var/spool/mail/virtual
sudo groupadd --system virtual -g <span style="color:#f60">5000</span>
sudo useradd --system virtual -u <span style="color:#f60">5000</span> -g <span style="color:#f60">5000</span>
sudo chown -R virtual:virtual /var/spool/mail/virtual
</code></pre></td></tr></table>
</div>
</div><p>Now we&rsquo;re ready to configure dovecot itself. It&rsquo;s all fairly straight forward.
Here&rsquo;s a copy of my configuration file. Everything ought to be fairly self
explanatory, and if it isn&rsquo;t, dovecot has some pretty good
<a href="http://wiki2.dovecot.org/">documentation</a>.</p>
<h3 id="etcdovecotdovecotconf">/etc/dovecot/dovecot.conf</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">65
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">66
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">67
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">68
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">69
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">70
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">71
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">72
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#09f;font-style:italic">#provide acesss to imap and ltmp</span>
<span style="color:#309">protocols</span> <span style="color:#555">=</span> <span style="color:#c30">imap lmtp</span>

<span style="color:#09f;font-style:italic">#don&#39;t handle mail without SSL silly</span>
<span style="color:#09f;font-style:italic">#if you don&#39;t have a cert go to LetsEncrypt.org</span>
<span style="color:#309">ssl</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">ssl_cert</span> <span style="color:#555">=</span> <span style="color:#c30">&lt;/path/to/fullchain.pem</span>
<span style="color:#309">ssl_key</span> <span style="color:#555">=</span> <span style="color:#c30">&lt;/path/to/privkey.pem</span>

<span style="color:#309">listen</span> <span style="color:#555">=</span> <span style="color:#c30">*, ::</span>

<span style="color:#309">base_dir</span> <span style="color:#555">=</span> <span style="color:#c30">/var/run/dovecot/</span>

<span style="color:#309">instance_name</span> <span style="color:#555">=</span> <span style="color:#c30">dovecot</span>

<span style="color:#309">login_greeting</span> <span style="color:#555">=</span> <span style="color:#c30">Dovecot ready.</span>

<span style="color:#309">login_trusted_networks</span> <span style="color:#555">=</span> <span style="color:#c30">127.0.0.1</span>

<span style="color:#309">disable_plaintext_auth</span> <span style="color:#555">=</span> <span style="color:#c30">no</span>

<span style="color:#309">auth_mechanisms</span> <span style="color:#555">=</span> <span style="color:#c30">plain login</span>

<span style="color:#09f;font-style:italic">#Mail is stored in &#34;Maildir&#34; in each user&#39;s home directory</span>
<span style="color:#309">mail_location</span> <span style="color:#555">=</span> <span style="color:#c30">maildir:~/Maildir</span>

<span style="color:#09f;font-style:italic"># authenticate users using SQL</span>
<span style="color:#309">passdb {</span>
  <span style="color:#309">driver</span> <span style="color:#555">=</span> <span style="color:#c30">sql
</span><span style="color:#c30">  #this config file is provided beneath
</span><span style="color:#c30">  args = /etc/dovecot/dovecot-sql.conf.ext</span>
<span style="color:#309">}</span>

<span style="color:#309">userdb {</span>
  <span style="color:#309">driver</span> <span style="color:#555">=</span> <span style="color:#c30">static
</span><span style="color:#c30">  #store each user&#39;s mail in /var/spool/mail/virtual/name/domain
</span><span style="color:#c30">  #i.e. virtual/harry/exec64.co.uk
</span><span style="color:#c30">  args = uid=virtual gid=virtual home=/var/spool/mail/virtual/%d/%n</span>
<span style="color:#309">}</span>

<span style="color:#309">namespace inbox {</span>
  <span style="color:#309">inbox</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">}</span>

<span style="color:#09f;font-style:italic">#the mail is owned by the user/group named &#34;virtual&#34;</span>
<span style="color:#309">mail_uid</span> <span style="color:#555">=</span> <span style="color:#c30">virtual</span>
<span style="color:#309">mail_gid</span> <span style="color:#555">=</span> <span style="color:#c30">virtual</span>

<span style="color:#309">auth_mechanisms</span> <span style="color:#555">=</span> <span style="color:#c30">plain login</span>

<span style="color:#09f;font-style:italic">#provide an authentication service to postfix</span>
<span style="color:#309">service auth {</span>
  <span style="color:#309">unix_listener /var/spool/postfix/private/auth {</span>
    <span style="color:#309">mode</span> <span style="color:#555">=</span> <span style="color:#c30">0666
</span><span style="color:#c30">    user = postfix
</span><span style="color:#c30">    group = postfix
</span><span style="color:#c30">  }</span>
<span style="color:#309">}</span>

<span style="color:#309">protocol lmtp {</span>
  <span style="color:#09f;font-style:italic">#this option is required, or you won&#39;t be able to receive mail</span>
  <span style="color:#309">postmaster_address</span> <span style="color:#555">=</span> <span style="color:#c30">postmaster@exec64.co.uk</span>
<span style="color:#309">}</span>

<span style="color:#09f;font-style:italic">#accept delivery from postfix via lmtp</span>
<span style="color:#309">service lmtp {</span>
  <span style="color:#309">unix_listener /var/spool/postfix/private/dovecot-lmtp {</span>
    <span style="color:#309">mode</span> <span style="color:#555">=</span> <span style="color:#c30">0600
</span><span style="color:#c30">    user = postfix
</span><span style="color:#c30">    group = postfix
</span><span style="color:#c30">  }</span>
<span style="color:#309">}</span>
</code></pre></td></tr></table>
</div>
</div><h3 id="etcdovecotdovecot-sqlconfext">/etc/dovecot/dovecot-sql.conf.ext</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#309">driver</span> <span style="color:#555">=</span> <span style="color:#c30">mysql</span>
<span style="color:#309">connect</span> <span style="color:#555">=</span> <span style="color:#c30">host=localhost dbname=maildb user=mail password=mailpasswordhere</span>
<span style="color:#309">default_pass_scheme</span> <span style="color:#555">=</span> <span style="color:#c30">SHA256-CRYPT #make sure this matches the encryption scheme you use</span>

<span style="color:#309">password_query</span> <span style="color:#555">=</span> <span style="color:#c30">SELECT email as user, crypt as password FROM users WHERE email = &#39;%u&#39;;</span>
</code></pre></td></tr></table>
</div>
</div><h3 id="testing-dovecot">Testing dovecot</h3>
<p>At this point, you should now have a working IMAP server that you can connect to
and retrieve mail from. Of course you won&rsquo;t have any mail to read, but you should
still verify that you can now connect, and also check that the relevant mail
directory was created in <code>/var/spool/mail/virtual</code> for your mail.</p>
<h2 id="configuring-postfix">Configuring Postfix</h2>
<p>And now for the final step, providing an SMTP server to send/receive mail with.</p>
<p>In my case, I only needed to set up one main configuration file for postfix,
and a couple of other files to allow it to query the SQL database.</p>
<p>Please note that this configuration doesn&rsquo;t provide any spam filtering.</p>
<p>Again, if something doesn&rsquo;t make sense to you, <a href="http://www.postfix.org/BASIC_CONFIGURATION_README.html">RTFM</a>.</p>
<h3 id="etcpostfixmaincf">/etc/postfix/main.cf</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">65
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">66
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">67
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">68
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">69
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">70
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">71
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">72
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">73
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">74
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">75
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">76
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">77
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">78
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">79
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">80
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">81
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">82
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#09f;font-style:italic">#We don&#39;t need to set the domain here, it&#39;s configured by the virtual mailboxes</span>
<span style="color:#309">mydomain</span> <span style="color:#555">=</span> <span style="color:#c30">localhost</span>
<span style="color:#309">myhostname</span> <span style="color:#555">=</span> <span style="color:#c30">$mydomain</span>
<span style="color:#309">myorigin</span> <span style="color:#555">=</span> <span style="color:#c30">$mydomain</span>
<span style="color:#309">mydestination</span> <span style="color:#555">=</span> <span style="color:#c30">localhost</span>
<span style="color:#309">mynetworks_style</span> <span style="color:#555">=</span> <span style="color:#c30">host</span>
<span style="color:#309">relay_domains</span> <span style="color:#555">=</span> <span style="color:#c30">$mydestination</span>
<span style="color:#309">relayhost</span> <span style="color:#555">=</span>
<span style="color:#309">smtpd_banner</span> <span style="color:#555">=</span> <span style="color:#c30">$myhostname ESMTP</span>

<span style="color:#09f;font-style:italic">#virtual mailbox settings</span>
<span style="color:#309">virtual_mailbox_base</span> <span style="color:#555">=</span> <span style="color:#c30">/var/spool/mail/virtual</span>
<span style="color:#309">virtual_mailbox_maps</span> <span style="color:#555">=</span> <span style="color:#c30">mysql:/etc/postfix/sql_mailbox.cf</span>
<span style="color:#309">virtual_alias_maps</span> <span style="color:#555">=</span> <span style="color:#c30">mysql:/etc/postfix/sql_alias.cf</span>
<span style="color:#309">virtual_mailbox_domains</span> <span style="color:#555">=</span> <span style="color:#c30">mysql:/etc/postfix/sql_domains.cf</span>
<span style="color:#09f;font-style:italic">#uid of virtual user is 5000</span>
<span style="color:#309">virtual_uid_maps</span> <span style="color:#555">=</span> <span style="color:#c30">static:5000</span>
<span style="color:#309">virtual_gid_maps</span> <span style="color:#555">=</span> <span style="color:#c30">static:5000</span>
<span style="color:#09f;font-style:italic">#tell postfix to send mail for virtual inboxes to dovecot</span>
<span style="color:#309">virtual_transport</span> <span style="color:#555">=</span> <span style="color:#c30">lmtp:unix:private/dovecot-lmtp</span>

<span style="color:#09f;font-style:italic">#aliases</span>
<span style="color:#309">alias_maps</span> <span style="color:#555">=</span> <span style="color:#c30">hash:/etc/postfix/aliases</span>
<span style="color:#309">alias_database</span> <span style="color:#555">=</span> <span style="color:#c30">hash:/etc/postfix/aliases</span>

<span style="color:#09f;font-style:italic">#tls parameters</span>
<span style="color:#309">smtpd_tls_cert_file</span><span style="color:#555">=</span><span style="color:#c30">/path/to/fullchain.pem</span>
<span style="color:#309">smtpd_tls_key_file</span><span style="color:#555">=</span><span style="color:#c30">/path/to/privkey.pem</span>
<span style="color:#309">smtpd_use_tls</span><span style="color:#555">=</span><span style="color:#c30">yes</span>
<span style="color:#309">smtpd_tls_session_cache_database</span> <span style="color:#555">=</span> <span style="color:#c30">btree:${data_directory}/smtpd_scache</span>
<span style="color:#309">smtp_tls_session_cache_database</span> <span style="color:#555">=</span> <span style="color:#c30">btree:${data_directory}/smtp_scache</span>
<span style="color:#309">smtp_tls_security_level</span> <span style="color:#555">=</span> <span style="color:#c30">may</span>
<span style="color:#309">smtpd_tls_security_level</span> <span style="color:#555">=</span> <span style="color:#c30">may</span>
<span style="color:#309">smtp_tls_note_starttls_offer</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">smtpd_tls_loglevel</span> <span style="color:#555">=</span> <span style="color:#c30">2</span>
<span style="color:#309">smtpd_tls_received_header</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">smtpd_tls_session_cache_timeout</span> <span style="color:#555">=</span> <span style="color:#c30">3600s</span>
<span style="color:#309">tls_random_source</span> <span style="color:#555">=</span> <span style="color:#c30">dev:/dev/urandom</span>

<span style="color:#09f;font-style:italic">#authentication settings</span>
<span style="color:#309">smtpd_sasl_auth_enable</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">smtpd_sasl_type</span> <span style="color:#555">=</span> <span style="color:#c30">dovecot</span>
<span style="color:#309">smtpd_sasl_path</span> <span style="color:#555">=</span> <span style="color:#c30">private/auth</span>
<span style="color:#309">smtpd_recipient_restrictions</span> <span style="color:#555">=</span> <span style="color:#c30">permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination</span>
<span style="color:#309">smtpd_relay_restrictions</span> <span style="color:#555">=</span> <span style="color:#c30">permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination</span>
<span style="color:#309">smtpd_recipient_limit</span> <span style="color:#555">=</span> <span style="color:#c30">16</span>
<span style="color:#309">smtpd_soft_error_limit</span> <span style="color:#555">=</span> <span style="color:#c30">3</span>
<span style="color:#309">smtpd_hard_error_limit</span> <span style="color:#555">=</span> <span style="color:#c30">12</span>
<span style="color:#309">smtpd_helo_restrictions</span> <span style="color:#555">=</span> <span style="color:#c30">permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit</span>
<span style="color:#309">smtpd_sender_restrictions</span> <span style="color:#555">=</span> <span style="color:#c30">permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit</span>
<span style="color:#309">smtpd_client_restrictions</span> <span style="color:#555">=</span> <span style="color:#c30">reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl</span>
<span style="color:#309">smtpd_data_restrictions</span> <span style="color:#555">=</span> <span style="color:#c30">reject_unauth_pipelining</span>
<span style="color:#309">smtpd_helo_required</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">smtpd_delay_reject</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>
<span style="color:#309">disable_vrfy_command</span> <span style="color:#555">=</span> <span style="color:#c30">yes</span>

<span style="color:#09f;font-style:italic">#other</span>
<span style="color:#309">compatibility_level</span> <span style="color:#555">=</span> <span style="color:#c30">2</span>
<span style="color:#309">queue_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/var/spool/postfix</span>
<span style="color:#309">command_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/bin</span>
<span style="color:#309">daemon_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/lib/postfix/bin</span>
<span style="color:#309">data_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/var/lib/postfix</span>
<span style="color:#309">mail_owner</span> <span style="color:#555">=</span> <span style="color:#c30">postfix</span>
<span style="color:#309">inet_interfaces</span> <span style="color:#555">=</span> <span style="color:#c30">all</span>
<span style="color:#309">local_recipient_maps</span> <span style="color:#555">=</span>
<span style="color:#309">sendmail_path</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/bin/sendmail</span>
<span style="color:#309">newaliases_path</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/bin/newaliases</span>
<span style="color:#309">mailq_path</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/bin/mailq</span>
<span style="color:#309">setgid_group</span> <span style="color:#555">=</span> <span style="color:#c30">postdrop</span>
<span style="color:#309">html_directory</span> <span style="color:#555">=</span> <span style="color:#c30">no</span>
<span style="color:#309">manpage_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/share/man</span>
<span style="color:#309">sample_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/etc/postfix</span>
<span style="color:#309">readme_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/share/doc/postfix</span>
<span style="color:#309">inet_protocols</span> <span style="color:#555">=</span> <span style="color:#c30">ipv4</span>
<span style="color:#309">meta_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/etc/postfix</span>
<span style="color:#309">shlib_directory</span> <span style="color:#555">=</span> <span style="color:#c30">/usr/lib/postfix</span>
<span style="color:#309">delay_warning_time</span> <span style="color:#555">=</span> <span style="color:#c30">1h</span>
<span style="color:#309">unknown_local_recipient_reject_code</span> <span style="color:#555">=</span> <span style="color:#c30">450</span>
<span style="color:#309">maximal_queue_lifetime</span> <span style="color:#555">=</span> <span style="color:#c30">7d</span>
<span style="color:#309">minimal_backoff_time</span> <span style="color:#555">=</span> <span style="color:#c30">1000s</span>
<span style="color:#309">maximal_backoff_time</span> <span style="color:#555">=</span> <span style="color:#c30">8000s</span>
<span style="color:#309">smtp_helo_timeout</span> <span style="color:#555">=</span> <span style="color:#c30">60s</span>
</code></pre></td></tr></table>
</div>
</div><p>We also need to tell postfix how to query the information it needs from the
SQL database.</p>
<h3 id="etcpostfixsql_aliascf">/etc/postfix/sql_alias.cf</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#309">user</span><span style="color:#555">=</span><span style="color:#c30">mail</span>
<span style="color:#309">password</span><span style="color:#555">=</span><span style="color:#c30">password</span>
<span style="color:#309">hosts</span><span style="color:#555">=</span><span style="color:#c30">127.0.0.1</span>
<span style="color:#309">dbname</span><span style="color:#555">=</span><span style="color:#c30">maildb</span>
<span style="color:#309">query</span> <span style="color:#555">=</span> <span style="color:#c30">select destination from aliases where mail = &#39;%s&#39;</span>
</code></pre></td></tr></table>
</div>
</div><h3 id="etcpostfixsql_mailboxcf">/etc/postfix/sql_mailbox.cf</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#309">user</span><span style="color:#555">=</span><span style="color:#c30">mail</span>
<span style="color:#309">password</span><span style="color:#555">=</span><span style="color:#c30">password</span>
<span style="color:#309">hosts</span><span style="color:#555">=</span><span style="color:#c30">127.0.0.1</span>
<span style="color:#309">dbname</span><span style="color:#555">=</span><span style="color:#c30">maildb</span>
<span style="color:#309">query</span> <span style="color:#555">=</span> <span style="color:#c30">select 1 from users where email = &#39;%s&#39;</span>
</code></pre></td></tr></table>
</div>
</div><h3 id="etcpostfixsql_domainscf">/etc/postfix/sql_domains.cf</h3>
<div class="highlight"><div style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4">
<table style="border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#309">user</span><span style="color:#555">=</span><span style="color:#c30">mail</span>
<span style="color:#309">password</span><span style="color:#555">=</span><span style="color:#c30">password</span>
<span style="color:#309">hosts</span><span style="color:#555">=</span><span style="color:#c30">127.0.0.1</span>
<span style="color:#309">dbname</span><span style="color:#555">=</span><span style="color:#c30">maildb</span>
<span style="color:#309">query</span> <span style="color:#555">=</span> <span style="color:#c30">select 1 from domains where domain = &#39;%&#39;</span>
</code></pre></td></tr></table>
</div>
</div><h2 id="dns">DNS</h2>
<p>The final step to get postfix working is to tell the world where it is. To do
this you need to set a MX DNS record. The purpose of an MX record is to indicate
where a domain&rsquo;s mail server is hosted. While most DNS records should resolve to
IP addresses, for MX records you should be returning another domain name. This
is to allow resolving that domain to either an IPv4 or an IPv6 address.</p>
<p>MX records also have a <code>priority</code> field. With a single record it&rsquo;s irrelevant so
you can just set it to <code>10</code>. For the address, give the domain name of the server
that postfix is running on.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Congratulations, you should now have your own mail server.</p>
<p>You&rsquo;ll probably want to add spam filtering, and a few other goodies. There&rsquo;s a
good guide to setting that up <a href="http://flurdy.com/docs/postfix/">here</a>.</p>
<p>Have any questions or corrections? Leave a comment below, or drop me an email.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[New site is live]]></title>
    <link href="https://harry.pm/blog/new_site/" />
    <published>2015-11-24T20:39:08+00:00</published>
    <updated>2015-11-24T20:39:08+00:00</updated>
    <author>
      <name>Harry Jeffery</name>
    </author>
    <id>https://harry.pm/blog/new_site/</id>
    <content type="html"><![CDATA[<p>Welcome to my new site and blog. My old single-page site was starting to get a
bit stale for my tastes, so I decided it was time to throw it out, and start
afresh.</p>
<p>This time around my site is generated entirely with <a href="https://gohugo.io">Hugo</a>,
a neat tool for statically generating websites out of markdown and some
templates.</p>
<p>I played around with a few themes for a while, but couldn&rsquo;t find one I liked
enough that I could tweak to suit my needs easily, so in the grand tradition of
Not-Invented-Here syndrome I wrote my own from scratch.</p>
<p>Stay tuned for further updates!</p>
]]></content>
  </entry>
  
</feed>
