Brian Silverman | 1662a0e | 2013-12-19 17:50:01 -0800 | [diff] [blame^] | 1 | #include "cape/cows.h" |
Brian Silverman | 2df8441 | 2013-12-10 14:00:40 -0800 | [diff] [blame] | 2 | |
| 3 | #include <limits.h> |
| 4 | |
| 5 | // This implementation is based on |
| 6 | // <http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing/>. |
| 7 | |
Daniel Petti | 23dcf6c | 2013-12-19 08:56:41 -0800 | [diff] [blame] | 8 | uint32_t cows_stuff(const void *__restrict__ source_in, size_t source_length, |
| 9 | void *__restrict__ destination_in) { |
Brian Silverman | 2df8441 | 2013-12-10 14:00:40 -0800 | [diff] [blame] | 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 | |
Daniel Petti | 23dcf6c | 2013-12-19 08:56:41 -0800 | [diff] [blame] | 37 | uint32_t cows_unstuff(const uint32_t *__restrict__ source, size_t source_length, |
| 38 | uint32_t *__restrict__ destination) { |
Brian Silverman | 2df8441 | 2013-12-10 14:00:40 -0800 | [diff] [blame] | 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 | } |