Some H2D2 progress, whilst messing with Run Length Encoding

So progress on my programming language, still codenamed H2D2 continues on background threads :-) I've not given up, but I haven't made many posts on the blog about it recently. It was probably getting boring anyway, and recent work has been tidying things up and writing unit tests - which does not make for interesting reading.

One thing that I wanted to try, was to compress the H2D2 bytecode so that it doesn't take as much time to serialise a running program between machines. I believe that Java JAR files are zipped, so I thought that I'd do something similar with H2D2. But I also wanted something that I could write myself that didn't take an age. Since I'm doing this for fun, it's nice to start with a blank page and go from there. So anyway, my web wanderings brought me to here. That page talks about Run Length Encoding - something that I implemented once myself back in the 1980s (or maybe the early 90s) - not that I have the source code anymore. But I read about the RLE PackBits algorithm and thought it might be a good way to go. Not a massive processing overhead and reasonably simple to implement. I chose not to look at the example souce code provided ... and just to write it from scratch myself. It sounded like fun.

It took me about an hour whilst drinking my morning coffee to write the compression code, and an hour or so in the evening to decompress the data back to the original values (I also wrote some unit tests to check for any obvious problems I could see). It seems to work OK: when I compress H2D2 bytecode I'm getting about a 30% reduction. It's not as good as zip compression obviously, but it will do for now.

I'm sure my code won't win any prizes for optimisation or style, but at least it works. I guess it might also come in handy if you were trying to squash some data on a microprocessor without needing a massive library or lots of processing power. So here is an example C program:

// Example RLE compression with PackBits
// ...just an example, not production code :-)

#include <stdio.h>
#include <string.h> // for memset

void fgrow(char*, char*);
void fshrink(char*, char*);

int main(int argc, char *argv[])
{
  if (argc==4 && strlen(argv[1])==2 && argv[1][0]=='/')
  {
    switch (argv[1][1])
    {
      case 'c':
        printf("Compressing... ");
        fshrink(argv[2], argv[3]);
        printf("done!\r\n");
        return 0;

      case 'u':
        printf("Uncompressing... ");
        fgrow(argv[2], argv[3]);
        printf("done!\r\n");
        return 0;
    }
  }
  
  printf("Usage: RLE { /c | /u }  \r\n");
  printf("   use the /c switch to compress or the");
  printf(" /u switch to uncompress\r\n");
  return 1;
}

void fgrow(char* inpath, char* outpath)
{
  char ch=0, hdr=0;
  FILE* op = fopen(outpath, "wb");
  FILE* mp = fopen(inpath, "rb");

  while (!feof(mp))
  {
    hdr=fgetc(mp);
    if (feof(mp)) break;

    if (hdr>=0) // copy bytes verbatim
    {
      for (; hdr>=0; hdr--)
      {
        ch = fgetc(mp);
        fputc(ch, op);
      }
    }
    else // copy a run of bytes
    {
      ch=fgetc(mp);
      for (; hdr<=0; hdr++)
      {
        fputc(ch, op);
      }
    }
  }
  fclose(mp);
  fclose(op);
}

void fshrink(char* inpath, char* outpath)
{
  char buf[128];
  memset(buf, 0, 128);
  int n=0, hdr=0, runlength=0;
  FILE* op = fopen(outpath, "wb");
  FILE *mp = fopen(inpath, "rb");

  while (!feof(mp))
  {
    buf[n++] = fgetc(mp);
    if (feof(mp))
    {
      n--;
      break;
    }

    if (n==128)
    {
      // buffer is full
      hdr=127;
      fputc(hdr, op);
      fwrite(buf, 1, 128, op);
      memset(buf, 0, 128);
      n=0;
      continue;
    }

    if (n >= 3 && buf[n-1]==buf[n-2] && buf[n-2]==buf[n-3])
    {
      // last three bytes are the same
      hdr = n-4;
      char symbol = buf[n-1];
      char tmp = symbol;
      if (n > 3)
      {
        fputc(hdr, op);
        fwrite(buf, 1, n-3, op);
      }
      runlength=3;

      while(!feof(mp) && tmp==symbol)
      {
        tmp = fgetc(mp);
        n++;
        runlength++;
      }
      hdr = 2-runlength;
      fputc(hdr, op);
      fputc(symbol, op);

      // put the different byte back for next read
      if (!feof(mp)) ungetc(tmp, mp);
      memset(buf, 0, 128); 
      n=0;
    }
  }

  // flush the buffer if not empty...
  if (n > 0)
  {
    hdr = n-1;
    fputc(hdr, op);
    fwrite(buf, 1, n, op);
  }

  fclose(mp);
  fclose(op);
}

Obviously this compression will only shrink files which have runs of the same repeated byte value in them. Otherwise it may increase the file size. You can try it from the command line and pass /c as the first argument to compress a file and then use /u to decompress the file back. The next two arguments need to be the names of the input and output files respectively. This example doesn't have any error trapping, so if the file fails to open, or something like that it will go bang. But that would not be hard to add.

Of course, in my H2D2 code, I'm using the same algorithm, but I've adapted the code to work on blocks of memory rather than on files. But in H2D2 I have made a VFILE struct to work alongside the C FILE pointers and I've added some functions that work the same as the C IO functions but taking my VFILE pointer instead. This means that I can easily swap code to operate either on disk or in memory...

Honda Unhappiness

If you're considering buying a Honda used car from a main dealer or are thinking about extending your Honda warranty, you may want to read my recent experience...

I've long been a fan of Honda cars. I've owned many, and most of them have been very reliable. However, the CR-V I bought in December last year developed a serious engine fault, so bad in fact that the dealer decided that the engine could not be repaired. The dealer said the whole engine needed to be replaced.

The car was fully covered by the 'Honda Happiness' warranty, but unfortunately, the dealer wanted to do the repairs at their own expense, and not use the warranty. This left me without a car. The warranty would have given me a hire car, but since the dealer was not making a claim on the warranty I found myself off the road. I was definitely not experiencing 'Honda Happiness' when I found myself taking the bus to work, to say the least.

After this dragged on for a week, and with no end in sight, I asked the dealer to just give me my money back. So I had to go and find another car to get back on the road again. But this seemed to be the quickest way to get my transport back.

Needless to say, I complained to the 'Honda Happiness' administration people, because the warranty that came with the car proved useless to me. But they've still not helped. I've taken it as far as I can, and this is their final response:

So, Honda are saying they've done nothing wrong. Meanwhile, the dealer said they're not obliged to use the warranty. And it seems that the only person who has lost out is me, the poor old customer. I would say that this is one of the worst customer service experiences I have ever had.

Ultimately, it seems that the 'Honda Happiness' warranty only helps you at the dealers discretion. Even if your car has a very serious failure like mine, it doesn't mean you're guaranteed to get any help. And if things go wrong, even if you complain, nothing seems to change. Even a token gesture to acknowledge all the inconvenience would have been something.

So, I'm left very disappointed indeed. Until now, I have considered myself a Honda enthusiast. As you can imagine, nowadays - not so much.

Casio personal-I (H-802)

Sometimes you're rewarded for looking around in second hand shops. Today, I found this Casio personal-I calculator in mint condition!

Not bad for the princely sum of £2.00, yes two whole pounds. Since I like a bit of retro, I had to own it, although I'll probably use it. It will look great on my desk at work.

As you can see here:

...it was boxed (the box is in near perfect condition) and has the original instructions and batteries as well. I won't use the batteries, they're pretty old. The actual calculator was still in the protective plastic bag inside the box. It's in such perfect condition I don't think it has ever been switched on.

Of course, the buttons make that nice clicky noise that you only get from electronics of this era. I found more information about this model here.

Islay adventure

We recently had a fantastic holiday on Islay, in the Hebredes. We stayed in a B&B called The Old Excise House which is next door to Laphroaig distillery, and also in walking distance to the Lagavulin and Ardbeg distilleries. It was a brilliant holiday, and The Old Excise House is probably the best accommodation I have ever stayed in.

To give you an idea, here is a photo we took from our bedroom:

...and when you visit the distilleries, they make you very welcome, here is the visitors tasting room at Laphroaig which is just a short walk up the road:

It was totally worth a days driving up from Cambridge, the scenery gets better and better as you go, and when you get past Glasgow it gets really good. So we're already making plans to go back.

Sony MEX-BT3900U Car Stereo Head Unit

I like it when things just work. Recently I replaced the standard Honda stereo head unit in my car for a better one. I wanted something that would work with my iPhone (both to play music and make phone calls) and that I could plug a USB stick into ... as well as the normal CD player, FM radio type stuff.

I managed to get one of these Sony MEX-BT3900U units on special offer (less than half price in fact).

I'm very pleased with it, everything just worked out of the box. It talks nicely to my phone over bluetooth (I can use the USB cable too which means I can charge my phone whilst driving).

I even fitted it myself. If like me, you have steering wheel controls on your car make sure you get the right adaptor. At first I got a basic Autoleads PC2-68-4 which worked fine, without any steering wheel controls. But now that I have the correct adaptor for my car everything works. Very cool.

Formula One and Lego

What better way to mark the impending start of a new season of Formula One than with some Lego:

Yes, we've been buying Lego. Some second hand stuff from eBay and some of the new 'Lego Creator' kits. Such fun. We made the car and then decided that it needed a garage to be kept in. Not a bad way to spend part of a Sunday afternoon.

Simple queuing with SQL Server and C#

I've been working on some simple queuing code using a SQL Server database and some C#. Items are queued by being inserted into a SQL table and then taken off the queue in batches. Multiple processes should be able to remove items from the queue at the same time. Oh, and you should be able to remove a subset of queued records in case you only want to dequeue records that match some criteria. What I came up with is surprisingly simple, the key part is the following SQL:

DELETE FROM TestQueue WITH (READPAST) OUTPUT DELETED.*
WHERE TestQueue.Id IN
(
  SELECT TOP(10) Id -- maximum batch size
  FROM TestQueue
  WHERE Data >= 0 AND Data <= 1000 -- selection criteria
  ORDER BY Id ASC
)

...this way you can set a batch size, meaning you can remove a number of records at a time and you can specify a criteria when you only wish to remove certain items from the queue. The beauty of the above SQL command is that it deletes the records and returns them at the same time. If there aren't enough records in the queue to fill a batch then it returns whatever it finds.

Here is how you could try it out in a C# program:

  1. Create a new Console App in Visual Studio 2012
  2. Add the NuGet package called 'PetaPoco' (which is a micro-ORM)
  3. Create the Queue Table, like this
  4. Set a connection string called "SQLq" in the App.Config of your Console App
  5. Use this program code

The example code will clear the table, then queue 1000 items. Next it will spin up six threads each dequeuing different ranges of items using a variery of different batch sizes. After the process is complete the table should be empty - all the items should have been removed.

Well, OK, this is just test code to show how it works, you'd write it differently in a live system, but hopefully it shows the idea...

Using my WCF http Basic Authentication code in VS 2012

I blogged about the implementation of http basic authentication that I made in this post here, but this is a more detailed description of how to get it working in a simple WCF service in Visual Studio 2012.

First, you'll need to set up a basic out-of-the-box WCF service in Visual Studio 2012:

...and change it slightly so that it can be used from a browser, as described in this post here. You should now be able to call your service from any web browser to see it's working properly.

Personally, I just stuck to the default Microsoft code example and added a [WebGet] attribute, like this:

[WebGet(UriTemplate="getdata?num={value}")]
public string GetData(int value)
{
   return string.Format("You entered: {0}", value);
}

...which means that I can call http://localhost:8080/Service1.svc/getdata?num=1 to pass a querystring value to my method.

Now, add these files to your project (BasicAuthenticationAttribute.cs, BasicAuthenticationHttpHeaderInjector.cs and BasicAuthenticationPasswordValidator.cs). When you've done that, just add the [BasicAuthentication] attribute to your service class. That's it! Try running the project again.

You should be asked for a username and password by the browser. Now, the WCF service will only return some data when you have used these details: username='user' and password='password'. You can change the BasicAuthenticationPasswordValidator class to implement whatever means you like to check that the user is authorised.

You now have a code-only implementation of http basic authentication for WCF. If you're using IIS, you don't need to configure anything to make this work, as far as IIS is concerned you are using anonymous access. But it should also work in IIS Express or the Visual Studio Development Server.

NOTE: this code makes no attempt to encrypt the username and password you type into the browser. The details will be sent in clear text as an http header. You should at least consider using https to encrypt the data. The purpose of this code is just to show how http basic authentication works, and how it could be done in code.

WCF HTTP Basic Authentication in Code

So I wanted to build a WCF service with a very simple authentication mechanism, and I thought that it would be good to start with my own implementation of http basic authentication - and then I could go from there, adding my own extras to the protocol if I wanted. But I thought that basic authentication over https would at least be a start.

And even though the username and password are sent in clear text, doing that over an https connection should be safe since it's encrypted before going over the wire.

Finally, I wanted to do the whole lot in code, so that I can deploy it to some hosted space without fiddling around in IIS. But also because I like code :-)

The good thing is that basic authentication is supported by most browsers, so I could expose the WCF service as web methods and test it very easily. I have assumed that since it works with all the major browsers I have implemented the protocol correctly.

The end result was a custom attribute which can be added to a WCF service and does all the work for you. The only other thing that needs to be done is modify the method which decides if a user is valid or not.

Here is the source code (click the image to download):

I'll post an example of how to use it (in Visual Studio 2012) in another blog.

Virtualise, Wipe and Reinstall

My home PC had been getting slower over time ... over the years I have installed a lot of software that I don't really use anymore, and there were still a bunch of Lenovo tools on there from when it was new. So it was time for a clean reinstall - a reformatted disk with a fresh copy of Windows can work wonders. But I still wanted a full backup of the old machine, just in case. So I thought that it would be good to virtualise the whole machine before I wiped it. Then I could always go back to the old version if I needed anything. Which is normally the case...

Anyway, I used the excellent Disk2VHD tool which can virtualise a hard disk whilst it is still running. So you can create the VHD on the machine that you're virtualising. Very cool.

So I'm now using VirtualBox to boot up the Virtual Hard Disk which has been created. It was a very nice way to achieve a clean install without losing anything, and it was pretty painless. I might do the same thing on my laptop actually...