#include "io.h" #include #include #include #include #include #include struct IOBlock { IOBlock *next; ssize_t used, size; unsigned char data[]; }; IOBlock* newIOBlock() { const ssize_t amount = 512*1024; // avoid fragmentation: 128kb is the standard M_MMAP_THRESHOLD IOBlock* b = (IOBlock*) malloc(amount); if (!b) abort(); b->size = amount - sizeof(*b); b->used = 0; b->next = NULL; return b; } // frees block list static void blocksToVector(IOBlock *blocks, ssize_t total, std::vector &buf) { buf.reserve(std::max(total+1, 512*1024)); // try forcing mmap buf.resize(total); (&buf.at(0))[total] = '\0'; ssize_t pos = 0; IOBlock *prev = 0; for (IOBlock *cur = blocks; cur; prev = cur, cur = cur->next) { free(prev); if (cur->used > 0) { memcpy(&buf.at(pos), cur->data, cur->used); pos += cur->used; } } free(prev); } void readAll(int fd, std::vector &buf) { IOBlock *first = newIOBlock(); IOBlock *cur = first; ssize_t total = 0; for (;;) { ssize_t avail; for (;;) { avail = cur->size - cur->used; if (0 != avail) break; cur->next = newIOBlock(); cur = cur->next; } ssize_t len = read(fd, cur->data + cur->used, avail); if (0 == len) break; /* eof */ if (0 > len) { perror("read failed"); abort(); } cur->used += len; total += len; } blocksToVector(first, total, buf); } void readLine(int fd, std::vector &buf) { IOBlock *first = newIOBlock(); IOBlock *cur = first; ssize_t total = 0; for (;;) { if (cur->size == cur->used) { cur->next = newIOBlock(); cur = cur->next; } ssize_t len = read(fd, cur->data + cur->used, 1); if (0 == len) break; /* eof */ if (0 > len) { perror("read failed"); abort(); } if (cur->data[cur->used] == '\n' || cur->data[cur->used] == '\r') break; cur->used += 1; total += 1; } blocksToVector(first, total, buf); }