F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
DpZLibCompressor.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title DpZLibCompressor.cpp
3 // \author kubiak
4 // \brief cpp file for DpZLibCompressor component implementation class
5 // ======================================================================
6 
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 
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) {
46 
47  cleanupContext(ctx);
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);
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 
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));
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());
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 
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());
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
~DpZLibCompressor()
Destroy DpZLibCompressor object.
DpZLibCompressor(const char *const compName)
Construct DpZLibCompressor object.
#define FW_PARAM_OK(paramValid)
Definition: ParamValid.hpp:22
PlatformSizeType FwSizeType
void setSize(FwSizeType size)
Definition: Buffer.cpp:131
Fw::Buffer bufferZLibGet_out(FwIndexType portNum, FwSizeType size) const
Invoke output port bufferZLibGet.
int8_t I8
8-bit signed integer
Definition: BasicTypes.h:51
U8 * getData() const
Definition: Buffer.cpp:82
void bufferCompressionReturn_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port bufferCompressionReturn.
Auto-generated base for DpZLibCompressor component.
Fw::Buffer bufferCompressionGet_out(FwIndexType portNum, FwSizeType size) const
Invoke output port bufferCompressionGet.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
FwSizeType getSize() const
Definition: Buffer.cpp:90
void bufferZLibReturn_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port bufferZLibReturn.
PlatformIndexType FwIndexType
RateGroupDivider component implementation.
Enum representing parameter validity.
FwSizeType paramGet_ZLibBufferSize(Fw::ParamValid &valid)
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformAssertArgType FwAssertArgType
The type of arguments to assert functions.