My hobbyist coding updates and releases as the mysterious "Mr. Tines"

Friday, 30 November 2007

Life in the old dog yet…

Contradicting my earlier assertion that “it's only when you want GUI that you have to get off the fence.” — I've built the Java 1.0-based Gadget Windowing Toolkit against JVM for Java 5 and (with just a little added C#) CLR.

It might not be “teh shiny”, and won't give you mouse wheel events, but it's the fastest way to a common GUI toolkit for both VMs.

Weaning it off the Java 1.0 event model that it uses inside a 1.1 emulator, and using Container instead of its own Gadget class (written because Container and Component had protected constructors at Java 1.0) would make it a lot leaner, and more robust, but it's not a simple matter of mechanically replacing the classes. There is a lot of code dedicated to managing focus and graphics contexts — including managing the masks and offsets — that would have to be carefully moved across.

And of course, there's only the one huge demo/test, rather than unit tests.

Tuesday, 27 November 2007

Smelling the coffee…

… before work goes crazy in the 4 weeks left to holidays — a first drop of angerona.redcoffee.zip; what may (ha! ha!) become a hybrid Java/Ruby CTClib equivalent for both JVM and CLR.

This contains code for various symmetric crypto algorithms, strong hashes, erasable big numbers and Zlib compression (based on JZlib 1.0.7); it contains some initial JUnit tests aimed at JUnit 3.8.2 in NetBeans 6.0 (currently using RC1). It also contains a project to build JUnit 3.8.2 (almost) as a J# project generating a command line executable (.exe also included). The "almost" is because the assertEquals() methods for Double and boolean have been taken from 3.8.1 to permit them to compile under J#.

The NetBeans project has been amended to use cobertura 1.9 to perform coverage analysis as the unit tests are run -- assumed to be in C:\cobertura-1.9, adjust build.xml to fit your location; or use it as a prototype for other projects. The VS 2005 solution builds the JUnit ~3.8.2 executable, the angerona.algorithms.dll library, and the unit tests as three projects; and as a post-build step for the last runs the tests under NCover (assumed to be installed to directory C:\Program Files\NCover) -- I'm using 1.5.4, having had some problems with 1.5.8 run over managed C++ code not contained in gc classes.

Also included is an FxCop project; I shall be using that run manually, and PMD as a live plug-in while the code is being groomed; they will get incorporated into the build process later when the noise level has been considerably reduced.

Note that the two build environments are set up to use the same source file structures, though J# has to be hand-held to point it at the files that NetBeans just picks up automagically.

The only files in any sort of stable state at the moment, the proofs of concept, are SHA0.java and SHA1.java, which have unit tests based on the FIPS PUB 180-1 test vectors. These tests all pass and give 100% coverage (including branch coverage) to the base SHA class and the two wrappers. The first phase will be getting the state of no PMD warnings, no FxCop warnings (except where naming conventions are involved, and there, Java conventions set out by PMD will win if there is a conflict), unit tests with ideally 100% coverage; this will overlap with doing some refactoring.

Then with a stable foundation, the plan will be to gradually migrate the rest of CTClib, primarily to Ruby, but probably with a few Java interface types to make the external interface more easily usable by other JVM or CLR projects.

Archive is 257,055 bytes; MD5 7335e89a 171560f3 003f225e d97a3b3c & SHA-1 4d421c00 d4b3b45d be0244e3 649b19bd 04923a94.

Monday, 26 November 2007

Shaking some dust off…

After a long distraction by paying work, I'm starting to turn attention back to projects. The IronPython FTP client still needs wiring up (and bug fixing), but a few developments in recent months -- JRuby, and now Ruby.Net 0.9, have led me to turn my attention once again to taking my old PGP-emulator library, currently languishing as 'C' and a number of abortive ports, out of the 1970s.

I have several key bits -- crypto algorithm implementations I rolled myself, and, now the JZlib port of the key ZLib component (for reasons best known to PRZ, the version in PGP 2.x uses an 8k window, and no standard APIs give you control over that so as to be able to emit compatible compression) -- in Java. But now I could build the rest of the system in Ruby and build it to the CLR as well as the JVM.

Then it's only when you want GUI that you have to get off the fence.

Of course, uploading the library will mean I shall want to have completed my improved FTP client, so win-win,… or something

Meanwhile a long term-goal for self-development stuff at work will involve some F#…

Friday, 28 September 2007

One small step…

A first part of the refactoring of the file system representation for the local files in the FTP client, removing all use of module os (to simply deployment by taking out all dependencies on FePy's extended library code), and encapsulating all references to the file data in a LocalFile class.

TODO list includes:

  • saving settings
  • hooking a remote file system class to the FTP client class
  • linking the FTP client and any low-level error feedback to the UI
  • Ensuring that file transfers but not directory listings get caught by the progress bar
  • Handling reconnects intelligently, including recording current directory state on the remote site

Drop here again.

Sunday, 16 September 2007

Coding formula

Normal service has resumed -- i.e. hobby coding is light again, as I'm deep into the dev cycle on the current project at work, the weather has improved since the height of the summer so I'm out at weekends, except I've been being distracted by my teeth, and have just been moping.

Tuesday, 28 August 2007

10 Minute refactor

After a long weekend in the garden...

module Com_ravnaandtines
  module Zlib
    class Adler32
      # largest prime smaller than 65536
      @@ADLER_BASE = 65521
    
      def initialize
        @value = 1
      end
      
      def update(buffer)
        if not buffer
          return @value
        end
        ## build up the checksum
        low = @value & 0xffff
        high = (@value >> 16) & 0xffff
        buffer.each do |x| 
          low += (x.to_i & 0xff)
          high += low
        end

        ## collapse into modular parts
        low %= @@ADLER_BASE
        high %= @@ADLER_BASE
        @value = (high << 16) | low      
      end
      
      def reset
        @value = 1
      end
      
    end
  end
end

and tweak the tests thus:

  def basic_test_engine(seq, expected)
    ## string to array
    ## otherwise expect an each method to yield integers
    if seq.respond_to? :unpack
      seq = seq.unpack("C*")
    end
    adler = Com_ravnaandtines::Zlib::Adler32.new()
    a = adler.update(seq)
    assert_equal(expected, a)
  end

  def test_boundary
    basic_test_engine(nil, 1)  
  end

That feels better. No special cases, no leakage of state. Looking at JZlib, most of the work will be in doing the encapsulation properly.

Next up, though, when time and energy combine, more on the IronPython FTP client.

Friday, 24 August 2007

Selection Factors

I had started porting CTClib to managed C++ to do an Iron<something> piecemeal conversion. But at the moment IronPython doesn't have a good deployment story, IronRuby isn't all there; and I still much prefer Java's UI model to WinForms or WPF… So what about JRuby -- familiar UI style and run from jar -- then?

The stumbling block as always is PhilZ's choice of deflate with a 2^13 bit window (as opposed to Zlib's fixed 2^15 bit window size for Ruby or java.util.zip) for compression. This was where I paused my first Java port -- JZlib which could do the job has appeared since I last looked, around the turn of the century. Even so, for sake of portability I've decided to bite the bullet, and do a minimal zlib/deflate implementation in Ruby for the purpose, to do something meaningful with the language, using JZlib as a guide. Inflate can, of course, have the larger window (as in current CTClib-C builds), and use the built-in version, be it the C version from native Ruby or JRuby's java.util.zip wrapper.

So, the easy bit first -- Adler 32 checksum…

module Com_ravnaandtines
  module Zlib
    # largest prime smaller than 65536
    ADLER_BASE = 65521
    # Adler32 checksum : takes a seed (usually 1), and a byte sequence, 
    # returns 32-bit integer
    def adler32(adler, buffer)
      if not buffer
        return 1
      end
      
      ## string to array
      ## otherwise expect an each method to yield integers
      if buffer.respond_to? :unpack
        buffer = buffer.unpack("C*")
      end
      
      ## build up the checksum
      low = adler & 0xffff
      high = (adler >> 16) & 0xffff
      buffer.each do |x| 
        low += (x.to_i & 0xff)
        high += low
      end

      ## collapse into modular parts
      low %= ADLER_BASE
      high %= ADLER_BASE
      (high << 16) | low
    end
  end
end

Test vectors for the unit tests had to be scavenged from the internet:

require 'test/unit'
require 'tinesware_zlib'
include Com_ravnaandtines::Zlib

class AdlerTest < Test::Unit::TestCase

  def basic_test_engine(seq, expected)
    a = Com_ravnaandtines::Zlib.adler32(1, seq)
    assert_equal(expected, a)
  end

  def test_boundary
    a = Com_ravnaandtines::Zlib.adler32(0, nil)
    assert_equal(1, a)    
  end

  def test_simple_0
    basic_test_engine("Mark Adler", 0x13070394)
  end
  
  def test_simple_1
    basic_test_engine("\x00\x01\x02\x03", 0x000e0007)
  end
 
  def test_simple_2
    basic_test_engine("\x00\x01\x02\x03\x04\x05\x06\x07",  0x005c001d)
  end

  def test_simple_3
    basic_test_engine("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 0x02b80079)
  end

  def test_simple_4
    basic_test_engine("\x41\x41\x41\x41", 0x028e0105)
  end

  def test_simple_5
    basic_test_engine("\x42\x42\x42\x42\x42\x42\x42\x42", 0x09500211)
  end

  def test_simple_6
    basic_test_engine("\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43", 0x23a80431)
  end

  class Vector #arrays filled with value = (byte) index
    def initialize(size)
      @size = size
    end
    def each
      index = 0
      while index < @size
        yield index & 0xff
        index += 1
      end
    end
  end

  def test_total
    index = 0
    results = [  486795068,
                1525910894,
                3543032800,
                2483946130,
                4150712693,
                3878123687,
                3650897945,
                1682829244,
                1842395054,
                 460416992,
                3287492690,
                 479453429,
                3960773095,
                2008242969,
                4130540683,
                1021367854,
                4065361952,
                2081116754,
                4033606837,
                1162071911 ]

    
    while index < 20
      size = 5*index + 1
      xx = Vector.new(1000*size)
      basic_test_engine(xx, results[index])
      index += 1
    end
  end

end

That was one evening. Now, how long will the rest of it take?