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