#ifndef DICT_H
#define DICT_H

#include <String.h>
#include <fstream.h>
#include <math.h>
#include "text.hh"
#include "perm.hh"

typedef int uint32;

#define THE_WRD(base,no) ((uint32*)base)[(no)>>5]
#define THE_BIT(no)      (1 << ((no) & 0x1f))           
#define SET_BIT(base,no) THE_WRD(base,no) |=  THE_BIT(no)
#define CLR_BIT(base,no) THE_WRD(base,no) &= ~THE_BIT(no)
#define GET_BIT(base,no) (THE_WRD(base,no) &  THE_BIT(no))

#define HASHBITS 24
#define HASHSIZE (1<<HASHBITS)
#define HASHMASK (HASHSIZE-1)


//==============================================================
// DICT - the class dict represents a dictionary aand provides
//        functions to compute the score of texts after decrypting
//        them with a permutation or a Vigenere key.
//==============================================================


class DICT
{
public:

    uint32 table[2][HASHSIZE/32];   /* double bloom filter */

    static uint32 hash1(PERM *p,char *string, int len)
        {
            uint32 sum = 0;

            while( len-- )
            {
                sum += sum << 7;
                sum ^= p->Translate(*string++);
            }

            return sum & HASHMASK;
        }

    static uint32 hash2(PERM *p,char *string, int len)
        {
            uint32 sum = 0;

            while( len-- )
            {
                sum += sum << 6;
                sum += p->Translate(*string++);
            }
            
            return sum & HASHMASK;
        }

    DICT(char *filename, int maxlength)
        {
            int j;
            PERM p;
            
            ifstream in(filename);
            if( !in)
                cerr << "cannot open: " << filename << endl;

            while( !in.eof() )
            {
                char buf[256];

                in.get(buf, sizeof(buf), '\n');
                in.get();   // read the newline
                
                //cout << "word: " << buf << endl;

                buf[maxlength] = 0;
                
                for(j=0; buf[j] != 0; j++ ) 
                    buf[j] = TEXT::char2num(buf[j]);
                    
                SET_BIT(table[0],hash1(&p,&buf[0],j));
                SET_BIT(table[1],hash2(&p,&buf[0],j));
            }
                   
        }
    
    int EvalTextPerm( TEXT *t, PERM *p, int weight, int maxlength)
        {
            int sum = 0;
            int i=0;
            while( i<t->Length() )
            {
                while( p->Translate(t->data[i]) == 0 &&  i<t->Length() )
                    i++;

                int j=i;
                while( p->Translate(t->data[j]) != 0 && j<t->Length() )
                    j++;

                int len = j-i;
                if( len > maxlength ) len = maxlength;
                
                if( GET_BIT(table[0],hash1(p,&t->data[i],len)) &&
                    GET_BIT(table[1],hash2(p,&t->data[i],len)))
                {
                    sum += weight*len;
                }
                
                i = j;
                
            }
            return sum;
        }

};


#endif 





























