summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/lz77_buffer
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/lz77_buffer')
-rw-r--r--ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_1.h263
-rw-r--r--ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_2.h504
-rw-r--r--ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_abstract.h210
-rw-r--r--ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_c.h169
4 files changed, 1146 insertions, 0 deletions
diff --git a/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_1.h b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_1.h
new file mode 100644
index 000000000..b93f0628d
--- /dev/null
+++ b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_1.h
@@ -0,0 +1,263 @@
+// 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_
+
diff --git a/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_2.h b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_2.h
new file mode 100644
index 000000000..f8d332784
--- /dev/null
+++ b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_2.h
@@ -0,0 +1,504 @@
+// 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_2_
+#define DLIB_LZ77_BUFFER_KERNEl_2_
+
+#include "lz77_buffer_kernel_abstract.h"
+#include "../algs.h"
+
+
+
+namespace dlib
+{
+
+ template <
+ typename sliding_buffer
+ >
+ class lz77_buffer_kernel_2
+ {
+ /*!
+ REQUIREMENTS ON sliding_buffer
+ sliding_buffer must be an implementation of sliding_buffer/sliding_buffer_kernel_abstract.h
+ and must be instantiated to contain unsigned char data
+
+ 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
+ buffer[i] == 0 for all valid i
+
+ nodes == an array of history_limit-3 nodes
+ id_table == an array of buffer.size() pointers
+ hash_table == an array of buffer.size() pointers and all are set to 0
+ mask == buffer.size() - 1
+ next_free_node == 0
+
+
+ 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]
+
+
+ hash_table[hash(a,b,c,d)] points to the head of a linked list.
+ Each node in this linked list tells the location in the buffer
+ of a string that begins with abcd or a string who's first four
+ letters have the same hash. The linked list is terminated by a
+ node with a null next pointer.
+
+ hash_table[i] == 0 if there is no linked list for this element of the hash
+ table.
+
+ each node in the hash table is allocated from the array nodes.
+ When adding a node to hash_table:
+ if (if all nodes aren't already in the hash_table) then
+ {
+ the next node to use is nodes[next_free_node].
+ }
+ else
+ {
+ recycle nodes from the hash_table itself. This works because
+ when we add new nodes we also have to remove nodes.
+ }
+
+ if (there is a node defined with an id of i) then
+ {
+ if (id_table[i] != 0) then
+ id_table[i]->next->id == i
+ else
+ hash_table[some_hash]->id == i
+ }
+ !*/
+
+ public:
+
+ lz77_buffer_kernel_2 (
+ unsigned long total_limit_,
+ unsigned long lookahead_limit_
+ );
+
+ virtual ~lz77_buffer_kernel_2 (
+ );
+
+ 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 unsigned long hash (
+ unsigned char a,
+ unsigned char b,
+ unsigned char c,
+ unsigned char d
+ ) const
+ /*!
+ ensures
+ - returns a hash of the 4 arguments and the hash is in the range
+ !*/
+ {
+ unsigned long B = b << 3;
+ unsigned long C = c << 6;
+ unsigned long D = d << 9;
+
+ unsigned long temp = a + B;
+ temp += C;
+ temp += D;
+
+ return (temp&mask); /**/
+ }
+
+ 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)
+ !*/
+
+
+
+ // member data
+ sliding_buffer buffer;
+ unsigned long lookahead_limit;
+ unsigned long history_limit;
+
+ struct node
+ {
+ unsigned long id;
+ node* next;
+ };
+
+ node** hash_table;
+ node* nodes;
+ node** id_table;
+ unsigned long next_free_node;
+ unsigned long mask;
+
+ unsigned long lookahead_size;
+ unsigned long history_size;
+
+
+ // restricted functions
+ lz77_buffer_kernel_2(lz77_buffer_kernel_2<sliding_buffer>&); // copy constructor
+ lz77_buffer_kernel_2<sliding_buffer>& operator=(lz77_buffer_kernel_2<sliding_buffer>&); // assignment operator
+ };
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+ // member function definitions
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename sliding_buffer
+ >
+ lz77_buffer_kernel_2<sliding_buffer>::
+ lz77_buffer_kernel_2 (
+ 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_;
+
+ nodes = new node[history_limit-3];
+
+ try { id_table = new node*[buffer.size()]; }
+ catch (...) { delete [] nodes; throw; }
+
+ try { hash_table = new node*[buffer.size()]; }
+ catch (...) { delete [] id_table; delete [] nodes; throw; }
+
+ mask = buffer.size()-1;
+ next_free_node = 0;
+
+
+ node** start = hash_table;
+ node** end = hash_table + buffer.size();
+ while (start != end)
+ {
+ *start = 0;
+ ++start;
+ }
+
+ for (unsigned long i = 0; i < buffer.size(); ++i)
+ buffer[i] = 0;
+
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename sliding_buffer
+ >
+ lz77_buffer_kernel_2<sliding_buffer>::
+ ~lz77_buffer_kernel_2 (
+ )
+ {
+ delete [] nodes;
+ delete [] hash_table;
+ delete [] id_table;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename sliding_buffer
+ >
+ void lz77_buffer_kernel_2<sliding_buffer>::
+ clear(
+ )
+ {
+ lookahead_size = 0;
+ history_size = 0;
+ next_free_node = 0;
+
+ node** start = hash_table;
+ node** end = hash_table + buffer.size();
+ while (start != end)
+ {
+ *start = 0;
+ ++start;
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename sliding_buffer
+ >
+ void lz77_buffer_kernel_2<sliding_buffer>::
+ shift_buffer (
+ unsigned long N
+ )
+ {
+ unsigned long old_history_size = history_size;
+ unsigned long temp = history_size+N;
+ unsigned long new_nodes; // the number of nodes to pull from the nodes array
+ unsigned long recycled_nodes; // the number of nodes to pull from hash_table
+ lookahead_size -= N;
+ if (temp <= history_limit)
+ {
+ if (history_size <= 3)
+ {
+ if ((3-history_size) >= N)
+ new_nodes = 0;
+ else
+ new_nodes = N - (3-history_size);
+ }
+ else
+ {
+ new_nodes = N;
+ }
+
+ recycled_nodes = 0;
+ history_size = temp;
+ }
+ else
+ {
+ if (history_size != history_limit)
+ {
+ new_nodes = history_limit - history_size;
+ recycled_nodes = temp - history_limit;
+ history_size = history_limit;
+ }
+ else
+ {
+ new_nodes = 0;
+ recycled_nodes = N;
+ }
+ }
+
+ unsigned long i = lookahead_limit + 2;
+
+ // if there are any "new" nodes to add to the hash table
+ if (new_nodes != 0)
+ {
+ unsigned long stop = i - new_nodes;
+ for (; i > stop; --i)
+ {
+ nodes[next_free_node].next = 0;
+ nodes[next_free_node].id = buffer.get_element_id(i);
+ id_table[nodes[next_free_node].id] = 0;
+
+ unsigned long new_hash = hash(buffer[i],buffer[i-1],buffer[i-2],buffer[i-3]);
+
+ if (hash_table[new_hash] != 0)
+ id_table[hash_table[new_hash]->id] = &nodes[next_free_node];
+ nodes[next_free_node].next = hash_table[new_hash];
+ hash_table[new_hash] = &nodes[next_free_node];
+
+ ++next_free_node;
+ }
+ } // if (new_nodes != 0)
+
+
+
+ unsigned long stop = i - recycled_nodes;
+ unsigned long old = old_history_size-1+lookahead_limit;
+ for (; i > stop; --i)
+ {
+ // find the next node to recycle in hash_table
+ node* recycled_node;
+
+
+ unsigned long old_id = buffer.get_element_id(old);
+
+ // find the node with id old_id
+ if (id_table[old_id] == 0)
+ {
+ unsigned long old_hash = hash(buffer[old],buffer[old-1],buffer[old-2],buffer[old-3]);
+ recycled_node = hash_table[old_hash];
+
+ // fill the gap left by removing this node
+ hash_table[old_hash] = recycled_node->next;
+ }
+ else
+ {
+ recycled_node = id_table[old_id]->next;
+
+ // fill the gap left by removing this node
+ id_table[old_id]->next = recycled_node->next;
+ }
+
+ --old;
+
+
+
+
+
+
+ recycled_node->next = 0;
+ recycled_node->id = buffer.get_element_id(i);
+ id_table[recycled_node->id] = 0;
+
+ unsigned long new_hash = hash(buffer[i],buffer[i-1],buffer[i-2],buffer[i-3]);
+
+ if (hash_table[new_hash] != 0)
+ id_table[hash_table[new_hash]->id] = recycled_node;
+
+ recycled_node->next = hash_table[new_hash];
+ hash_table[new_hash] = recycled_node;
+
+ } // for (; i > stop; --i)
+
+
+
+
+ buffer.rotate_left(N);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename sliding_buffer
+ >
+ void lz77_buffer_kernel_2<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_2<sliding_buffer>::
+ find_match (
+ unsigned long& index,
+ unsigned long& length,
+ unsigned long min_match_length
+ )
+ {
+ 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
+
+
+ const unsigned long hash_value = hash(lookahead_buffer(0),
+ lookahead_buffer(1),
+ lookahead_buffer(2),
+ lookahead_buffer(3)
+ );
+
+
+
+ node* temp = hash_table[hash_value];
+ while (temp != 0)
+ {
+ // current position in the history buffer
+ unsigned long hpos = buffer.get_element_index(temp->id)-lookahead_limit;
+ // current position in the lookahead buffer
+ unsigned long lpos = 0;
+
+ // find length of this match
+ while (history_buffer(hpos) == lookahead_buffer(lpos))
+ {
+ ++lpos;
+ if (hpos == 0)
+ break;
+ --hpos;
+ if (lpos == lookahead_size)
+ break;
+ }
+
+ if (lpos > match_length)
+ {
+ match_length = lpos;
+ match_index = buffer.get_element_index(temp->id)-lookahead_limit;
+ // if this is the longest possible match then stop looking
+ if (lpos == lookahead_limit)
+ break;
+ }
+
+
+ temp = temp->next;
+ } // while (temp != 0)
+
+
+
+
+ // 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_2_
+
diff --git a/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_abstract.h b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_abstract.h
new file mode 100644
index 000000000..942b4e3c2
--- /dev/null
+++ b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_abstract.h
@@ -0,0 +1,210 @@
+// Copyright (C) 2004 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#undef DLIB_LZ77_BUFFER_KERNEl_ABSTRACT_
+#ifdef DLIB_LZ77_BUFFER_KERNEl_ABSTRACT_
+
+#include "../algs.h"
+
+namespace dlib
+{
+
+ class lz77_buffer
+ {
+ /*!
+ INITIAL VALUE
+ get_history_buffer_limit() == defined by constructor arguments
+ get_lookahead_buffer_limit() == defined by constructor arguments
+ get_history_buffer_size() == 0
+ get_lookahead_buffer_size() == 0
+
+
+ WHAT THIS OBJECT REPRESENTS
+ This object represents a pair of buffers (history and lookahead buffers)
+ used during lz77 style compression.
+
+ It's main function is to search the history buffer for long strings which
+ match the contents (or a part of the contents) of the lookahead buffer.
+
+
+ HISTORY AND LOOKAHEAD BUFFERS
+ The buffers have the following structure:
+ | history buffer | lookahead buffer | <-- contents of buffers
+ | ...9876543210 | 0123456789... | <-- index numbers
+
+ So this means that history_buffer(0) == 'r', history_buffer(1) == 'e'
+ and so on. And lookahead_buffer(0) == 'l', lookahead_buffer(1) == 'o'
+ and so on.
+
+
+ What shift_buffers() does in english:
+ This function just means that the buffers have their contents shifted
+ left by N elements and that elements shifted out of the lookahead buffer
+ go into the history buffer. An example will make it clearer.
+
+ Suppose that we have the following buffers before we apply shift_buffers()
+ history_buffer() == "hey" and
+ lookahead_buffer() == "lookahead buffer"
+ And in the same format as the above diagram it would be
+ | hey | lookahead buffer | <-- contents of buffers
+ | 210 | 0123456789... | <-- index numbers
+
+ Applying shift_buffers(4) will give
+ lookahead_buffer() == "ahead buffer"
+ history_buffer() == "heylook" or "eylook" or "ylook" or "look"
+
+ You might be wondering why the history_buffer can resize itself in
+ such a nondeterministic way. It is just to allow a lot of freedom in the
+ implementations of this object.
+ !*/
+
+ public:
+
+ lz77_buffer (
+ unsigned long total_limit,
+ unsigned long lookahead_limit
+ );
+ /*!
+ requires
+ - 6 < total_limit < 32
+ - 15 < lookahead_limit <= 2^(total_limit-2)
+ ensures
+ - #*this is properly initialized
+ - #get_history_buffer_limit() == 2^total_limit - lookahead_limit
+ - #get_lookahead_buffer_limit() == lookahead_limit
+ throws
+ - std::bad_alloc
+ !*/
+
+ virtual ~lz77_buffer (
+ );
+ /*!
+ ensures
+ - any resources associated with *this have been released
+ !*/
+
+ void clear(
+ );
+ /*!
+ ensures
+ - #*this has its initial value
+ throws
+ - std::bad_alloc
+ if this exception is thrown then #*this is unusable
+ until clear() is called and succeeds
+ !*/
+
+ void shift_buffers (
+ unsigned long N
+ );
+ /*!
+ requires
+ - N <= get_lookahead_buffer_size()
+ ensures
+ - #get_lookahead_buffer_size() == get_lookahead_buffer_size() - N
+ - #get_history_buffer_size() >= N
+ - #get_history_buffer_size() <= get_history_buffer_size()+N
+ - #get_history_buffer_size() <= get_history_buffer_limit()
+ - for all i where 0 <= i < N:
+ #history_buffer(N-1-i) == lookahead_buffer(i)
+ - for all i where 0 <= i < #get_history_buffer_size()-N:
+ #history_buffer(N+i) == history_buffer(i)
+ - for all i where 0 <= i < #get_lookahead_buffer_size()
+ #lookahead_buffer(i) == lookahead_buffer(N+i)
+ !*/
+
+ void add (
+ unsigned char symbol
+ );
+ /*!
+ ensures
+ - if (get_lookahead_buffer_size() == get_lookahead_buffer_limit()) then
+ - performs shift_buffers(1)
+ - #lookahead_buffer(get_lookahead_buffer_limit()-1) == symbol
+ - #get_lookahead_buffer_size() == get_lookahead_buffer_size()
+ - else
+ - #lookahead_buffer(get_lookahead_buffer_size()) == symbol
+ - #get_lookahead_buffer_size() == get_lookahead_buffer_size() + 1
+ throws
+ - std::bad_alloc
+ if this exception is thrown then #*this is unusable
+ until clear() is called and succeeds
+ !*/
+
+ void find_match (
+ unsigned long& index,
+ unsigned long& length,
+ unsigned long min_match_length
+ );
+ /*!
+ ensures
+ - if (#length != 0) then
+ - #length >= min_match_length
+ - for all i where 0 <= i < #length:
+ history_buffer(#index-i) == lookahead_buffer(i)
+ - performs shift_buffers(#length)
+ throws
+ - std::bad_alloc
+ if this exception is thrown then #*this is unusable
+ until clear() is called and succeeds
+ !*/
+
+ unsigned long get_history_buffer_limit (
+ ) const;
+ /*!
+ ensures
+ - returns the max number of symbols that can fit in the history buffer
+ !*/
+
+ unsigned long get_lookahead_buffer_limit (
+ ) const;
+ /*!
+ ensures
+ - returns the max number of symbols that can fit in the lookahead buffer
+ !*/
+
+ unsigned long get_history_buffer_size (
+ ) const;
+ /*!
+ ensures
+ - returns the number of symbols currently in the history buffer
+ !*/
+
+ unsigned long get_lookahead_buffer_size (
+ ) const;
+ /*!
+ ensures
+ - returns the number of symbols currently in the lookahead buffer
+ !*/
+
+ unsigned char lookahead_buffer (
+ unsigned long index
+ ) const;
+ /*!
+ requires
+ - index < get_lookahead_buffer_size()
+ ensures
+ - returns the symbol in the lookahead buffer at location index
+ !*/
+
+ unsigned char history_buffer (
+ unsigned long index
+ ) const;
+ /*!
+ requires
+ - index < get_history_buffer_size()
+ ensures
+ - returns the symbol in the history buffer at location index
+ !*/
+
+
+ private:
+
+ // restricted functions
+ lz77_buffer(lz77_buffer&); // copy constructor
+ lz77_buffer& operator=(lz77_buffer&); // assignment operator
+
+ };
+}
+
+#endif // DLIB_LZ77_BUFFER_KERNEl_ABSTRACT_
+
diff --git a/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_c.h b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_c.h
new file mode 100644
index 000000000..704763ad1
--- /dev/null
+++ b/ml/dlib/dlib/lz77_buffer/lz77_buffer_kernel_c.h
@@ -0,0 +1,169 @@
+// Copyright (C) 2003 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_LZ77_BUFFER_KERNEl_C_
+#define DLIB_LZ77_BUFFER_KERNEl_C_
+
+#include "lz77_buffer_kernel_abstract.h"
+#include "../algs.h"
+#include "../assert.h"
+#include <iostream>
+
+namespace dlib
+{
+
+ template <
+ typename lz77_base
+ >
+ class lz77_buffer_kernel_c : public lz77_base
+ {
+
+ public:
+ lz77_buffer_kernel_c (
+ unsigned long total_limit,
+ unsigned long lookahead_limit
+ );
+
+ unsigned char lookahead_buffer (
+ unsigned long index
+ ) const;
+
+ unsigned char history_buffer (
+ unsigned long index
+ ) const;
+
+ void shift_buffers (
+ unsigned long N
+ );
+
+
+
+ unsigned long make_safe (
+ unsigned long total_limit,
+ unsigned long lookahead_limit
+ )
+ /*!
+ ensures
+ - if ( 6 < total_limit < 32 &&
+ 15 < lookahead_limit <= 2^(total_limit-2)
+ ) then
+ - returns total_limit
+ - else
+ - throws due to failed CASSERT
+ !*/
+ {
+ unsigned long exp_size = (total_limit!=0)?total_limit-2:0;
+ unsigned long two_pow_total_limit_minus_2 = 1;
+ while (exp_size != 0)
+ {
+ --exp_size;
+ two_pow_total_limit_minus_2 <<= 1;
+ }
+
+ // make sure requires clause is not broken
+ DLIB_CASSERT( 6 < total_limit && total_limit < 32 &&
+ 15 < lookahead_limit && lookahead_limit <= two_pow_total_limit_minus_2,
+ "\tlz77_buffer::lz77_buffer(unsigned long,unsigned long)"
+ << "\n\ttotal_limit must be in the range 7 to 31 and \n\tlookahead_limit in the range 15 to 2^(total_limit-2)"
+ << "\n\tthis: " << this
+ << "\n\ttotal_limit: " << total_limit
+ << "\n\tlookahead_limit: " << lookahead_limit
+ );
+
+ return total_limit;
+ }
+
+ };
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+ // member function definitions
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename lz77_base
+ >
+ void lz77_buffer_kernel_c<lz77_base>::
+ shift_buffers (
+ unsigned long N
+ )
+ {
+ // make sure requires clause is not broken
+ DLIB_CASSERT( N <= this->get_lookahead_buffer_size(),
+ "\tvoid lz77_buffer::shift_buffers(unsigned long)"
+ << "\n\tN must be <= the number of chars in the lookahead buffer"
+ << "\n\tthis: " << this
+ << "\n\tget_lookahead_buffer_size(): " << this->get_lookahead_buffer_size()
+ << "\n\tN: " << N
+ );
+
+ // call the real function
+ lz77_base::shift_buffers(N);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename lz77_base
+ >
+ unsigned char lz77_buffer_kernel_c<lz77_base>::
+ history_buffer (
+ unsigned long index
+ ) const
+ {
+ // make sure requires clause is not broken
+ DLIB_CASSERT( index < this->get_history_buffer_size(),
+ "\tunsigned char lz77_buffer::history_buffer(unsigned long) const"
+ << "\n\tindex must be in the range 0 to get_history_buffer_size()-1"
+ << "\n\tthis: " << this
+ << "\n\tget_history_buffer_size(): " << this->get_history_buffer_size()
+ << "\n\tindex: " << index
+ );
+
+ // call the real function
+ return lz77_base::history_buffer(index);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename lz77_base
+ >
+ unsigned char lz77_buffer_kernel_c<lz77_base>::
+ lookahead_buffer (
+ unsigned long index
+ ) const
+ {
+ // make sure requires clause is not broken
+ DLIB_CASSERT( index < this->get_lookahead_buffer_size(),
+ "\tunsigned char lz77_buffer::lookahead_buffer(unsigned long) const"
+ << "\n\tindex must be in the range 0 to get_lookahead_buffer_size()-1"
+ << "\n\tthis: " << this
+ << "\n\tget_lookahead_buffer_size(): " << this->get_lookahead_buffer_size()
+ << "\n\tindex: " << index
+ );
+
+ // call the real function
+ return lz77_base::lookahead_buffer(index);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename lz77_base
+ >
+ lz77_buffer_kernel_c<lz77_base>::
+ lz77_buffer_kernel_c (
+ unsigned long total_limit,
+ unsigned long lookahead_limit
+ ) :
+ lz77_base(make_safe(total_limit,lookahead_limit),lookahead_limit)
+ {
+ }
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_LZ77_BUFFER_KERNEl_C_
+