Blame |
Last modification |
View Log
| Download
| RSS feed
#include <stdio.h>
#include <stdlib.h>
#include "mhmt-types.h"
#include "mhmt-globals.h"
#include "mhmt-tb.h"
// entry for twobyters search and add
struct tb_chain
* tb_entry
[65536];
struct tb_chain
* tb_free
; // linked list of freed tb_chain entries - NULL at the beginning
struct tb_bunch
* tb_bunches
; // all allocated bunches as linked list
void init_tb
(void)
{
ULONG i
;
tb_free
=NULL
; // init linked list of free tb_chain elements
tb_bunches
=NULL
; // no bunches already allocated
for(i
=0;i
<65536;i
++) // init array of 2-byte match pointers
{
tb_entry
[i
]=NULL
;
}
}
void free_tb
(void)
{
// free all allocated bunches
struct tb_bunch
* tbtmp
;
while( tb_bunches
)
{
tbtmp
=tb_bunches
;
tb_bunches
=tb_bunches
->next
;
free( tbtmp
);
}
}
// addw new twobyter:
// index=(prev<<8)+curr - index into tb_entry,
// position - position in input file for 'curr' byte
// returns zero if any error (cant allocate mem), otherwise 1
ULONG add_tb
(UWORD index
, OFFSET position
)
{
struct tb_chain
* newtb
;
newtb
=get_free_tb
();
if( !newtb
)
{ // no free elements
if( (OFFSET
)(position
+wrk.
prelen) > (OFFSET
)wrk.
maxwin ) // if there could be enough tbs to try to flush
{
// try to flush current chain
cutoff_tb_chain
(index
,position
);
}
newtb
=get_free_tb
();
if( !newtb
)
{ // nothing free - allocate new bunch
if( !add_bunch_of_tb
() )
{
return 0;
}
newtb
=get_free_tb
(); // here is no chance to fail!... hopefully...
}
}
newtb
->pos
=position
-1; // points to the first byte of given two bytes
newtb
->next
=tb_entry
[index
];
tb_entry
[index
]=newtb
;
return 1;
}
// shorten given twobyter chain to have only actual (<wrk.maxwin old) elements, giving some free elements to reuse
void cutoff_tb_chain
(UWORD index
,OFFSET position
)
{
struct tb_chain
* curr
, * prev
;
curr
=tb_entry
[index
];
if( !curr
) return; // if nothing to remove
// see if we should delete some elements after first element in the given chain
prev
=curr
;
curr
=curr
->next
;
while( curr
)
{
if( (position
-(curr
->pos
)) > (OFFSET
)wrk.
maxwin ) // found some old element: delete rest of chain along with it
{
// find end of chain
while( curr
->next
)
{
curr
= curr
->next
;
}
// now curr - last chain element, prev->next - beginning of orphaned chain
// add orphaned chain to free list
curr
->next
= tb_free
;
tb_free
= prev
->next
;
prev
->next
= NULL
; // cut off chain
break;
}
else
{
prev
=curr
;
curr
=curr
->next
;
}
}
// delete first (entry) element in chain if needed (in this case, all subsequent els are already deleted)
curr
=tb_entry
[index
];
if( (position
-(curr
->pos
)) > (OFFSET
)wrk.
maxwin )
{
tb_entry
[index
] = NULL
;
curr
->next
=tb_free
; // element goes to free list
tb_free
=curr
;
}
}
// adds new bunch of TBs when needed
// zero - error
ULONG add_bunch_of_tb
(void)
{
ULONG i
;
struct tb_bunch
* newbunch
;
// alloc new bunch
newbunch
=(struct tb_bunch
*)malloc( sizeof(struct tb_bunch
) );
if( !newbunch
) return 0;
// link every twobyter into one list
for(i
=0;i
<(BUNCHSIZE
-1);i
++)
{
newbunch
->bunch
[i
].
next=&(newbunch
->bunch
[i
+1]);
}
// add this list to the free list
newbunch
->bunch
[BUNCHSIZE
-1].
next=tb_free
;
tb_free
=&(newbunch
->bunch
[0]);
// add bunch to bunches list
newbunch
->next
=tb_bunches
;
tb_bunches
=newbunch
;
return 1;
}
// find free tb, if any, otherwise NULL
struct tb_chain
* get_free_tb
(void)
{
struct tb_chain
* newtb
;
if( tb_free
)
{
newtb
=tb_free
;
tb_free
=tb_free
->next
;
return newtb
;
}
else
{
return NULL
;
}
}