88{
89 QByteArray output;
90 output.resize(unpacked_len);
91
92 const auto *src = input.cbegin();
93 auto *dst = output.begin();
94
95 while (src < input.end() && dst < output.end()) {
96
97 const int8_t n = *reinterpret_cast<const int8_t *>(src);
98 src += 1;
99
100 if (n >= 0) {
101 const int bytes = 1 + n;
102 if (src + bytes > input.cend()) {
103 errFile <<
"Input buffer exhausted in replicate of" << bytes <<
"chars, left" << (input.cend() - src);
104 return {};
105 }
106 if (dst + bytes > output.end()) {
107 errFile <<
"Overrun in packbits replicate of" << bytes <<
"chars, left" << (output.end() - dst);
108 return {};
109 }
110 std::copy_n(src, bytes, dst);
112 dst += bytes;
113 } else if (n >= -127 && n <= -1) {
114 const int bytes = 1 - n;
115 if (src >= input.cend()) {
116 errFile <<
"Input buffer exhausted in copy";
117 return {};
118 }
119 if (dst + bytes > output.end()) {
120 errFile <<
"Output buffer exhausted in copy of" << bytes <<
"chars, left" << (output.end() - dst);
121 return {};
122 }
123 const auto byte = *
src;
124 std::fill_n(dst, bytes, byte);
126 dst += bytes;
127 } else if (n == -128) {
128 continue;
129 }
130 }
131
132 if (dst < output.end()) {
133 errFile <<
"Packbits decode - unpack left" << (output.end() - dst);
134 std::fill(dst, output.end(), 0);
135 }
136
137
138 if (src + 1 < input.cend()) {
139 QByteArray leftovers;
140 leftovers.resize(static_cast<int>(input.cend() - src));
141 std::copy(src, input.cend(), leftovers.begin());
142 errFile <<
"Packbits decode - pack left" << leftovers.size() << leftovers.toHex();
143 }
144
145 return output;
146}