/*
    This file is part of BOP.
    Copyright (C) 2004  Patrick Davalan

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    The GNU General Public License text is also available at
    http://www.gnu.org/
    or on the Copyright holder web site :
    http://patrick.davalan.free.fr/gnu-gpl.html
*/

// substitute #include <bop.h> when bop is installed

#define DEBUG 0

// change the include to #include <bop.2/bop.h>
#include "bop.h"
#include "bopmakeh.h"


//
// This function fills a hash from the the lines of a file
// It is intended to serve as en example to use the bop API.
//
// This function expect that each line of the input file is a word
// followed by a new-line, what is a word is up to you.
// 


int
bopMakeH(BophHandle *hash, char * wordFileName)
{
    // Read a file and for each word which appears in, update a count.
    // the first time the word appears, it is put in a hash 
    // with a count of 1, the next times, this count is incremented.
    // 
    // return true or abort on failure.
    //
    FILE * wordFile ;
#define BUFSIZE 4096    
    char name[BUFSIZE] ;
    BophEntry * hEntry ;
    unsigned long wordRead = 0 ;
    unsigned long wordAdded = 0 ;
    
    bopdEnter( ) ;
    bopdTrace( "hash at %p\n", hash ) ;

    wordFile = bopxFopen( wordFileName, "r" ) ; // fopen or abort

    // for each line of the input file
    for ( ; fgets( name, BUFSIZE, wordFile ) != NULL ; )
    { 
        size_t len = 0 ;
        unsigned long count = 0 ;
        unsigned long * hCount ;
        
        wordRead++ ;
        len = strlen(name) ;
        *( name + len - 1 ) = 0 ;   // erase \n
        // len is the string length + 1 for the 0 char which we want to be
        // stored in the hash
            
        // here we will use the powerfulness of the flag BOPH_TEST :
        // if the entry is not in the hash, the entry will be added 
        // to the hash and returned.
        // if this entry is in the hash, the already existing entry
        // will be returned.
        // Anyway the entry, added or not, will be returned
        // 
        // This is better than getting an entry, add a new one if not
        // found or replace it, which implies 2 access to the entry.
        // 
            
        hEntry = bophPut(hash, name, len, &count, sizeof(count), BOPH_TEST ) ;
        // 
        // We have to increment the count of an existing entry or
        // set the count of a new entry to 1.
        // thus, we tried to add an entry with a zero count so that,
        // was the entry already in the hash or not, we just have to
        // increment the count afterward.

        // get the address of count
        hCount = (unsigned long *) bophGetData( hEntry ) ;
        
        if ( (*hCount) == 0 ) wordAdded++ ;

        // the entry returned is the address of the entry in the hash,
        // not a copy. So, we can update it in place.
        (*hCount)++ ;   // update the entry in place
    }

    bopdTrace( "words added :    %ld / ", wordAdded );
    bopdTrace( "words read  :    %ld\n", wordRead );
    
    bopxFclose( wordFile ) ;

    bopdReturn( true ) ;
    return( true ) ;
}