GCC Code Coverage Report


Directory: ./
File: Svc/DpZLibCompressor/DpZLibCompressor.cpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 0 78 0.0%
Functions: 0 7 0.0%
Branches: 0 88 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title DpZLibCompressor.cpp
3 // \author kubiak
4 // \brief cpp file for DpZLibCompressor component implementation class
5 // ======================================================================
6
7 #include "Svc/DpZLibCompressor/DpZLibCompressor.hpp"
8
9 #include <cstring>
10
11 #include <Fw/Prm/ParamValid.hpp>
12
13 namespace Svc {
14
15 // ----------------------------------------------------------------------
16 // Component construction and destruction
17 // ----------------------------------------------------------------------
18
19 DpZLibCompressor ::DpZLibCompressor(const char* const compName) : DpZLibCompressorComponentBase(compName) {}
20
21 DpZLibCompressor ::~DpZLibCompressor() {}
22
23 // ----------------------------------------------------------------------
24 // Handler implementations for typed input ports
25 // ----------------------------------------------------------------------
26
27 void DpZLibCompressor::cleanupContext(ZLibCtx& ctx) {
28 if (ctx.compression_buffer.getSize() != 0) {
29 bufferCompressionReturn_out(0, ctx.compression_buffer);
30 }
31
32 if (ctx.zlib_alloc_buffer.getSize() != 0) {
33 bufferZLibReturn_out(0, ctx.zlib_alloc_buffer);
34 }
35 }
36
37 Svc::CompressionAlgorithm DpZLibCompressor ::compressChunk_handler(FwIndexType portNum,
38 Fw::Buffer& buffer,
39 FwSizeType min_compression,
40 FwSizeType write_offset) {
41 ZLibCtx ctx(*this);
42
43 ctx.compression_buffer = bufferCompressionGet_out(0, min_compression);
44 if (ctx.compression_buffer.getSize() == 0) {
45 log_WARNING_LO_ZLibCompressionBadBuffer(min_compression);
46
47 cleanupContext(ctx);
48 return CompressionAlgorithm::UNCOMPRESSED;
49 }
50
51 Fw::ParamValid param_valid;
52 const FwSizeType zlib_alloc_size = paramGet_ZLibBufferSize(param_valid);
53 FW_ASSERT(FW_PARAM_OK(param_valid), param_valid);
54
55 ctx.zlib_alloc_buffer = bufferZLibGet_out(0, zlib_alloc_size);
56 if (ctx.zlib_alloc_buffer.getSize() == 0) {
57 log_WARNING_LO_ZLibAllocBadBuffer(zlib_alloc_size);
58
59 cleanupContext(ctx);
60 return CompressionAlgorithm::UNCOMPRESSED;
61 }
62
63 ctx.zlib_stream.zalloc = DpZLibCompressor::zlib_alloc_fn;
64 ctx.zlib_stream.zfree = DpZLibCompressor::zlib_free_fn;
65 ctx.zlib_stream.opaque = &ctx;
66
67 const CompressionAlgorithm alg = zlibCompressionHelper(ctx, buffer);
68
69 if (alg != CompressionAlgorithm::UNCOMPRESSED) {
70 // Compression completed and the size is <= min size
71 // Copy the compressed data into the original buffer
72
73 // Check that there is sufficient room in the buffer
74 // for the compressed data. This should be guaranteed
75 // by the caller, but double checking
76 FW_ASSERT(buffer.getSize() - write_offset >= ctx.compression_buffer.getSize(),
77 static_cast<FwAssertArgType>(buffer.getSize()), static_cast<FwAssertArgType>(write_offset),
78 static_cast<FwAssertArgType>(ctx.compression_buffer.getSize()));
79
80 (void)std::memcpy(buffer.getData() + write_offset, ctx.compression_buffer.getData(),
81 ctx.compression_buffer.getSize());
82 buffer.setSize(ctx.compression_buffer.getSize() + write_offset);
83 }
84
85 cleanupContext(ctx);
86 return alg;
87 }
88
89 CompressionAlgorithm DpZLibCompressor::zlibCompressionHelper(ZLibCtx& ctx, const Fw::Buffer& in_buffer) {
90 Fw::ParamValid param_valid;
91 const I8 compression_level = paramGet_CompressionLevel(param_valid);
92 FW_ASSERT(FW_PARAM_OK(param_valid), param_valid);
93
94 int zlib_ok = 0;
95 zlib_ok = deflateInit(&ctx.zlib_stream, compression_level);
96 if (zlib_ok != Z_OK) {
97 ctx.comp.log_WARNING_LO_ZLibInitError(
98 zlib_ok, ctx.zlib_stream.msg == nullptr ? Fw::String("") : Fw::String(ctx.zlib_stream.msg));
99 return CompressionAlgorithm::UNCOMPRESSED;
100 }
101
102 if (in_buffer.getSize() > std::numeric_limits<uInt>::max() ||
103 ctx.compression_buffer.getSize() > std::numeric_limits<uInt>::max()) {
104 ctx.comp.log_WARNING_LO_BufferTooBigForZLib(in_buffer.getSize(), ctx.compression_buffer.getSize(),
105 std::numeric_limits<uInt>::max());
106 return CompressionAlgorithm::UNCOMPRESSED;
107 }
108
109 ctx.zlib_stream.next_in = in_buffer.getData();
110 ctx.zlib_stream.avail_in = static_cast<uInt>(in_buffer.getSize());
111
112 ctx.zlib_stream.next_out = ctx.compression_buffer.getData();
113 ctx.zlib_stream.avail_out = static_cast<uInt>(ctx.compression_buffer.getSize());
114
115 zlib_ok = deflate(&ctx.zlib_stream, Z_FINISH);
116
117 if (zlib_ok == Z_STREAM_END && ctx.zlib_stream.total_out <= ctx.compression_buffer.getSize()) {
118 ctx.compression_buffer.setSize(ctx.zlib_stream.total_out);
119
120 ctx.comp.log_DIAGNOSTIC_ZLibCompression(in_buffer.getSize(), ctx.compression_buffer.getSize());
121
122 ctx.comp.log_DIAGNOSTIC_ZLibMemoryUsage(ctx.bump_allocator, ctx.zlib_alloc_buffer.getSize());
123
124 return CompressionAlgorithm::ZLIB_DEFLATE;
125 } else {
126 if (zlib_ok != Z_OK) {
127 ctx.comp.log_WARNING_LO_ZLibDeflateError(
128 zlib_ok, ctx.zlib_stream.msg == nullptr ? Fw::String("") : Fw::String(ctx.zlib_stream.msg));
129 }
130
131 ctx.comp.log_DIAGNOSTIC_ZLibNoCompression(in_buffer.getSize(), ctx.compression_buffer.getSize());
132 return CompressionAlgorithm::UNCOMPRESSED;
133 }
134
135 // Note: Skipping call to deflateEnd. Per the documentation this
136 // call frees the dynamically allocated data structures, but this
137 // is not necessary with the bump allocator.
138 // The call to deflateEnd does not flush any additional output data
139 }
140
141 voidpf DpZLibCompressor::zlib_alloc_fn(voidpf opaque, uInt items, uInt size) {
142 FW_ASSERT(opaque != nullptr);
143 ZLibCtx* ctx = reinterpret_cast<ZLibCtx*>(opaque);
144
145 FW_ASSERT(ctx->bump_allocator <= ctx->zlib_alloc_buffer.getSize(),
146 static_cast<FwAssertArgType>(ctx->bump_allocator),
147 static_cast<FwAssertArgType>(ctx->zlib_alloc_buffer.getSize()));
148 const FwSizeType free_space = ctx->zlib_alloc_buffer.getSize() - ctx->bump_allocator;
149
150 const FwSizeType alloc_size = static_cast<FwSizeType>(items) * static_cast<FwSizeType>(size);
151
152 if (free_space < alloc_size) {
153 return Z_NULL;
154 }
155
156 U8* alloc_ptr = ctx->zlib_alloc_buffer.getData() + ctx->bump_allocator;
157 ctx->bump_allocator += alloc_size;
158
159 return alloc_ptr;
160 }
161
162 void DpZLibCompressor::zlib_free_fn(voidpf opaque, voidpf address) {
163 // No work. Cannot free from bump allocator
164 }
165
166 } // namespace Svc
167