[SCM] Samba Shared Repository - branch v4-0-test updated - release-4-0-0alpha5-454-g1432a96

Stefan Metzmacher metze at samba.org
Sun Sep 7 18:49:53 GMT 2008


The branch, v4-0-test has been updated
       via  1432a96d37e367d9d97d48b69c6f16351a9ad066 (commit)
       via  fd84c5a08f7e8d6402e5f68eede546eb092d22aa (commit)
       via  b36056aac3f55587d2b3e7b66feea8173dbc67f0 (commit)
       via  ee505df3742dac0af8eec8b9b27d1e1f5ef54ca9 (commit)
      from  40b71bbd718f6dee70c0611e527f55c56623dea6 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit 1432a96d37e367d9d97d48b69c6f16351a9ad066
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Aug 20 22:12:51 2008 +0200

    ndr_compression: add XPRESS compression support
    
    metze

commit fd84c5a08f7e8d6402e5f68eede546eb092d22aa
Author: Matthieu Suiche <matt at msuiche.net>
Date:   Thu Jul 10 09:31:43 2008 +0000

    lzxpress: Import of lzxpress compression
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit b36056aac3f55587d2b3e7b66feea8173dbc67f0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sun Sep 7 18:52:29 2008 +0200

    ndr_compression: fix the build after lzxpress_decompress() prototype change
    
    metze

commit ee505df3742dac0af8eec8b9b27d1e1f5ef54ca9
Author: Matthieu Suiche <matt at msuiche.net>
Date:   Thu Jul 10 09:31:43 2008 +0000

    lzxpress: fix for decompression...
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source/lib/compression/lzxpress.c   |  206 +++++++++++++++++++++++++++++++---
 source/lib/compression/lzxpress.h   |   11 ++-
 source/librpc/ndr/ndr_compression.c |   62 ++++++++++-
 3 files changed, 256 insertions(+), 23 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/lib/compression/lzxpress.c b/source/lib/compression/lzxpress.c
index 5063051..0abbfc4 100644
--- a/source/lib/compression/lzxpress.c
+++ b/source/lib/compression/lzxpress.c
@@ -32,7 +32,6 @@
  *
  */
 
-#include "includes.h"
 #include "replace.h"
 #include "lzxpress.h"
 
@@ -57,10 +56,184 @@
 ))
 #endif
 
-static uint32_t xpress_decompress(uint8_t *input,
-				uint32_t input_size,
-				uint8_t *output,
-				uint32_t output_size)
+ssize_t lzxpress_compress(const uint8_t *uncompressed,
+			  uint32_t uncompressed_size,
+			  uint8_t *compressed,
+			  uint32_t max_compressed_size)
+{
+	uint32_t uncompressed_pos, compressed_pos, byte_left;
+	uint32_t max_offset, best_offset;
+	int32_t offset;
+	uint32_t max_len, len, best_len;
+	const uint8_t *str1, *str2;
+	uint32_t indic;
+	uint8_t *indic_pos;
+	uint32_t indic_bit, nibble_index;
+
+	uint32_t metadata_size;
+	uint16_t metadata;
+	uint16_t *dest;
+
+	if (!uncompressed_size) {
+		return 0;
+	}
+
+	uncompressed_pos = 0;
+	indic = 0;
+	compressed_pos = sizeof(uint32_t);
+	indic_pos = &compressed[0];
+
+	byte_left = uncompressed_size;
+	indic_bit = 0;
+	nibble_index = 0;
+
+	if (uncompressed_pos > XPRESS_BLOCK_SIZE)
+		return 0;
+
+	do {
+		bool found = false;
+
+		max_offset = uncompressed_pos;
+
+		str1 = &uncompressed[uncompressed_pos];
+
+		best_len = 2;
+		best_offset = 0;
+
+		max_offset = MIN(0x1FFF, max_offset);
+
+		/* search for the longest match in the window for the lookahead buffer */
+		for (offset = 1; (uint32_t)offset <= max_offset; offset++) {
+			str2 = &str1[-offset];
+
+			/* maximum len we can encode into metadata */
+			max_len = MIN((255 + 15 + 7 + 3), byte_left);
+
+			for (len = 0; (len < max_len) && (str1[len] == str2[len]); len++);
+
+			/*
+			 * We check if len is better than the value found before, including the
+			 * sequence of identical bytes
+			 */
+			if (len > best_len) {
+				found = true;
+				best_len = len;
+				best_offset = offset;
+			}
+		}
+
+		if (found) {
+			metadata_size = 0;
+			dest = (uint16_t *)&compressed[compressed_pos];
+
+			if (best_len < 10) {
+				/* Classical meta-data */
+				metadata = (uint16_t)(((best_offset - 1) << 3) | (best_len - 3));
+				dest[metadata_size / sizeof(uint16_t)] = metadata;
+				metadata_size += sizeof(uint16_t);
+			} else {
+				metadata = (uint16_t)(((best_offset - 1) << 3) | 7);
+				dest[metadata_size / sizeof(uint16_t)] = metadata;
+				metadata_size = sizeof(uint16_t);
+
+				if (best_len < (15 + 7 + 3)) {
+					/* Shared byte */
+					if (!nibble_index) {
+						compressed[compressed_pos + metadata_size] = (best_len - (3 + 7)) & 0xF;
+						metadata_size += sizeof(uint8_t);
+					} else {
+						compressed[nibble_index] &= 0xF;
+						compressed[nibble_index] |= (best_len - (3 + 7)) * 16;
+					}
+				} else if (best_len < (3 + 7 + 15 + 255)) {
+					/* Shared byte */
+					if (!nibble_index) {
+						compressed[compressed_pos + metadata_size] = 15;
+						metadata_size += sizeof(uint8_t);
+					} else {
+						compressed[nibble_index] &= 0xF;
+						compressed[nibble_index] |= (15 * 16);
+					}
+
+					/* Additionnal best_len */
+					compressed[compressed_pos + metadata_size] = (best_len - (3 + 7 + 15)) & 0xFF;
+					metadata_size += sizeof(uint8_t);
+				} else {
+					/* Shared byte */
+					if (!nibble_index) {
+						compressed[compressed_pos + metadata_size] |= 15;
+						metadata_size += sizeof(uint8_t);
+					} else {
+						compressed[nibble_index] |= 15 << 4;
+					}
+
+					/* Additionnal best_len */
+					compressed[compressed_pos + metadata_size] = 255;
+
+					metadata_size += sizeof(uint8_t);
+
+					compressed[compressed_pos + metadata_size] = (best_len - 3) & 0xFF;
+					compressed[compressed_pos + metadata_size + 1] = ((best_len - 3) >> 8) & 0xFF;
+					metadata_size += sizeof(uint16_t);
+				}
+			}
+
+			indic |= 1 << (32 - ((indic_bit % 32) + 1));
+
+			if (best_len > 9) {
+				if (nibble_index == 0) {
+					nibble_index = compressed_pos + sizeof(uint16_t);
+				} else {
+					nibble_index = 0;
+				}
+			}
+
+			compressed_pos += metadata_size;
+			uncompressed_pos += best_len;
+			byte_left -= best_len;
+		} else {
+			compressed[compressed_pos++] = uncompressed[uncompressed_pos++];
+			byte_left--;
+		}
+		indic_bit++;
+
+		if ((indic_bit - 1) % 32 > (indic_bit % 32)) {
+			*(uint32_t *)indic_pos = indic;
+			indic = 0;
+			indic_pos = &compressed[compressed_pos];
+			compressed_pos += sizeof(uint32_t);
+		}
+	} while (byte_left > 3);
+
+	do {
+		compressed[compressed_pos] = uncompressed[uncompressed_pos];
+		indic_bit++;
+
+		uncompressed_pos++;
+		compressed_pos++;
+                if (((indic_bit - 1) % 32) > (indic_bit % 32)){
+			*(uint32_t *)indic_pos = indic;
+			indic = 0;
+			indic_pos = &compressed[compressed_pos];
+			compressed_pos += sizeof(uint32_t);
+		}
+	} while (uncompressed_pos < uncompressed_size);
+
+	if ((indic_bit % 32) > 0) {
+		for (; (indic_bit % 32) != 0; indic_bit++)
+			indic |= 0 << (32 - ((indic_bit % 32) + 1));
+
+		*(uint32_t *)indic_pos = indic;
+		compressed_pos += sizeof(uint32_t);
+	}
+
+	return compressed_pos;
+}
+
+ssize_t lzxpress_decompress(const uint8_t *input,
+			    uint32_t input_size,
+			    uint8_t *output,
+			    uint32_t max_output_size)
 {
 	uint32_t output_index, input_index;
 	uint32_t indicator, indicator_bit;
@@ -112,11 +285,11 @@ static uint32_t xpress_decompress(uint8_t *input,
 				if (length == 15) {
 					length = input[input_index];
 					input_index += sizeof(uint8_t);
-						if (length == 255) {
-							length = PULL_LE_UINT16(input, input_index);
-							input_index += sizeof(uint16_t);
-							length -= (15 + 7);
-						}
+					if (length == 255) {
+						length = PULL_LE_UINT16(input, input_index);
+						input_index += sizeof(uint16_t);
+						length -= (15 + 7);
+					}
 					length += 15;
 				}
 				length += 7;
@@ -125,20 +298,15 @@ static uint32_t xpress_decompress(uint8_t *input,
 			length += 3;
 
 			do {
-				if (output_index >= output_size) break;
+				if ((output_index >= max_output_size) || ((offset + 1) > output_index)) break;
+
 				output[output_index] = output[output_index - offset - 1];
+
 				output_index += sizeof(uint8_t);
 				length -= sizeof(uint8_t);
 			} while (length != 0);
 		}
-
-	} while ((output_index < output_size) && (input_index < input_size));
+	} while ((output_index < max_output_size) && (input_index < (input_size)));
 
 	return output_index;
 }
-
-uint32_t lzxpress_decompress(DATA_BLOB *inbuf,
-				DATA_BLOB *outbuf)
-{
-	return xpress_decompress(inbuf->data, inbuf->length, outbuf->data, outbuf->length);
-}
diff --git a/source/lib/compression/lzxpress.h b/source/lib/compression/lzxpress.h
index 4862fd2..df0ee59 100644
--- a/source/lib/compression/lzxpress.h
+++ b/source/lib/compression/lzxpress.h
@@ -37,7 +37,14 @@
 
 #define XPRESS_BLOCK_SIZE 0x10000
 
-uint32_t lzxpress_decompress(DATA_BLOB *inbuf,
-			     DATA_BLOB *outbuf);
+ssize_t lzxpress_compress(const uint8_t *uncompressed,
+			  uint32_t uncompressed_size,
+			  uint8_t *compressed,
+			  uint32_t max_compressed_size);
+
+ssize_t lzxpress_decompress(const uint8_t *input,
+			    uint32_t input_size,
+			    uint8_t *output,
+			    uint32_t max_output_size);
 
 #endif /* _LZXPRESS_H */
diff --git a/source/librpc/ndr/ndr_compression.c b/source/librpc/ndr/ndr_compression.c
index 5939c38..92c5b04 100644
--- a/source/librpc/ndr/ndr_compression.c
+++ b/source/librpc/ndr/ndr_compression.c
@@ -276,6 +276,7 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp
 	uint32_t plain_chunk_offset;
 	uint32_t comp_chunk_size;
 	uint32_t plain_chunk_size;
+	ssize_t ret;
 
 	NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size));
 	if (plain_chunk_size > 0x00010000) {
@@ -299,7 +300,16 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp
 		 plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size));
 
 	/* Uncompressing the buffer using LZ Xpress algorithm */
-	lzxpress_decompress(&comp_chunk, &plain_chunk);
+	ret = lzxpress_decompress(comp_chunk.data,
+				  comp_chunk.length,
+				  plain_chunk.data,
+				  plain_chunk.length);
+	if (ret < 0) {
+		return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+				      "XPRESS lzxpress_decompress() returned %d\n",
+				      ret);
+	}
+	plain_chunk.length = ret;
 
 	if ((plain_chunk_size < 0x00010000) || (ndrpull->offset+4 >= ndrpull->data_size)) {
 		/* this is the last chunk */
@@ -313,7 +323,55 @@ static enum ndr_err_code ndr_push_compression_xpress_chunk(struct ndr_push *ndrp
 							   struct ndr_pull *ndrpull,
 							   bool *last)
 {
-	return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, "XPRESS compression is not supported yet (PUSH)");
+	DATA_BLOB comp_chunk;
+	uint32_t comp_chunk_size_offset;
+	DATA_BLOB plain_chunk;
+	uint32_t plain_chunk_size;
+	uint32_t plain_chunk_offset;
+	uint32_t max_plain_size = 0x00010000;
+	uint32_t max_comp_size = 0x00020000 + 2; /* TODO: use the correct value here */
+	uint32_t tmp_offset;
+	ssize_t ret;
+
+	plain_chunk_size = MIN(max_plain_size, ndrpull->data_size - ndrpull->offset);
+	plain_chunk_offset = ndrpull->offset;
+	NDR_CHECK(ndr_pull_advance(ndrpull, plain_chunk_size));
+
+	plain_chunk.data = ndrpull->data + plain_chunk_offset;
+	plain_chunk.length = plain_chunk_size;
+
+	if (plain_chunk_size < max_plain_size) {
+		*last = true;
+	}
+
+	NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, plain_chunk_size));
+	comp_chunk_size_offset = ndrpush->offset;
+	NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, 0xFEFEFEFE));
+
+	NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size));
+
+	comp_chunk.data = ndrpush->data + ndrpush->offset;
+	comp_chunk.length = max_comp_size;
+
+	/* Compressing the buffer using LZ Xpress algorithm */
+	ret = lzxpress_compress(plain_chunk.data,
+				plain_chunk.length,
+				comp_chunk.data,
+				comp_chunk.length);
+	if (ret < 0) {
+		return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION,
+				      "XPRESS lzxpress_compress() returned %d\n",
+				      ret);
+	}
+	comp_chunk.length = ret;
+
+	tmp_offset = ndrpush->offset;
+	ndrpush->offset = comp_chunk_size_offset;
+	NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk.length));
+	ndrpush->offset = tmp_offset;
+
+	ndrpush->offset += comp_chunk.length;
+	return NDR_ERR_SUCCESS;
 }
 
 /*


-- 
Samba Shared Repository


More information about the samba-cvs mailing list