-
-
Save allenk/e7060b15fd28ff4ba77d9a6a03698397 to your computer and use it in GitHub Desktop.
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
// MSVC apparently doesn't have C's getline | |
// This is a poor man's implementation of it using fgets. | |
// See the man page at | |
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html | |
size_t getline(char** buf, size_t* bufLen, FILE* f) | |
{ | |
if (buf == nullptr || bufLen == nullptr) | |
{ | |
errno = EINVAL; | |
return -1; | |
} | |
if (fgets(*buf, *bufLen, f) != *buf) | |
return -1; | |
while (true) | |
{ | |
const size_t amountRead = strlen(*buf); | |
// If the length of the string is less than the whole buffer | |
// (minus the last space for \0) or the last character is a newline, | |
// we win. Done. | |
if (amountRead != *bufLen - 1 || (*buf)[amountRead - 1] == '\n') | |
return amountRead; | |
// We didn't have enought room, expand with realloc. | |
// First make sure we can. | |
// If we can't take any more, give up. | |
if (*bufLen == SSIZE_MAX) | |
{ | |
errno = EOVERFLOW; | |
return -1; | |
} | |
// If the MSB of bufLen is 1, doubling will overflow. | |
const bool willOverflow = (*bufLen >> (sizeof(size_t) * 8 - 1)) == 1; | |
const size_t newSize = willOverflow ? SSIZE_MAX : *bufLen * 2; | |
char* newBuf = static_cast<char*>(realloc(*buf, newSize)); | |
if (newBuf == nullptr) | |
{ | |
errno = ENOMEM; | |
return -1; | |
} | |
// We succeeded in expanding. | |
*buf = newBuf; | |
*bufLen = newSize; | |
// Keep reading where we left off | |
char* const resumePoint = *buf + amountRead; | |
if (fgets(resumePoint, *bufLen - amountRead, f) != resumePoint) | |
return -1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment