/* bits - pipe the bits of each byte from stdin to stdout * * usage: bits [] */ #include #include #include #define BUFFER_SIZE 4096 #define IGNORE(param) do { (void)(param); } while(0) //TODO: For explicitly threaded version: Make a lazy thread spawner, spawning up to 8 threads which will each work on a byte and atomically write back to a central array of `uint64_t [num_of_bytes / num_of_threads]`. //TODO: But how to sync the fwrites of this buffer? An atomic counter of which threads have completed their operations, and a condvar that allows the controlling thread to check if the counter is full before `fwrite_all()`ing the array, resetting the counter, and carrying on static inline int sfread(void* out, size_t *restrict size, FILE* f) { register ssize_t r = fread(out, 1, *size, f); return r < 0 ? (perror("failed to read from stdin"), 0) : !!(*size = (size_t)r); } static int fwrite_all(const void* _buf, size_t sz, size_t num, FILE* out) { register size_t w, done=0; register const unsigned char* buf = _buf; while( (w = fwrite(buf+done, sz, num-done, out)) > 0 && done < num) done+=w; if (done!=num) return 0; else return 1; } static void pbits(char out[restrict 8], unsigned char byte, const char bit[static 2]) { for(register int i=8; i --> 0; byte >>= 1) *out++=bit[byte & 1]; //TODO: In explicitly threaded version, we can use an atomic (atomic.h) 64-bit integer `store()` to output those 8 bytes in `out`, which will be re-cast as `uint64_t out[restrict 1]` } static inline int check(int val, const char* msg) { if(val) return val; fprintf(stderr, "error: %s\n", msg); exit(1); } int main(int argc, char **argv) { IGNORE(argc); const char* mask = argv[1] && check(strlen(argv[1]) > 1, "expected 2 character mask") ? argv[1] : "01"; unsigned char buf[BUFFER_SIZE]; char tbuf[BUFFER_SIZE * 8]; size_t bsz = BUFFER_SIZE; while(sfread(buf, &bsz, stdin)) { register size_t size = bsz; while(size --> 0) pbits(tbuf+(8*size), buf[size], mask); if(!fwrite_all(tbuf, 8, bsz, stdout)) { perror("Failed to write"); return 1; } } return 0; }