Author: kotkov
Date: Thu Jul 27 09:59:47 2017
New Revision: 1803158
URL: http://svn.apache.org/viewvc?rev=1803158&view=rev
Log:
Split libsvn_subr/compress.c into three files.
This file contained routines for zlib and LZ4 compression and for general
data encoding, such as svn__encode_uint(). It would be better to maintain
all of these three groups separately.
* subversion/libsvn_subr/compress.c
(svn__encode_uint, svn__encode_int, svn__decode_uint, svn__decode_int):
Move to encode.c.
(svn_zlib__compiled_version, svn_zlib__runtime_version,
svnCompressBound, MIN_COMPRESS_SIZE, zlib_encode, zlib_decode,
svn__compress_zlib, svn__decompress_zlib): Move to compress_zlib.c.
(svn__compress_lz4, svn__decompress_lz4): Move to compress_lz4.c.
* subversion/libsvn_subr/encode.c,
subversion/libsvn_subr/compress_zlib.c,
subversion/libsvn_subr/compress_lz4.c: New files.
Added:
subversion/trunk/subversion/libsvn_subr/compress_lz4.c (with props)
subversion/trunk/subversion/libsvn_subr/compress_zlib.c (with props)
subversion/trunk/subversion/libsvn_subr/encode.c (with props)
Removed:
subversion/trunk/subversion/libsvn_subr/compress.c
Added: subversion/trunk/subversion/libsvn_subr/compress_lz4.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/compress_lz4.c?rev=1803158&view=auto
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/compress_lz4.c (added)
+++ subversion/trunk/subversion/libsvn_subr/compress_lz4.c Thu Jul 27 09:59:47
2017
@@ -0,0 +1,128 @@
+/*
+ * compress_lz4.c: LZ4 data compression routines
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include <assert.h>
+
+#include "private/svn_subr_private.h"
+
+#include "svn_private_config.h"
+
+#if SVN_INTERNAL_LZ4
+#include "lz4/lz4internal.h"
+#else
+#include <lz4.h>
+#endif
+
+svn_error_t *
+svn__compress_lz4(const void *data, apr_size_t len,
+ svn_stringbuf_t *out)
+{
+ apr_size_t hdrlen;
+ unsigned char buf[SVN__MAX_ENCODED_UINT_LEN];
+ unsigned char *p;
+ int compressed_data_len;
+ int max_compressed_data_len;
+
+ assert(len <= LZ4_MAX_INPUT_SIZE);
+
+ p = svn__encode_uint(buf, (apr_uint64_t)len);
+ hdrlen = p - buf;
+ max_compressed_data_len = LZ4_compressBound((int)len);
+ svn_stringbuf_setempty(out);
+ svn_stringbuf_ensure(out, max_compressed_data_len + hdrlen);
+ svn_stringbuf_appendbytes(out, (const char *)buf, hdrlen);
+ compressed_data_len = LZ4_compress_default(data, out->data + out->len,
+ (int)len,
max_compressed_data_len);
+ if (!compressed_data_len)
+ return svn_error_create(SVN_ERR_LZ4_COMPRESSION_FAILED, NULL, NULL);
+
+ if (compressed_data_len >= (int)len)
+ {
+ /* Compression didn't help :(, just append the original text */
+ svn_stringbuf_appendbytes(out, data, len);
+ }
+ else
+ {
+ out->len += compressed_data_len;
+ out->data[out->len] = 0;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn__decompress_lz4(const void *data, apr_size_t len,
+ svn_stringbuf_t *out,
+ apr_size_t limit)
+{
+ apr_size_t hdrlen;
+ int compressed_data_len;
+ int decompressed_data_len;
+ apr_uint64_t u64;
+ const unsigned char *p = data;
+ int rv;
+
+ assert(len <= INT_MAX);
+ assert(limit <= INT_MAX);
+
+ /* First thing in the string is the original length. */
+ p = svn__decode_uint(&u64, p, p + len);
+ if (p == NULL)
+ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
+ _("Decompression of compressed data failed: "
+ "no size"));
+ if (u64 > limit)
+ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
+ _("Decompression of compressed data failed: "
+ "size too large"));
+ decompressed_data_len = (int)u64;
+ hdrlen = p - (const unsigned char *)data;
+ compressed_data_len = (int)(len - hdrlen);
+
+ svn_stringbuf_setempty(out);
+ svn_stringbuf_ensure(out, decompressed_data_len);
+
+ if (compressed_data_len == decompressed_data_len)
+ {
+ /* Data is in the original, uncompressed form. */
+ memcpy(out->data, p, decompressed_data_len);
+ }
+ else
+ {
+ rv = LZ4_decompress_safe((const char *)p, out->data, compressed_data_len,
+ decompressed_data_len);
+ if (rv < 0)
+ return svn_error_create(SVN_ERR_LZ4_DECOMPRESSION_FAILED, NULL, NULL);
+
+ if (rv != decompressed_data_len)
+ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
+ NULL,
+ _("Size of uncompressed data "
+ "does not match stored original length"));
+ }
+
+ out->data[decompressed_data_len] = 0;
+ out->len = decompressed_data_len;
+
+ return SVN_NO_ERROR;
+}
Propchange: subversion/trunk/subversion/libsvn_subr/compress_lz4.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: subversion/trunk/subversion/libsvn_subr/compress_zlib.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/compress_zlib.c?rev=1803158&view=auto
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/compress_zlib.c (added)
+++ subversion/trunk/subversion/libsvn_subr/compress_zlib.c Thu Jul 27 09:59:47
2017
@@ -0,0 +1,201 @@
+/*
+ * compress_zlib.c: zlib data compression routines
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+
+#include <zlib.h>
+
+#include "private/svn_subr_private.h"
+#include "private/svn_error_private.h"
+
+#include "svn_private_config.h"
+
+const char *
+svn_zlib__compiled_version(void)
+{
+ static const char zlib_version_str[] = ZLIB_VERSION;
+
+ return zlib_version_str;
+}
+
+const char *
+svn_zlib__runtime_version(void)
+{
+ return zlibVersion();
+}
+
+
+/* The zlib compressBound function was not exported until 1.2.0. */
+#if ZLIB_VERNUM >= 0x1200
+#define svnCompressBound(LEN) compressBound(LEN)
+#else
+#define svnCompressBound(LEN) ((LEN) + ((LEN) >> 12) + ((LEN) >> 14) + 11)
+#endif
+
+/* For svndiff1, address/instruction/new data under this size will not
+ be compressed using zlib as a secondary compressor. */
+#define MIN_COMPRESS_SIZE 512
+
+/* If IN is a string that is >= MIN_COMPRESS_SIZE and the COMPRESSION_LEVEL
+ is not SVN_DELTA_COMPRESSION_LEVEL_NONE, zlib compress it and places the
+ result in OUT, with an integer prepended specifying the original size.
+ If IN is < MIN_COMPRESS_SIZE, or if the compressed version of IN was no
+ smaller than the original IN, OUT will be a copy of IN with the size
+ prepended as an integer. */
+static svn_error_t *
+zlib_encode(const char *data,
+ apr_size_t len,
+ svn_stringbuf_t *out,
+ int compression_level)
+{
+ unsigned long endlen;
+ apr_size_t intlen;
+ unsigned char buf[SVN__MAX_ENCODED_UINT_LEN], *p;
+
+ svn_stringbuf_setempty(out);
+ p = svn__encode_uint(buf, (apr_uint64_t)len);
+ svn_stringbuf_appendbytes(out, (const char *)buf, p - buf);
+
+ intlen = out->len;
+
+ /* Compression initialization overhead is considered to large for
+ short buffers. Also, if we don't actually want to compress data,
+ ZLIB will produce an output no shorter than the input. Hence,
+ the DATA would directly appended to OUT, so we can do that directly
+ without calling ZLIB before. */
+ if (len < MIN_COMPRESS_SIZE || compression_level == SVN__COMPRESSION_NONE)
+ {
+ svn_stringbuf_appendbytes(out, data, len);
+ }
+ else
+ {
+ int zerr;
+
+ svn_stringbuf_ensure(out, svnCompressBound(len) + intlen);
+ endlen = out->blocksize;
+
+ zerr = compress2((unsigned char *)out->data + intlen, &endlen,
+ (const unsigned char *)data, len,
+ compression_level);
+ if (zerr != Z_OK)
+ return svn_error_trace(svn_error__wrap_zlib(
+ zerr, "compress2",
+ _("Compression of svndiff data failed")));
+
+ /* Compression didn't help :(, just append the original text */
+ if (endlen >= len)
+ {
+ svn_stringbuf_appendbytes(out, data, len);
+ return SVN_NO_ERROR;
+ }
+ out->len = endlen + intlen;
+ out->data[out->len] = 0;
+ }
+ return SVN_NO_ERROR;
+}
+
+/* Decode the possibly-zlib compressed string of length INLEN that is in
+ IN, into OUT. We expect an integer is prepended to IN that specifies
+ the original size, and that if encoded size == original size, that the
+ remaining data is not compressed.
+ In that case, we will simply return pointer into IN as data pointer for
+ OUT, COPYLESS_ALLOWED has been set. The, the caller is expected not to
+ modify the contents of OUT.
+ An error is returned if the decoded length exceeds the given LIMIT.
+ */
+static svn_error_t *
+zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out,
+ apr_size_t limit)
+{
+ apr_size_t len;
+ apr_uint64_t size;
+ const unsigned char *oldplace = in;
+
+ /* First thing in the string is the original length. */
+ in = svn__decode_uint(&size, in, in + inLen);
+ len = (apr_size_t)size;
+ if (in == NULL || len != size)
+ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
+ _("Decompression of zlib compressed data failed:
no size"));
+ if (len > limit)
+ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
+ _("Decompression of zlib compressed data failed: "
+ "size too large"));
+
+ /* We need to subtract the size of the encoded original length off the
+ * still remaining input length. */
+ inLen -= (in - oldplace);
+ if (inLen == len)
+ {
+ svn_stringbuf_ensure(out, len);
+ memcpy(out->data, in, len);
+ out->data[len] = 0;
+ out->len = len;
+
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ unsigned long zlen = len;
+ int zerr;
+
+ svn_stringbuf_ensure(out, len);
+ zerr = uncompress((unsigned char *)out->data, &zlen, in, inLen);
+ if (zerr != Z_OK)
+ return svn_error_trace(svn_error__wrap_zlib(
+ zerr, "uncompress",
+ _("Decompression of svndiff data failed")));
+
+ /* Zlib should not produce something that has a different size than the
+ original length we stored. */
+ if (zlen != len)
+ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
+ NULL,
+ _("Size of uncompressed data "
+ "does not match stored original length"));
+ out->data[zlen] = 0;
+ out->len = zlen;
+ }
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn__compress_zlib(const void *data, apr_size_t len,
+ svn_stringbuf_t *out,
+ int compression_method)
+{
+ if ( compression_method < SVN__COMPRESSION_NONE
+ || compression_method > SVN__COMPRESSION_ZLIB_MAX)
+ return svn_error_createf(SVN_ERR_BAD_COMPRESSION_METHOD, NULL,
+ _("Unsupported compression method %d"),
+ compression_method);
+
+ return zlib_encode(data, len, out, compression_method);
+}
+
+svn_error_t *
+svn__decompress_zlib(const void *data, apr_size_t len,
+ svn_stringbuf_t *out,
+ apr_size_t limit)
+{
+ return zlib_decode(data, len, out, limit);
+}
Propchange: subversion/trunk/subversion/libsvn_subr/compress_zlib.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: subversion/trunk/subversion/libsvn_subr/encode.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/encode.c?rev=1803158&view=auto
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/encode.c (added)
+++ subversion/trunk/subversion/libsvn_subr/encode.c Thu Jul 27 09:59:47 2017
@@ -0,0 +1,107 @@
+/*
+ * encode.c: various data encoding and decoding routines
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "private/svn_subr_private.h"
+
+#include "svn_private_config.h"
+
+unsigned char *
+svn__encode_uint(unsigned char *p, apr_uint64_t val)
+{
+ int n;
+ apr_uint64_t v;
+
+ /* Figure out how many bytes we'll need. */
+ v = val >> 7;
+ n = 1;
+ while (v > 0)
+ {
+ v = v >> 7;
+ n++;
+ }
+
+ /* Encode the remaining bytes; n is always the number of bytes
+ coming after the one we're encoding. */
+ while (--n >= 1)
+ *p++ = (unsigned char)(((val >> (n * 7)) | 0x80) & 0xff);
+
+ *p++ = (unsigned char)(val & 0x7f);
+
+ return p;
+}
+
+unsigned char *
+svn__encode_int(unsigned char *p, apr_int64_t val)
+{
+ apr_uint64_t value = val;
+ value = value & APR_UINT64_C(0x8000000000000000)
+ ? APR_UINT64_MAX - (2 * value)
+ : 2 * value;
+
+ return svn__encode_uint(p, value);
+}
+
+const unsigned char *
+svn__decode_uint(apr_uint64_t *val,
+ const unsigned char *p,
+ const unsigned char *end)
+{
+ apr_uint64_t temp = 0;
+
+ if (end - p > SVN__MAX_ENCODED_UINT_LEN)
+ end = p + SVN__MAX_ENCODED_UINT_LEN;
+
+ /* Decode bytes until we're done. */
+ while (SVN__PREDICT_TRUE(p < end))
+ {
+ unsigned int c = *p++;
+
+ if (c < 0x80)
+ {
+ *val = (temp << 7) | c;
+ return p;
+ }
+ else
+ {
+ temp = (temp << 7) | (c & 0x7f);
+ }
+ }
+
+ return NULL;
+}
+
+const unsigned char *
+svn__decode_int(apr_int64_t *val,
+ const unsigned char *p,
+ const unsigned char *end)
+{
+ apr_uint64_t value;
+ const unsigned char *result = svn__decode_uint(&value, p, end);
+
+ value = value & 1
+ ? (APR_UINT64_MAX - value / 2)
+ : value / 2;
+ *val = (apr_int64_t)value;
+
+ return result;
+}
Propchange: subversion/trunk/subversion/libsvn_subr/encode.c
------------------------------------------------------------------------------
svn:eol-style = native