Win32: fix an incorrect error status being propagated to the caller in case
[svn/apache.git] / subversion / libsvn_subr / compress_lz4.c
blob7dd45263b0c460815b2ad6bb926a33646b9dc324
1 /*
2 * compress_lz4.c: LZ4 data compression routines
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 * ====================================================================
24 #include <assert.h>
26 #include "private/svn_subr_private.h"
28 #include "svn_private_config.h"
30 #ifdef SVN_INTERNAL_LZ4
31 #include "lz4/lz4internal.h"
32 #else
33 #include <lz4.h>
34 #endif
36 svn_error_t *
37 svn__compress_lz4(const void *data, apr_size_t len,
38 svn_stringbuf_t *out)
40 apr_size_t hdrlen;
41 unsigned char buf[SVN__MAX_ENCODED_UINT_LEN];
42 unsigned char *p;
43 int compressed_data_len;
44 int max_compressed_data_len;
46 assert(len <= LZ4_MAX_INPUT_SIZE);
48 p = svn__encode_uint(buf, (apr_uint64_t)len);
49 hdrlen = p - buf;
50 max_compressed_data_len = LZ4_compressBound((int)len);
51 svn_stringbuf_setempty(out);
52 svn_stringbuf_ensure(out, max_compressed_data_len + hdrlen);
53 svn_stringbuf_appendbytes(out, (const char *)buf, hdrlen);
54 compressed_data_len = LZ4_compress_default(data, out->data + out->len,
55 (int)len, max_compressed_data_len);
56 if (!compressed_data_len)
57 return svn_error_create(SVN_ERR_LZ4_COMPRESSION_FAILED, NULL, NULL);
59 if (compressed_data_len >= (int)len)
61 /* Compression didn't help :(, just append the original text */
62 svn_stringbuf_appendbytes(out, data, len);
64 else
66 out->len += compressed_data_len;
67 out->data[out->len] = 0;
70 return SVN_NO_ERROR;
73 svn_error_t *
74 svn__decompress_lz4(const void *data, apr_size_t len,
75 svn_stringbuf_t *out,
76 apr_size_t limit)
78 apr_size_t hdrlen;
79 int compressed_data_len;
80 int decompressed_data_len;
81 apr_uint64_t u64;
82 const unsigned char *p = data;
83 int rv;
85 assert(len <= INT_MAX);
86 assert(limit <= INT_MAX);
88 /* First thing in the string is the original length. */
89 p = svn__decode_uint(&u64, p, p + len);
90 if (p == NULL)
91 return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
92 _("Decompression of compressed data failed: "
93 "no size"));
94 if (u64 > limit)
95 return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL,
96 _("Decompression of compressed data failed: "
97 "size too large"));
98 decompressed_data_len = (int)u64;
99 hdrlen = p - (const unsigned char *)data;
100 compressed_data_len = (int)(len - hdrlen);
102 svn_stringbuf_setempty(out);
103 svn_stringbuf_ensure(out, decompressed_data_len);
105 if (compressed_data_len == decompressed_data_len)
107 /* Data is in the original, uncompressed form. */
108 memcpy(out->data, p, decompressed_data_len);
110 else
112 rv = LZ4_decompress_safe((const char *)p, out->data, compressed_data_len,
113 decompressed_data_len);
114 if (rv < 0)
115 return svn_error_create(SVN_ERR_LZ4_DECOMPRESSION_FAILED, NULL, NULL);
117 if (rv != decompressed_data_len)
118 return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA,
119 NULL,
120 _("Size of uncompressed data "
121 "does not match stored original length"));
124 out->data[decompressed_data_len] = 0;
125 out->len = decompressed_data_len;
127 return SVN_NO_ERROR;
130 const char *
131 svn_lz4__compiled_version(void)
133 static const char lz4_version_str[] = APR_STRINGIFY(LZ4_VERSION_MAJOR) "." \
134 APR_STRINGIFY(LZ4_VERSION_MINOR) "." \
135 APR_STRINGIFY(LZ4_VERSION_RELEASE);
137 return lz4_version_str;
141 svn_lz4__runtime_version(void)
143 return LZ4_versionNumber();