Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/package/source/zipapi/Deflater.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <package/Deflater.hxx>
21
#include <zlib.h>
22
#include <com/sun/star/packages/zip/ZipConstants.hpp>
23
#include <osl/diagnose.h>
24
#include <string.h>
25
26
using namespace com::sun::star::packages::zip::ZipConstants;
27
using namespace com::sun::star;
28
using namespace ZipUtils;
29
30
/** Provides general purpose compression using the ZLIB compression
31
 * library.
32
 */
33
34
Deflater::~Deflater()
35
0
{
36
0
    end();
37
0
}
38
void Deflater::init (sal_Int32 nLevelArg, bool bNowrap)
39
0
{
40
0
    pStream.reset(new z_stream);
41
    /* Memset it to 0...sets zalloc/zfree/opaque to NULL */
42
0
    memset (pStream.get(), 0, sizeof(*pStream));
43
44
0
    switch (deflateInit2(pStream.get(), nLevelArg, Z_DEFLATED, bNowrap? -MAX_WBITS : MAX_WBITS,
45
0
                DEF_MEM_LEVEL, DEFAULT_STRATEGY))
46
0
    {
47
0
        case Z_OK:
48
0
            break;
49
0
        case Z_MEM_ERROR:
50
0
        case Z_STREAM_ERROR:
51
0
            pStream.reset();
52
0
            break;
53
0
        default:
54
0
             break;
55
0
    }
56
0
}
57
58
Deflater::Deflater(sal_Int32 nSetLevel, bool bNowrap)
59
0
: bFinish(false)
60
0
, bFinished(false)
61
0
, nOffset(0)
62
0
, nLength(0)
63
0
, nTotalOut64(0)
64
0
, nTotalIn64(0)
65
0
{
66
0
    init(nSetLevel, bNowrap);
67
0
}
68
69
sal_Int32 Deflater::doDeflateBytes (uno::Sequence < sal_Int8 > &rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength)
70
0
{
71
0
    sal_Int32 nResult;
72
0
    pStream->next_in   = reinterpret_cast<const unsigned char*>( sInBuffer.getConstArray() + nOffset );
73
0
    pStream->next_out  = reinterpret_cast<unsigned char*>(rBuffer.getArray())+nNewOffset;
74
0
    pStream->avail_in  = nLength;
75
0
    pStream->avail_out = nNewLength;
76
0
    auto nLastTotalIn = pStream->total_in;
77
0
    auto nLastTotalOut = pStream->total_out;
78
79
0
#if !defined Z_PREFIX
80
0
    nResult = deflate(pStream.get(), bFinish ? Z_FINISH : Z_NO_FLUSH);
81
#else
82
    nResult = z_deflate(pStream.get(), bFinish ? Z_FINISH : Z_NO_FLUSH);
83
#endif
84
    // total_in / total_out may stored only in 32bit, and can overflow during deflate
85
    // 1 deflate call, uncompress only a few data, so only 1 overflow can happen at once.
86
0
    if (pStream->total_in < nLastTotalIn)
87
0
    {
88
0
        nTotalIn64 += 0x100000000;
89
0
    }
90
0
    if (pStream->total_out < nLastTotalOut)
91
0
    {
92
0
        nTotalOut64 += 0x100000000;
93
0
    }
94
0
    switch (nResult)
95
0
    {
96
0
        case Z_STREAM_END:
97
0
            bFinished = true;
98
0
            [[fallthrough]];
99
0
        case Z_OK:
100
0
            nOffset += nLength - pStream->avail_in;
101
0
            nLength = pStream->avail_in;
102
0
            return nNewLength - pStream->avail_out;
103
0
        default:
104
0
            return 0;
105
0
    }
106
0
}
107
108
void Deflater::setInputSegment( const uno::Sequence< sal_Int8 >& rBuffer )
109
0
{
110
0
    sInBuffer = rBuffer;
111
0
    nOffset = 0;
112
0
    nLength = rBuffer.getLength();
113
0
}
114
115
bool Deflater::needsInput() const
116
0
{
117
0
    return nLength <=0;
118
0
}
119
void Deflater::finish(  )
120
0
{
121
0
    bFinish = true;
122
0
}
123
sal_Int32 Deflater::doDeflateSegment( uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewLength )
124
0
{
125
0
    OSL_ASSERT( !(nNewLength < 0 || nNewLength > rBuffer.getLength()));
126
0
    return doDeflateBytes(rBuffer, /*nNewOffset*/0, nNewLength);
127
0
}
128
sal_Int64 Deflater::getTotalIn() const
129
0
{
130
0
    return pStream->total_in + nTotalIn64;
131
0
}
132
sal_Int64 Deflater::getTotalOut() const
133
0
{
134
0
    return pStream->total_out + nTotalOut64;
135
0
}
136
void Deflater::reset(  )
137
0
{
138
0
#if !defined Z_PREFIX
139
0
    deflateReset(pStream.get());
140
#else
141
    z_deflateReset(pStream.get());
142
#endif
143
0
    bFinish = false;
144
0
    bFinished = false;
145
0
    nOffset = nLength = 0;
146
0
}
147
void Deflater::end(  )
148
0
{
149
0
    if (pStream)
150
0
    {
151
0
#if !defined Z_PREFIX
152
0
        deflateEnd(pStream.get());
153
#else
154
        z_deflateEnd(pStream.get());
155
#endif
156
0
        pStream.reset();
157
0
    }
158
0
}
159
160
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */