Total rewrite, uses hash tables for speed and low memory use.