| 1157 | } |
| 1158 | |
| 1159 | static size_t psl_a85_encode (struct PSL_CTRL *PSL, const unsigned char *src_buf, size_t nbytes) { |
| 1160 | /* Encode 4-byte binary data from src_buf to 5-byte ASCII85 |
| 1161 | * Special cases: 0x00000000 is encoded as z |
| 1162 | * Encoded data is stored in dst_buf and written to file in |
| 1163 | * one go, which is faster than writing one char at a time. |
| 1164 | * The function returns the output buffer size. */ |
| 1165 | size_t dst_buf_size; |
| 1166 | unsigned char *dst_buf, *dst_ptr; |
| 1167 | const unsigned char *src_ptr = src_buf, *src_end = src_buf + nbytes; |
| 1168 | const unsigned int max_line_len = 95; /* number of chars after which a newline is inserted */ |
| 1169 | |
| 1170 | if (!nbytes) |
| 1171 | /* Ignore empty input */ |
| 1172 | return 0; |
| 1173 | |
| 1174 | /* dst_buf has to be large enough to hold data + line endings */ |
| 1175 | dst_buf_size = (size_t)(nbytes * 1.25 + 1); /* output buffer is at least 1.25 times larger */ |
| 1176 | dst_buf_size += dst_buf_size / max_line_len + 4; /* add more space for '\n' and delimiter */ |
| 1177 | dst_ptr = dst_buf = PSL_memory (PSL, NULL, dst_buf_size, unsigned char); /* output buffer */ |
| 1178 | |
| 1179 | do { /* for each quad in src_buf while src_ptr < src_end */ |
| 1180 | const size_t ilen = nbytes > 4 ? 4 : nbytes, olen = ilen + 1; |
| 1181 | static unsigned int line_len = 0; |
| 1182 | unsigned int i, n = 0, byte; |
| 1183 | int j; |
| 1184 | unsigned char quintuple[5] = { 0 }; |
| 1185 | |
| 1186 | /* Wrap 4 chars into a 4-byte integer */ |
| 1187 | for (i = 0; i < ilen; ++i) { |
| 1188 | byte = *src_ptr++; |
| 1189 | n += byte << (24 - 8*i); |
| 1190 | } |
| 1191 | |
| 1192 | if (n == 0 && ilen == 4) { |
| 1193 | /* Set the only output byte to "z" */ |
| 1194 | *dst_ptr++ = 'z'; |
| 1195 | ++line_len; |
| 1196 | continue; |
| 1197 | } |
| 1198 | |
| 1199 | /* Else determine output 5-tuple */ |
| 1200 | for (j = 4; j >= 0; --j) { |
| 1201 | quintuple[j] = (unsigned char) ((n % 85) + '!'); |
| 1202 | n = n / 85; |
| 1203 | } |
| 1204 | |
| 1205 | /* Copy olen bytes to dst_buf */ |
| 1206 | memcpy (dst_ptr, quintuple, olen); |
| 1207 | line_len += (unsigned int)olen; |
| 1208 | dst_ptr += olen; |
| 1209 | |
| 1210 | /* Insert newline when line exceeds 95 characters */ |
| 1211 | if (line_len + 1 > max_line_len) { |
| 1212 | *dst_ptr++ = '\n'; |
| 1213 | line_len = 0; |
| 1214 | } |
| 1215 | } while (nbytes -= 4, src_ptr < src_end); /* end do */ |
| 1216 |
no test coverage detected