-
Notifications
You must be signed in to change notification settings - Fork 29
/
morfi.c
80 lines (69 loc) · 1.96 KB
/
morfi.c
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
#include <stdio.h>
#include <stdint.h>
#ifdef _WIN32
# include <io.h>
# include <fcntl.h>
#endif
// Default key, if none is given
#define DEFAULTKEY 0xBADC0FFEE0DDF00D // 0x0000ab16badd06fell
// From: https://en.wikipedia.org/wiki/Xorshift#xorshift*
uint64_t XorShiftStar64(uint64_t seed) {
static uint64_t k = DEFAULTKEY;
if(seed)
k = seed;
k ^= k >> 12;
k ^= k << 25;
k ^= k >> 27;
return k * 0x2545F4914F6CDD1D;
}
uint8_t hex2dec(uint8_t hex) {
if(hex >= 'a' && hex <= 'z')
return hex - 'a' + 10;
else if(hex >= 'A' && hex <= 'Z')
return hex - 'A' + 10;
else if(hex >= '0' && hex <= '9')
return hex - '0';
return hex;
}
void morfi(uint64_t blk, int blkLen) {
uint8_t *pBlk = (uint8_t *)&blk + blkLen;
blk ^= XorShiftStar64(0);
while(--pBlk >= (uint8_t *)&blk) // Little-endian
putchar(*pBlk);
}
int main(int argc, char* argv[]) {
uint64_t blk = 0;
int blkLen = 0, c;
if(argv[1]) {
char* pSeed = argv[1];
uint64_t seed = 0;
while(*pSeed)
seed = (seed << 4) | hex2dec(*pSeed++);
XorShiftStar64(seed);
}
#ifdef _WIN32
// On Windows, the default mode of stdin is O_TEXT.
// This will cause EOF when a 0x1a(^Z) is reached.
setmode(fileno(stdin), O_BINARY);
// This turns \n into \r\n, causing troubles
setmode(fileno(stdout), O_BINARY);
#endif
while((c = getchar()) != EOF) {
blk = (blk << 8) | (uint8_t)c; // Fill a block
blkLen = ++blkLen % 8;
if(!blkLen) { // A block is full
morfi(blk, 8);
blk = 0;
}
}
if(blkLen) // The last block is not fully filled
morfi(blk, blkLen);
#ifdef _WIN32
// Avoid strange console problems
setmode(fileno(stdin), O_TEXT);
// Write all data out before becoming weird
fflush(stdout);
setmode(fileno(stdout), O_TEXT);
#endif
return 0;
}