blob: 16ed1fca8b7041da87225a35aaa75b40014c16cf [file] [log] [blame]
Brian Silverman1662a0e2013-12-19 17:50:01 -08001#include "cape/cows.h"
Brian Silverman2df84412013-12-10 14:00:40 -08002
3#include <limits.h>
4
5// This implementation is based on
6// <http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing/>.
7
Daniel Petti23dcf6c2013-12-19 08:56:41 -08008uint32_t cows_stuff(const void *__restrict__ source_in, size_t source_length,
9 void *__restrict__ destination_in) {
Brian Silverman2df84412013-12-10 14:00:40 -080010 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
Daniel Petti23dcf6c2013-12-19 08:56:41 -080037uint32_t cows_unstuff(const uint32_t *__restrict__ source, size_t source_length,
38 uint32_t *__restrict__ destination) {
Brian Silverman2df84412013-12-10 14:00:40 -080039 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}