blob: b896fd750f68615c69361b8bd4e468c60a941357 [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,
Brian Silverman54787962013-12-28 22:31:16 -080038 uint32_t *__restrict__ destination,
39 size_t destination_length) {
Brian Silverman2df84412013-12-10 14:00:40 -080040 size_t source_index = 0;
41 size_t destination_index = 0;
42 uint32_t code;
43
44 while (source_index < ((source_length - 1) / 4) + 1) {
45 code = source[source_index];
Brian Silvermanac5dd402013-12-23 21:50:06 -080046 if (source_index + code > source_length / 4 && code != 1) {
Brian Silverman2df84412013-12-10 14:00:40 -080047 return 0;
48 }
49
50 ++source_index;
51
52 for (uint32_t i = 1; i < code; ++i) {
53 destination[destination_index++] = source[source_index++];
Brian Silverman54787962013-12-28 22:31:16 -080054 if (destination_index > destination_length / 4) return 0;
Brian Silverman2df84412013-12-10 14:00:40 -080055 }
Brian Silverman53f29182013-12-21 15:16:27 -080056 if (code != UINT32_MAX && source_index != source_length / 4) {
Brian Silverman2df84412013-12-10 14:00:40 -080057 destination[destination_index++] = 0;
Brian Silverman54787962013-12-28 22:31:16 -080058 if (destination_index > destination_length / 4) return 0;
Brian Silverman2df84412013-12-10 14:00:40 -080059 }
60 }
61 return destination_index;
62}