Created
April 2, 2015 18:20
-
-
Save thequux/1c51a13141ac81fe27b2 to your computer and use it in GitHub Desktop.
Spritz in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file was written by TQ Hirsch <[email protected]>. | |
// It may be used under any of the following licenses, at your | |
// discretion: | |
// - Public Domain | |
// - WTFPLv2 | |
// - CC-0 | |
// - MIT | |
// - ISC | |
// This file may be used as a header for separate compilation by | |
// #define-ing SPRITZ_HEADER_ONLY. Alternatively, cut this file at the | |
// line that contains "=== END HEADER ==="; the top half is usuable as | |
// a header while the bottom half contains the implementation. If you | |
// do this, the header should be called "spritz.h" | |
#ifndef SPRITZ__H | |
#define SPRITZ__H | |
#include <stdint.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
typedef struct spritz_t { | |
uint8_t s[256]; | |
uint8_t i,j,k,z,a,w; | |
} spritz_t; | |
#define SPRITZ_STATIC_INIT { \ | |
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \ | |
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \ | |
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ | |
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \ | |
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \ | |
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \ | |
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, \ | |
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, \ | |
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, \ | |
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, \ | |
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, \ | |
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, \ | |
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, \ | |
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, \ | |
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, \ | |
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}, \ | |
0, 0, 0, 0, 0, 1} | |
void spritz_init(spritz_t *sp); | |
void spritz_absorb(spritz_t *sp, const uint8_t *buf, size_t len); | |
void spritz_absorb_stop(spritz_t *sp); | |
void spritz_squeeze(spritz_t *sp, const uint8_t *buf, size_t len); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // !SPRITZ__H | |
// === END HEADER === | |
// === BEGIN CODE === | |
#ifndef SPRITZ_HEADER_ONLY | |
#ifndef SPRITZ__H | |
#include "spritz.h" | |
#endif | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#define S (sp->s) | |
#define I (sp->i) | |
#define J (sp->j) | |
#define K (sp->k) | |
#define Z (sp->z) | |
#define A (sp->a) | |
#define W (sp->w) | |
#define SWAP(a,b) do { uint8_t t = (a); (a) = (b); (b) = t; } while(0) | |
#define SPRITZ_ABS_NIBBLE(b) do { \ | |
if (A == 128) spritz_shuffle(sp); \ | |
SWAP(S[A], S[128 + ((b) & 0xF)]); \ | |
A++; \ | |
} | |
#define SPRITZ_UPDATE() do { \ | |
I += W; \ | |
J = K + S[J + S[I]]; \ | |
K = I + K + S[J]; \ | |
SWAP(S[I], S[J]); \ | |
} while (0) | |
void spritz_init(spritz_t *sp) { | |
int i; | |
for (i = 0; i < 256; i++) { | |
S[i] = (uint8_t)i; | |
} | |
I = J = K = Z = A = 0; | |
W = 1; | |
} | |
void spritz_absorb(spritz_t *sp, const uint8_t *buf, size_t len) { | |
int i; | |
uint8_t b, t; | |
for (i = 0; i < len; i++) { | |
b = buf[i]; | |
SPRITZ_ABS_NIBBLE(b & 0xF); | |
SPRITZ_ABS_NIBBLE(b >> 4); | |
} | |
} | |
void spritz_absorb_stop(spritz_t *sp) { | |
if (A == 128) spritz_shuffle(sp); | |
A++; | |
} | |
void spritz_squeeze(spritz_t *sp, const uint8_t *buf, size_t len) { | |
if (A > 0) spritz_shuffle(sp); | |
int i; | |
for (i = 0; i < len; i++) { | |
SPRITZ_UPDATE(); | |
buf[i] = Z = S[J + S[I + S[Z+K]]]; | |
} | |
} | |
void spritz_whip(spritz_t *sp) { | |
int i; | |
for (i = 0; i < 512; i++) SPRITZ_UPDATE(); | |
w += 2; | |
} | |
void spritz_crush(spritz_t *sp) { | |
int i; | |
for (i = 0; i < 128; i++) { | |
uint8_t a,b, m; | |
a = S[i]; | |
b = S[255-i]; | |
// take high bit of (b-a), place it in the low bit, and negate it | |
// (to sign extend) | |
// in other words, m = (a < b) ? 0 : 0xff; | |
m = ~(((b - a) & 0x80) >> 7) + 1; | |
S[i] = a &~ m | b & m; | |
S[255-i] = a & m | b &~ m; | |
} | |
} | |
void spritz_shuffle(spritz_t *sp) { | |
spritz_whip(sp); | |
spritz_crush(sp); | |
spritz_whip(sp); | |
spritz_crush(sp); | |
spritz_whip(sp); | |
A = 0; | |
} | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // !SPRITZ_HEADER_ONLY |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment