/*
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
*/
#define DEBUG 0
#include <sys/times.h>
//FIXME comment the line below
//#define HAVE_RANDOM
// change the include to #include <bop.2/bop.h>
#include "bop.h"
typedef struct
{
BophHandle * hash ; // hash to store lines
unsigned long lineNum ; // line number to make all lines different
} LoadData ;
static int load( void * data, char * line, unsigned int length)
{
#define loadData ( (LoadData *) data )
// this function is called for each input line.
// put it in the hash
size_t allocSize ;
char * hashRecord ;
BophEntry * entry ; // stored hash entry
unsigned long * pNum ;
bopdEnter( ) ;
bopdTrace(" line <%s> length=%u\n", line, length ) ;
// prepend a line number to make all lines different
loadData->lineNum += 1 ;
allocSize = length + 2 + sizeof(unsigned long) ;
#ifndef HAVE_ALLOCA
bopdTrace( "use bopmMalloc size=%u\n", allocSize ) ;
hashRecord = bopmMalloc( allocSize) ;
#else
bopdTrace( "use alloca size=%u\n", allocSize ) ;
hashRecord = alloca( allocSize) ;
#endif
pNum = ( unsigned long * ) hashRecord ;
* pNum = loadData->lineNum ;
memcpy( hashRecord + sizeof(unsigned long),
line, length ) ;
* (hashRecord + allocSize - 2) = '\n' ;
* (hashRecord + allocSize - 1) = 0 ;
// put it in hash
entry = bophPut( loadData->hash, hashRecord, allocSize, NULL, 0, BOPH_PUT ) ;
if ( entry == NULL )
{
bopxAbort( "Cannot store in hash" ) ;
}
#ifndef HAVE_ALLOCA
// the record has been copied in the hash, free it
bopmFree( hashRecord ) ;
#endif
#undef loadData
bopdReturn( false ) ;
return( false ) ;
}
static int unload( void * data, BophEntry * entry )
{
// this function is called for each hash entry.
// output the line
char * line ;
bopdEnter( ) ;
// do not output the line number
line = ( (char *)bophGetKey( entry ) ) + sizeof(unsigned long) ;
fputs( line, (FILE *)data ) ;
bopdTrace( "fputs <%s>\n", line ) ;
bopdReturn( false ) ;
return( false ) ;
}
int
main( int argc, char * argv[] )
{
BophHandle * hash ;
char * fileName ;
unsigned int hashSize ;
LoadData loadData ;
bopmTrace ( ) ;
bopdEnter( ) ;
// get the filename argument
if ( argc < 2 )
{
fprintf( stderr, "bopshuffle: argument expected\n" ) ;
fprintf( stderr, "usage: bopshuffle filename\n" ) ;
exit( EXIT_FAILURE ) ;
}
fileName = argv[1] ;
// find a "random" hash size
// que vient faire Marignan dans cette histoire ?
hashSize = ( bopxRandom( ) % 8191 ) + 1515 ;
// create a hash
bopdTrace( "hash size %u\n", hashSize ) ;
hash = bophNew( NULL, "shuffle hash", hashSize, NULL, NULL ) ;
// load the file in the hash
loadData.hash = hash ;
loadData.lineNum = 0 ;
bopxScanLines( &loadData, fileName, load ) ;
// unload the hash on stdout
bophScan( stdout, hash, unload ) ;
// unusefully free the hash object
bophDelete ( NULL, hash ) ;
bopmMem( ) ;
bopdReturn( EXIT_SUCCESS ) ;
return( EXIT_SUCCESS ) ;
}