Created
July 22, 2020 04:33
-
-
Save memreflect/128ee7052cc0f84faa1cf80254e7a5bc to your computer and use it in GitHub Desktop.
Bounded line input routine `get_line`
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
#include <errno.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include "errval.h" | |
static char const* errstrings[] = { | |
[ErrOK] = "no error", | |
[ErrIO] = "I/O error", | |
[ErrMore] = "more data available", | |
[ErrParam] = "invalid parameter", | |
//[ErrSys] = strerror(errno), | |
[ErrMax] = "unknown error", | |
}; | |
char const* | |
errstr(errval err) { | |
if (err == ErrSys) { | |
return strerror(errno); | |
} else if (err > ErrMax) { | |
err = ErrMax; | |
} | |
return errstrings[err]; | |
} | |
void | |
errprint(errval err, char const* msg) { | |
if (msg) { | |
fprintf(stderr, "%s: ", msg); | |
} | |
fprintf(stderr, "%s\n", errstr(err)); | |
} |
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
#ifndef ERRVAL_H | |
#define ERRVAL_H 1 | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/* | |
* Error constants | |
*/ | |
typedef enum { | |
ErrOK, | |
ErrIO, | |
ErrMore, | |
ErrParam, | |
ErrSys, | |
ErrMax, | |
} errval; | |
/* | |
* Return a string description of an error | |
* | |
* If `err` is `ErrSys`, `strerror(errno)` is returned. | |
*/ | |
char const* errstr(errval); | |
/* | |
* Print a string description of an error to `stderr` | |
* | |
* If `msg` is not a null pointer, it is printed before the error | |
* description, followed by a space and a colon like `perror`. | |
*/ | |
void errprint(errval err, char const* msg); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif /* !ERRVAL_H */ |
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
#include <stdio.h> | |
#include "errval.h" | |
/* | |
* Read a line from standard input | |
* | |
* Upon return, successful or not, the `buffer` argument contains a | |
* null-terminated string that is `size-1` characters or less in length, | |
* and the `len` parameter, if not a null pointer, will contain the | |
* length of that string. | |
* | |
* A newline character, if read, is discarded and causes the function to | |
* return as if `EOF` was encountered. | |
* | |
* The return value is a value suitable for use with `errstr` or | |
* `errprint`. | |
* | |
* Errors: | |
* ErrOK - No error | |
* ErrIO - I/O error (only used if ErrSys is not returned instead) | |
* ErrMore - line was longer than `size-1` characters, excluding \n | |
* ErrParam - buffer is a null pointer, or size is less than 2 | |
* ErrSys - error is stored in errno | |
*/ | |
errval | |
get_line(char* restrict buffer, size_t size, size_t* restrict len) { | |
// size == 0 cannot store any characters. | |
// size == 1 can only store a null terminator. | |
if (!buffer || size < 2) { | |
return ErrParam; | |
} | |
int c; | |
for (size_t i = 0; i < size; i++) { | |
c = getchar(); | |
if (c == '\n' || c == EOF) { | |
buffer[i] = 0; | |
if (len) { | |
*len = i; | |
} | |
if (ferror(stdin)) { | |
if (errno) { | |
return ErrSys; | |
} | |
return ErrIO; | |
} | |
return ErrOK; | |
} | |
buffer[i] = c; | |
} | |
// If we're outside the loop, then we didn't read a full | |
// line. This means we don't have room for a null terminator, | |
// so we need to push the last char back onto stdin. | |
ungetc(c, stdin); | |
buffer[size-1] = 0; | |
if (len) { | |
*len = size-1; | |
} | |
return ErrMore; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment