Jez Higgins

Freelance software grandad
software created
extended or repaired


Follow me on Twitter
My code on GitHub
Talks & Presentations

Hire me
Contact

Older posts are available in the archive or through tags.

Feed

Friday 03 July 2020 Talk: Journey Into Space

nor(DEV):live - Journey Into Space with Jez Higgins

How I read an article by one of the original signatories of the manifesto for agile software development, and accidentally ended up writing a version of Asteroids for my phone.


Because no good deed goes unpunished, when I mentioned on Twitter that I had unexpectedly written a phone game, I was signed up to do a live stream for my friends at Norfolk Developers in about 5 seconds flat. I don’t think I’ve put together a talk in such a short space of time before, and I did lose my thread a little at the end, but it was fun to do and people seemed to enjoy it.

Thanks in particular to Alex and Shaun at NorDev for indulging my video pipelining shenanighans instead of insisting I just do a screen share like a normal person.

The articles that kicked all this off

  • Ron Jeffries' Asteroids articles. I’d strongly suggest you start at the beginning and work through because they’re just a delight, but if that seems a bit daunting at least read number 59. If you aren’t moved by that one, I don’t know what to say to you.

The WikiWikiWeb

The C2 Wiki still exists, with much of the content from the time I was talking about.


Tagged talk, nordev, code, and android

Friday 05 June 2020 The Forest Road Reader, No 2.48 : STinC++ - makecopy

STinC++ rewrites the programs in Software Tools in Pascal using C++

Deep into chapter 3, we’re now on our fifth file handling program and it takes a bit of a turn away from what we’ve done so far.

PROGRAM

makecopy copy a file to a new file

USAGE

makecopy old new

FUNCTION

makecopy copies the file old to a new instance of the file new, i.e. if new already exists it is truncated and rewritten, otherwise it is made to exist. The new file is an exact replica of the old.

EXAMPLE

To make a backup copy of a precious file

makecopy precious backup

BUGS

Copying a file onto itself is very system dependent and usually disastrous.

As you read this program description, you’re probably already sketching the source out in your head. The description even says 'truncated and rewritten', which is a pretty solid example of implementation detail leaking into documentation. I certainly was, not least because Kernighan and Plauger have established a pattern of setting out a problem at the start of a chapter, and then growing and tweaking the code we write to take us through solving the next problem and the next.

This program differs significantly from its predecessors, though. It’s entirely about the file system. We’re copying a file. We’re not changing the contents, we’re not even looking at it. We just need to manipulate the file, and if we can do that without cracking it open and messing around with its insides, well that would be lovely. And we can! In a development that’s taken nearly 20 years and required what seems like unreasonable amounts of high-quality brainpower, as of the 2017 standard C++ sports a spiffy filesystem library.

makecopy.cpp
#include <iostream>
#include <filesystem>
#include <tuple>
#include "../../lib/arguments.hpp"

namespace fs = std::filesystem;

std::tuple<fs::path, fs::path> file_paths(int argc, char const* argv[]);

int main(int argc, char const* argv[]) {
  try {
    auto [source, destination] = file_paths(argc, argv);

    if (fs::exists(destination) && fs::is_regular_file(destination))
      fs::remove(destination); (1)

    fs::copy_file(source, destination);
  } catch (const std::exception& fse) {
    std::cerr << fse.what() << '\n';
  }
}

std::tuple<fs::path, fs::path> file_paths(int argc, char const* argv[]) {
  auto filenames = stiX::make_arguments(argc, argv);

  if (filenames.size() != 2)
    throw std::runtime_error("Error: makecopy old new");

  auto source = fs::path(filenames[0]);
  auto destination = fs::path(filenames[1]);

  if (fs::equivalent(source, destination)) (2)
    throw std::runtime_error("Error: source and destination are the same file");

  return std::make_tuple(source, destination); (3)
} // file_paths
  1. The copy operation, fs::copy_file, fails if the destination exists, hence why I delete any existing file first.

  2. fs::equivalent is almost, but not quite, equals for paths. Two paths are equivalent if they point to the same file, even if one is, say, a file and the other a symlink, or one is a relative path and the other absolute, or whatever. If, underneath it all, they resolve to the same file, they are equivalent.

  3. I’m using a std::tuple as an ad hoc multivalue return. Using the magic of auto and structured binding, we can unpack the tuple directly into two separate variables at the call site and never really see the tuple at all. As I’m returning two values, I could have used a std::pair I suppose, but std::tuple just feels more suited here. To me, a pair says these two things belong together while tuple says these are just some things that I happen have right now.

But does it work?

It does, but you’ll have to build and run it yourself to prove it.

Partly because it’s so short, little more than a glorified wrapper around a library function, and partly because it’s all about filesystem manipulation, this is the first STinC++ program for which I wrote no tests. I could, I suppose, have shimmed out the std::filesystem functions I needed, done a bit of namespace manipulation, and thrown some tests around it but, what, really would that prove? There’s no 'business logic' to validate, no unit to isolate. I could try to test 'good' and 'bad' inputs I suppose, but filesystems are hard and any mock couldn’t hope to match real behaviour beyond the simplest.

Part of the raison d’etre of a standard library is to provide guarantees about the boundaries of your program. I’m happy to rely on those here. After all, this version doesn’t suffer from the bug described by Kernighan and Plauger and can make a much stronger claim on the new file is an exact replica of the old than their program could.

That’s All Very Neat, But Haven’t It Rather Missed The Point

Having thoroughly covered reading files, Kernighan and Plauger’s pedagogic intent with makecopy was to introduce programmatic file creation. This version of makecopy does not do that. It’s not even close. I’m a little surprised to get this far into the book before the Pascal and C++ version diverged so completely. Maybe we haven’t come as far as we thought.

Source code

Source code for this program, indeed the whole project, is available in the stiX GitHub repository. print is fifth program of Chapter 3.

Library Reference

  • The Filesystem library was added in C++17. It does look largely as you expect, and is one of the many Standard features born and nutured in Boost

  • Structured Binding Declaration, binding the specified names to subobjects or elements of the initializer, is one of the gifts of C++17 that will surely be giving for a long, long time.

  • std::tuple has been around since C++11, but I wouldn’t be surprised if it had largely passed you by until structured binding made it radically more convenient to use.

Endnotes

This whole endeavour relies Software Tools in Pascal and Software Tools, both by Brian W Kernighan and PJ Plauger. I love these books and commend them to you. They’re both still in print, but new copies are, frankly, just ridiculously expensive. Happily, here are plenty of second-hand copies floating round, or you can borrow them from the The Internet Archive using the links above.

For this project I’ve been using JetBrain’s CLion, which I liked enough to buy a license. CLion uses CMake to build projects. My previous flirtations with CMake, admittedly many years ago, weren’t a huge success. Not so this time - it’s easy to use and works a treat.


Tagged code, and software-tools-in-c++

Wednesday 27 May 2020 First ice cream van of the year …​

A longitudinal study

First confirmed ice cream van of the year. Tony’s Ices - Yankee Doodle chime - at the bottom of Grove Avenue at 16:57. No customers, despite beautiful sunny weather, which no doubt accounted for probably-not-actually-called-Tony’s scowling face. Don’t blame people really. I wouldn’t buy from an ice cream man who smoked in his van either.

This is the same van and location as last year, making it the first confirmed repeat recording.

This year’s sighting is the latest yet, fully six weeks beyond our previous latest sighting. It is, perhaps obviously given that, our first sighting in May. It’s also our first Wednesday.

At first glance then, this year’s recording appears wildly anomalous, but we must not rush to judgement. When we have another 15 or 20 more data-points, we can set this in its proper context. Until then, we can only speculate.

The Van

Tony’s Ices

Field observations

Analysis

First Ice Cream Van Of The Year 2004-2020
First Ice Cream Van Of The Year 2004-2020
First Ice Cream Van Of The Year 2004-2020

The full ice cream van data is available as a spreadsheet.

Previous Years


Tagged icecream

Monday 18 May 2020 The Forest Road Reader, No 2.47 : Iris

A single purple iris, framed against a pale green bush.

Thursday 30 April 2020 The Forest Road Reader, No 2.46 : STinC++ - print

STinC++ rewrites the programs in Software Tools in Pascal using C++

The previous program, concat, was a simple example of taking an indeterminate number of inputs and generating one output. That your own machine undoubtedly has cat or its moral equivalent installed shows the enduring utility of combining files, unformatted, into a single stream.

Similar styles of program, such as less, take those multiple inputs and produce some kind of formatted output. Kernighan and Plauger’s next program, print, continues the many-in/one-out pattern and adds just a smattering of formatting.

PROGRAM

print print files with headings

USAGE

print [ file …​ ]

FUNCTION

print copies each of its argument files in turn to its output, inserting page headers and footer and filling the last page of each file to full length. A header consists of two blank lines, a line giving the filename and page number, and two more blank lines; a footer consists of two blank lines. Pages for each file are numbered starting at one. If no arguments are specified, print prints its standard input; the file name is null.
The text of each file is unmodified - no attempt is made to fold long lines or expands tabs to spaces.

EXAMPLE

print print.p fprint.p

My implementation is probably much as you would imagine. Loop on each file, reading a line at a time, keeping count of lines as we go. If we’re at the top of a page, print the header. If we’re at the bottom, print the footer. When we run out of lines to read, pad with blanks until we hit the bottom of the page.

My initial implementation matched almost exactly with Kernighan and Plauger’s. The only real difference was that I calculated the number of lines in the header and footer from their implementations, rather than using manifest constants. But there it was, a loop, some input, some output, a bit of incrementing, some conditionals, just as Kernighan and Plauger had 40 years previously -

print.cpp - initial implementation
  int print(
    std::string const& filename,
    std::istream& input,
    std::ostream& output,
    size_t path_length
  ) {
    size_t page_count = 0;
    size_t line_count = 0;
    size_t const last_line = path_length - footer_lines;

    while(input && !input.eof()) {
      if (line_count == 0) {
        header(filename, ++page_count, output);
        line_count += header_lines;
      }

      std::string line = getline(input);
      output << line << '\n';
      ++line_count;

      if (line_count == last_line) {
        footer(output);
        line_count = 0;
      }
    }

    if (line_count != 0) {
      for ( ; line_count != last_line; ++line_count)
        output << '\n';
      footer(output);
    }

    return page_count;
  } // print

Since I’ve already described what it does, you can quite easily see which bit does what and it’s, you know, fine. But it’s a bit of long, and it’s kind of boring.

So late on, after I’d started drafting what you’re reading now, I had another go at it, gathering up the bits of state into a little class, and now the file printing loop looks like this.

print.cpp
  class page_printer {
    // ...

    size_t print() {
      while(input_available()) {
        if (at_page_start())
          print_header();

        print_line();

        if (at_last_line())
          print_footer();
      } // while ...

      pad_to_page_end();

      return page_count_;
    } // print

    // ...
  };

Better.

Source code

Source code for this program, indeed the whole project, is available in the stiX GitHub repository. print is fourth program of Chapter 3.


Tagged code, and software-tools-in-c++
Older posts are available in the archive or through tags.


Jez Higgins

Freelance software grandad
software created
extended or repaired

Follow me on Twitter
My code on GitHub
Talks & Presentations

Hire me
Contact

Older posts are available in the archive or through tags.

Feed