// Copyright (C) 2004 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_LZ77_BUFFER_KERNEl_1_
#define DLIB_LZ77_BUFFER_KERNEl_1_
#include "lz77_buffer_kernel_abstract.h"
#include "../algs.h"
namespace dlib
{
template <
typename sliding_buffer
>
class lz77_buffer_kernel_1
{
/*!
REQUIREMENTS ON sliding_buffer
sliding_buffer must be an implementation of sliding_buffer/sliding_buffer_kernel_abstract.h
INITIAL VALUE
history_limit == defined by constructor arguments
lookahead_limit == defined by constructor arguments
history_size == 0
lookahead_size == 0
buffer.size() == history_limit + lookahead_limit
CONVENTION
history_limit == get_history_buffer_limit()
lookahead_limit == get_lookahead_buffer_limit()
history_size == get_history_buffer_size()
lookahead_limit == get_lookahead_buffer_size()
buffer.size() == history_limit + lookahead_limit
lookahead_buffer(i) == buffer[lookahead_limit-1-i]
history_buffer(i) == buffer[lookahead_limit+i]
!*/
public:
lz77_buffer_kernel_1 (
unsigned long total_limit_,
unsigned long lookahead_limit_
);
virtual ~lz77_buffer_kernel_1 (
) {}
void clear(
);
void add (
unsigned char symbol
);
void find_match (
unsigned long& index,
unsigned long& length,
unsigned long min_match_length
);
inline unsigned long get_history_buffer_limit (
) const { return history_limit; }
inline unsigned long get_lookahead_buffer_limit (
) const { return lookahead_limit; }
inline unsigned long get_history_buffer_size (
) const { return history_size; }
inline unsigned long get_lookahead_buffer_size (
) const { return lookahead_size; }
inline unsigned char lookahead_buffer (
unsigned long index
) const { return buffer[lookahead_limit-1-index]; }
inline unsigned char history_buffer (
unsigned long index
) const { return buffer[lookahead_limit+index]; }
inline void shift_buffers (
unsigned long N
) { shift_buffer(N); }
private:
inline void shift_buffer (
unsigned long N
)
/*!
requires
- N <= lookahead_size
ensuers
- #lookahead_size == lookahead_size - N
- if (history_size+N < history_limit) then
- #history_size == history_size+N
- else
- #history_size == history_limit
- for all i where 0 <= i < N:
#history_buffer(N-1-i) == lookahead_buffer(i)
- for all i where 0 <= i < #history_size-N:
#history_buffer(N+i) == history_buffer(i)
- for all i where 0 <= i < #lookahead_size
#lookahead_buffer(i) == lookahead_buffer(N+i)
!*/
{
unsigned long temp = history_size+N;
buffer.rotate_left(N);
lookahead_size -= N;
if (temp < history_limit)
history_size = temp;
else
history_size = history_limit;
}
// member data
sliding_buffer buffer;
unsigned long lookahead_limit;
unsigned long history_limit;
unsigned long lookahead_size;
unsigned long history_size;
// restricted functions
lz77_buffer_kernel_1(lz77_buffer_kernel_1<sliding_buffer>&); // copy constructor
lz77_buffer_kernel_1<sliding_buffer>& operator=(lz77_buffer_kernel_1<sliding_buffer>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename sliding_buffer
>
lz77_buffer_kernel_1<sliding_buffer>::
lz77_buffer_kernel_1 (
unsigned long total_limit_,
unsigned long lookahead_limit_
) :
lookahead_size(0),
history_size(0)
{
buffer.set_size(total_limit_);
lookahead_limit = lookahead_limit_;
history_limit = buffer.size() - lookahead_limit_;
}
// ----------------------------------------------------------------------------------------
template <
typename sliding_buffer
>
void lz77_buffer_kernel_1<sliding_buffer>::
clear(
)
{
lookahead_size = 0;
history_size = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename sliding_buffer
>
void lz77_buffer_kernel_1<sliding_buffer>::
add (
unsigned char symbol
)
{
if (lookahead_size == lookahead_limit)
{
shift_buffer(1);
}
buffer[lookahead_limit-1-lookahead_size] = symbol;
++lookahead_size;
}
// ----------------------------------------------------------------------------------------
template <
typename sliding_buffer
>
void lz77_buffer_kernel_1<sliding_buffer>::
find_match (
unsigned long& index,
unsigned long& length,
unsigned long min_match_length
)
{
unsigned long hpos = history_size; // current position in the history buffer
unsigned long lpos = 0; // current position in the lookahead buffer
unsigned long match_length = 0; // the length of the longest match we find
unsigned long match_index = 0; // the index of the longest match we find
// try to find a match
while (hpos != 0)
{
--hpos;
// if we are finding a match
if (history_buffer(hpos) == lookahead_buffer(lpos))
{
++lpos;
// if we have found a match that is as long as the lookahead buffer
// then we are done
if (lpos == lookahead_size)
break;
}
// else if we found the end of a match
else if (lpos > 0)
{
// if this match is longer than the last match we saw
if (lpos > match_length)
{
match_length = lpos;
match_index = hpos + lpos;
}
lpos = 0;
}
} // while (hpos != 0)
// if we found a match at the end of the loop that is greater than
// the match in match_index
if (lpos > match_length)
{
match_length = lpos;
match_index = hpos + lpos - 1;
}
// if we found a match that was long enough then report it
if (match_length >= min_match_length)
{
shift_buffer(match_length);
index = match_index;
length = match_length;
}
else
{
length = 0;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_LZ77_BUFFER_KERNEl_1_