24 Jun 2026 • Fast LZ match lengths One step in LZ encoding is computing the longest match at the current position for a given offset, or computing how long the shared prefix between two strings is. In Leetcode parlance, this is called Longest Common Prefix. In C, you find the largest n such that memcmp(a, b, n) == 0 . The scalar implementation is obvious, the SIMD version is also very…
20 Jun 2025 • Auto-mounting USB drives on NixOS This is a followup to Auto-mounting removable drives , a post that was already long obsolete by the time I posted it. Assuming mounting disks has advanced at the same pace as the rest of Linux userspace, you would expect this post to be at least 15 years better than the old one, and you would be correct. The most obvious change is that Linux…
6 Feb 2025 • Apple products quarantine post This is a combo post for a couple of nice little things you can do with your phone. "Siri vacuum the kitchen" Valetudo has a Home Assistant integration, you have to set up some MQTT garbage and that's probably annoying so I didn't do it. Instead, you can get the payloads by hitting F12 in chrome and use the Shortcuts app to send HTTP requests.…
29 Jun 2024 • C tricks: enum arithmetic It's annoying having to write stuff like for( MyEnum i = MyEnum( 0 ); i < MyEnum_Count; i = MyEnum( i + 1 ) ) { Doubly so with enums that are really bitfields where you can actually do arithmetic, they just return non-enum types and C++ doesn't allow the implicit casts back to the enum in all situations. At some point you might get sick of this and…
7 Jun 2024 • C tricks: STL-free type traits I ended up not actually using these but it seemed a shame to throw them away so here they are for copy pasterity. underlyling_type: template< typename T > constexpr bool IsSigned() { return int( T( -1 ) ) == -1; } template< size_t N, bool Signed > struct MakeIntType; template<> struct MakeIntType< 1, true > { using T = s8; }; template<> struct…
21 Feb 2024 • sem_postmany On Windows, ReleaseSemaphore lets you raise/post a semaphore n times with a single call, the idea being that the OS can implement it more efficiently than n syscalls in a loop. Indeed on Linux the underlying syscall has that functionality, futex can (amongst other things) make a thread wait for some token to be signalled, and wake some number of threads blocking…
24 Jan 2024 • All perf zero quality BC4 encoding BC4 encoding is pretty straightforward. You find the min/max to use as endpoints and do a little bit of funny arithmetic to compute the selectors. But what if we didn't care at all about quality? The motivation behind this is we have a lot of single channel decals in Cocaine Diesel that are mostly pure white on a pure transparent background.…
22 Jan 2024 • C tricks: NonRAIIDynamicArray In Cocaine Diesel our DynamicArray class takes an Allocator in its constructor. One our of allocators is just malloc plus std::map< void *, AllocInfo > for leak checking, which we initialise statically. So it didn't take us long to run into the standard static initialisation order problem when we wanted to use file-scoped arrays. At first we added…
22 Jan 2024 • C tricks: defer I was writing another tricks post and was shocked to find I hadn't already posted this. It's super useful! C++ purists would call it heresy and tell you to use RAII, in practice I've found RAII gets in the way as much as it helps which is annoying and no good. Credit to either Jonathan Blow and Ignacio Castaño, since this is either lifted from jblow's MSVC…
27 Dec 2023 • Configuring launchd scheduled tasks with Nix home manager macOS has a thing called launchd which amongst other things can run scripts periodically. I use it to schedule backups and auto-update youtube-dl. I thought it would be nice to manage that through home manager so it's one less thing to forget about. You can do it out of the box and it is ostensibly documented in places…
30 Nov 2023 • C tricks: STL-free initializer list Credit for this one to https://nitter.net/Donzanoid/status/1611315409596071936 . C++'s initializer_list is dogshit: > cat a.cpp #include <initializer_list> > cl.exe /std:c++20 a.cpp /P > /dev/null; and wc -l a.i Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32534 for x64 Copyright (C) Microsoft Corporation. All rights reserved. a.cpp…
29 Nov 2023 • Realloc and arena allocators If you combine a dynamic array with an arena allocator, you get a dynamically growing buffer on top of a dynamically growing buffer. The easiest way to implement realloc is as malloc + memcpy + free, but that behaves sub-optimally here. Unfortunately the standard realloc interface prevents you from doing any better. You could fix that by storing…
29 Nov 2023 • C tricks: Production Ready TM aligned malloc People generally implement aligned malloc by adding some metadata at ptr[-1] pointing to the actual allocation. In this post I will show you a simpler way. void * Allocate( size_t size, size_t alignment ) { Assert( alignment <= 16 ); return malloc( size ); } This works because: Windows: "In Visual C++, the fundamental alignment is…
18 Nov 2023 • 2023 Windows post-install checklist This is a guide on how to set up Windows to not be annoying. You should set aside a few hours to go through everything. Most steps, but not all, are detailed enough that you can autopilot your way through it. Initial setup and disabling security features Install the correct version. You want Windows 10 IoT Enterprise LTSC 21h1, which is…
4 Nov 2023 • Running a business in Finland I noticed I was getting a lot of spam from Finnish companies to firstname.lastname@. Presumably this comes from scraping the companies registry. Fastmail lets you block senders but not recipients from the GUI, so we have to nuke them from sieve instead: ### Reject firstname.lastname {{{ if anyof( address :matches :localpart "to"…
11 Sep 2023 • Least effort self-destructing email addresses with Fastmail Fastmail has a builtin tempomail provider ( "Masked Email" ) which works and is good, but is mostly just barely too clunky to use much. So I made a sieve filter that lets me sign up for things with e.g. blah.temp20230101@... and auto-rejects emails received after the date in the address. ### Reject tempYYYYMMDD@ after…
19 Jul 2021 • Building a userspace CSPRNG on top of Monocypher 3 Same idea as the code I wrote a few years ago , except for the latest version of Monocypher and it actually works. The tl;dr of the last time I did this is that OS entropy APIs are annoying because that have vaguely defined failure conditions, and moving it to userspace sidesteps all of that. We still need to seed it with…
2 Dec 2020 • An equal but opposite reaction Too many websites have adblock detection and whine banners now, let's stick it to the man. 👍 Thanks for blocking ads! 😍 ⚠️ Uh-oh, you're not blocking ads! ⚠️ Please install one or more of the following: Chrome/Edge: uBlock Origin Firefox: uBlock Origin iPhone/iOS: AdGuard Android: Firefox and uBlock…
18 Aug 2020 • OpenSMTPD is excellent 2020 edition It's been three years since I first posted this and OpenSMTPD still kicks dick. But the config format and plugin ecosystem has changed a lot since then so I thought I'd post my config again (minus some Mike stuff covered elsewhere on this blog). The biggest differences from last time are that smtpd has filters now and Jeff Bezos delivers my…
14 Aug 2020 • C tricks: catching ASAN errors in a debugger Add a breakpoint at __sanitizer::Die then try not to think about how ASAN could just call abort.
9 Jul 2020 • gg libraries index gg libraries are little libraries that are easy to add to any project (one .cpp and one .h). So my contribution to stb land. Library What it does ggformat Better printf ggentropy Cross platform crypto secure entropy function ggtime High precision fixed point time function
9 Jul 2020 • ggtime ggtime is a sane (i.e. not using <chrono> ) implementation of Facebook's flicks library . Basically it's a fixed point time library with roughly nanosecond precision, and whose unit divides all the FPS values we care about in games. github
21 Jan 2020 • Daily Mail Alternatively titled: least effort self hosted disposable mail Email spam is widely considered to be a solved problem. If you open your inbox this is immediately obviously false. Scams and outright virus mail are long gone, but the spammers have adapted. Customer success mails, newsletters after you unchecked the box saying I want newsletters, terms of service…
26 Dec 2019 • C tricks: compound literals C99 has this nice thing where you can initialise structs inline with named members, so like: struct A { int a, b, c; }; ... struct A a = ( struct A ) { .c = 1, .a = 2 }; printf( "%d %d %d\n", a.a, a.b, a.c ); // { 2, 0, 1 } It's useful so it's not available in C++, but we can hack it together with variadic templates and pointer-to-members: template<…
31 Oct 2019 • C tricks: member array count I recently wanted to make an array with the same size as some other array. Normally I would use ARRAY_COUNT , But this time the reference array was a struct member, and I was in a context where I had no struct instance I could use. So this: struct A { int a[ 4 ]; }; struct B { int b[ ??? ]; }; The solution is to use C++'s "pointer to data member"…
31 Oct 2019 • GL tricks: glPushDebugGroup KHR_debug can do more than just spam you every time you call glBufferData, it also has a cool thing called debug groups. They don't do anything normally but you can use them to group related draw calls into collapsible lists in renderdoc. For example, here's a diesel engine frame: They're very simple to use: glPushDebugGroup(…
25 May 2019 • Server side React JSX is nice. Most templating languages start with HTML and add dumpy scripting on top, while JSX adds HTML syntax to javascript. It means you (mostly) get to use normal language constructs and flow control and it's much less annoying. I'd like to see more languages go this way. If you only want to use it server side so people don't have to enable javascript…
29 Apr 2019 • SSH local discovery tinc has a nice feature called local discovery, where if the endpoints can talk directly it will do that rather than routing packets out through my VPS. Wireguard is the new hotness but it doesn't do this. The only thing I really use my VPN for is to SSH/scp between my computers though, so solving this for SSH solves 99% of the problem. Fortunately it's…
15 Apr 2019 • C tricks: compile time string hashing While writing that last post I figured I should write about this too. We use it in Cocaine Diesel to generate a unique version number from the version string (git shorthash or tag if there is one). We also plan to use it for assets so we can refer to them by name in the code but not have it be super slow at runtime (could use an enum but…
15 Apr 2019 • C tricks: compile time type IDs Here's a little trick for getting a unique ID for each type in your codebase, entirely at compile time. typeid C++ has typeid which is garbage. It works like this: #include <stdio.h> #include <typeinfo> int main() { constexpr const std::type_info & a = typeid( int ); printf( "%zu\n", a.hash_code() ); return 0; } and compiles to leaq…
4 Mar 2019 • Useful tmux window titles If you Google for this you'll find a lot of wrong answers. tmux rename-window is useless and will break if you do like sleep 1 and switch windows. Fortunately tmux has an escape sequence you can use too. First you have to enable it in tmux.conf: set -g allow-rename on Then to get the current working directory put this in your shell prompt: echo -en…
18 Feb 2019 • Sending mail through Amazon SES with OpenSMTPD I've not had problems with delivery but sending your own mail is generally considered to be No Good, and SES is $0.10 per 1k messages, so why not. You need to add a few DNS entries so SES can verify your domain, then grab your SMTP credentials from the dashboard and put them in /etc/mail/ses_credentials like ses username:password…
12 Jan 2019 • Detecting WSL in Makefiles 2024 update: WSLENV doesn't work anymore, do ifdef WSL_DISTRO_NAME instead. There's a WSLENV variable, but it's empty by default so ifdef doesn't do what you want. ?= can distinguish between empty and undefined, so this works: WSLENV ?= notwsl ifndef WSLENV # this runs when you _are_ in WSL endif
12 Jan 2019 • Windows 10 2019 post-install checklist This is a guide on how to set up Windows 10 to not be annoying. You should set aside a few hours to go through everything. Most steps, but not all, are detailed enough that you can autopilot your way through it. Initial setup and disabling security features Install the correct version. You want Windows 10 LTSC, which is pretty stripped…
5 Jan 2019 • Immediate mode audio In games you typically have a fire and forget API, where you start a sound and it plays to completion. Maybe it returns some handle so you can stop it later on. PlayingSound ps = PlaySound( "path/to/sound" ); ... StopSound( ps ); Most of the time you want to play sounds to completion so this is nice and convenient, but sometimes you have sounds attached to…
18 Dec 2018 • How to get rid of ? globbing in fish ? globbing is useless and makes pasting URLs annoying, this is how you kill it: git clone https://github.com/fish-shell/fish-shell cd fish-shell sed -i "s/set_from_string(opts.features)/set_from_string(L\"qmark-noglob\")/" src/fish.cpp then make and install that. If you're on arch you can grab fish-git from AUR, and add the sed line to…
12 Sep 2018 • Branch prediction minutiae in LZ decoders Say we have an LZSS inner decode loop like this (not good, just an example): u8 ctrl = read_u8(); // match when MSB of ctrl is set, literal otherwise if( ctrl >= 128 ) { u32 len = ctrl - 128 + MML; if( len == 127 ) len += read_extra_length(); u16 offset = read_u16(); memcpy( op, op - offset, len ); op += len; } else { u32 len = ctrl;…
8 Sep 2018 • Least effort image self-hosting My requirements: Self hosted Easy to upload photos from my PC Easy to upload photos from my phone Don't require tons of new crap software on my VPS I already have mail clients on my PC/phone, and a mail server running on my VPS, so writing it as an MDA seemed like the least effort approach. It ended up being one line in smtpd.conf, 70 lines of…
8 Sep 2018 • Using WSAAsyncSelect This API is garbage, the docs are garbage, and every piece of code I could find that uses it is garbage. It works roughly like this: You open a socket You call WSAAsyncSelect on it WndProc gets called with FD_READ every frame if there's still data on the socket WndProc gets called with FD_CLOSE when it closes which looks totally reasonable. But, FD_CLOSE…
24 Apr 2018 • GoAccess with OpenBSD httpd httpd's logs are pretty similar to CLF but not exactly, so you need to put this in ~/.goaccessrc : time-format %T date-format %d/%b/%Y log-format %v %h %^ %^ [%d:%t %^] "%r" %s %b And then run zcat /var/www/logs/access.log.*.gz | cat /var/www/logs/access.log - | grep -v syslog | goaccess --no-global-config .
14 Apr 2018 • namespace is bad and should not be used namespace in C++ is an odd one. Even anti-C++ people do not seem to complain about it, and it's not obvious exactly why it's bad. It's taken me some years of programming in C++ to come to that realisation myself. The problem with namespace is that it brings no upsides and causes problems that are very annoying and somewhat time consuming…
5 Apr 2018 • Never update anything #145432 I occasionally write posts like this and then delete because it's just whining about things that are not interesting and nobody wants to read it. But this case was so annoying so that I have to push it. I wanted to install OBS so I could record my screen with sound. OBS has a lot of dependencies and thanks to dynamic linking that basically meant I…
30 Mar 2018 • cmov The reason cmov is not always is a win is that you have to block on the branch condition and on both sides of the branch. To make that more explicit, say you have some code like this, and let's assume we take the true side of the branch. int x; bool p = [pred code]; // let's say it ends up being true if( p ) { [true code]; x = something; } else { [false code]; x =…
21 Mar 2018 • Compression gold medalist I have the world's fastest compression algorithm. Some quick preliminary benchmarks against LZ4: Silesia mozilla LZ4 -1: 717.1MB/s encode, 3057.9MB/s decode, 1.938 ratio me: 553.5MB/s encode, 5305.8MB/s decode, 1.991 ratio I'm nearly 75% faster to decode with slightly better ratio. My encoder hasn't received much love but will become faster than LZ4…
26 Feb 2018 • ggentropy Code dump for a cross platform getentropy . Goes well with the CSPRNG post . Update: deleted the inline code dump code because and put it on github
7 Feb 2018 • C tricks: dealing with 3rd party code There are really only two options for this. You can copy the source code into your repository and add it to your build system. If it's too hard to add to your build system or takes too long to compile you can add it to CI separate from the main codebase and commit the binaries. I feel like this is pretty well known, the only interesting…
28 Jan 2018 • Building a userspace CSPRNG on top of Monocypher 2 Addendum July 2021 This was written against Monocypher 2 and doesn't work with Monocypher 3. Also the stirring logic is bad, when you encrypt something the chacha state is unaffected by the data itself, i.e. the entropy doesn't actually get mixed in. You need to reinitialise the chacha context! Go here for the Monocypher 3…
11 Jan 2018 • C tricks: named function arguments You all know what they are and why they're useful. In C you can hack it with designated initialisers and macros so your calls look like f( .x = 1, .y = 2 ); . C++ doesn't have designated initialisers, but you can do something pretty similar with lambdas: struct FooArgs { int x, y; }; int foo_impl( const FooArgs & args ) { return args.x +…