blob: b0d168e439ee796726ede75169156179c6bd7396 [file] [log] [blame]
Brian Silverman2df84412013-12-10 14:00:40 -08001#include "cape/cows.h"
2
3#include <limits.h>
4
5// This implementation is based on
6// <http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing/>.
7
8uint32_t cows_stuff(const void *restrict source_in, size_t source_length,
9 void *restrict destination_in) {
10 const uint32_t *restrict source = (const uint32_t *)source_in;
11 uint32_t *restrict destination = (uint32_t *)destination_in;
12 size_t source_index = 0;
13 size_t destination_index = 1;
14 size_t code_index = 0;
15 uint32_t code = 1;
16
17 while (source_index < ((source_length - 1) / 4) + 1) {
18 if (source[source_index] == 0) {
19 destination[code_index] = code;
20 code = 1;
21 code_index = destination_index++;
22 ++source_index;
23 } else {
24 destination[destination_index++] = source[source_index++];
25 ++code;
26 if (code == UINT32_MAX) {
27 destination[code_index] = code;
28 code = 1;
29 code_index = destination_index++;
30 }
31 }
32 }
33 destination[code_index] = code;
34 return destination_index;
35}
36
37uint32_t cows_unstuff(const uint32_t *restrict source, size_t source_length,
38 uint32_t *restrict destination) {
39 size_t source_index = 0;
40 size_t destination_index = 0;
41 uint32_t code;
42
43 while (source_index < ((source_length - 1) / 4) + 1) {
44 code = source[source_index];
45 if (source_index + code > source_length && code != 1) {
46 return 0;
47 }
48
49 ++source_index;
50
51 for (uint32_t i = 1; i < code; ++i) {
52 destination[destination_index++] = source[source_index++];
53 }
54 if (code != UINT32_MAX && source_index != source_length) {
55 destination[destination_index++] = 0;
56 }
57 }
58 return destination_index;
59}