forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
2.5 KiB
115 lines
2.5 KiB
/* SPDX-License-Identifier: GPL-2.0 */ |
|
/* |
|
* Lightweight buffered reading library. |
|
* |
|
* Copyright 2019 Google LLC. |
|
*/ |
|
#ifndef __API_IO__ |
|
#define __API_IO__ |
|
|
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
|
|
struct io { |
|
/* File descriptor being read/ */ |
|
int fd; |
|
/* Size of the read buffer. */ |
|
unsigned int buf_len; |
|
/* Pointer to storage for buffering read. */ |
|
char *buf; |
|
/* End of the storage. */ |
|
char *end; |
|
/* Currently accessed data pointer. */ |
|
char *data; |
|
/* Set true on when the end of file on read error. */ |
|
bool eof; |
|
}; |
|
|
|
static inline void io__init(struct io *io, int fd, |
|
char *buf, unsigned int buf_len) |
|
{ |
|
io->fd = fd; |
|
io->buf_len = buf_len; |
|
io->buf = buf; |
|
io->end = buf; |
|
io->data = buf; |
|
io->eof = false; |
|
} |
|
|
|
/* Reads one character from the "io" file with similar semantics to fgetc. */ |
|
static inline int io__get_char(struct io *io) |
|
{ |
|
char *ptr = io->data; |
|
|
|
if (io->eof) |
|
return -1; |
|
|
|
if (ptr == io->end) { |
|
ssize_t n = read(io->fd, io->buf, io->buf_len); |
|
|
|
if (n <= 0) { |
|
io->eof = true; |
|
return -1; |
|
} |
|
ptr = &io->buf[0]; |
|
io->end = &io->buf[n]; |
|
} |
|
io->data = ptr + 1; |
|
return *ptr; |
|
} |
|
|
|
/* Read a hexadecimal value with no 0x prefix into the out argument hex. If the |
|
* first character isn't hexadecimal returns -2, io->eof returns -1, otherwise |
|
* returns the character after the hexadecimal value which may be -1 for eof. |
|
* If the read value is larger than a u64 the high-order bits will be dropped. |
|
*/ |
|
static inline int io__get_hex(struct io *io, __u64 *hex) |
|
{ |
|
bool first_read = true; |
|
|
|
*hex = 0; |
|
while (true) { |
|
int ch = io__get_char(io); |
|
|
|
if (ch < 0) |
|
return ch; |
|
if (ch >= '0' && ch <= '9') |
|
*hex = (*hex << 4) | (ch - '0'); |
|
else if (ch >= 'a' && ch <= 'f') |
|
*hex = (*hex << 4) | (ch - 'a' + 10); |
|
else if (ch >= 'A' && ch <= 'F') |
|
*hex = (*hex << 4) | (ch - 'A' + 10); |
|
else if (first_read) |
|
return -2; |
|
else |
|
return ch; |
|
first_read = false; |
|
} |
|
} |
|
|
|
/* Read a positive decimal value with out argument dec. If the first character |
|
* isn't a decimal returns -2, io->eof returns -1, otherwise returns the |
|
* character after the decimal value which may be -1 for eof. If the read value |
|
* is larger than a u64 the high-order bits will be dropped. |
|
*/ |
|
static inline int io__get_dec(struct io *io, __u64 *dec) |
|
{ |
|
bool first_read = true; |
|
|
|
*dec = 0; |
|
while (true) { |
|
int ch = io__get_char(io); |
|
|
|
if (ch < 0) |
|
return ch; |
|
if (ch >= '0' && ch <= '9') |
|
*dec = (*dec * 10) + ch - '0'; |
|
else if (first_read) |
|
return -2; |
|
else |
|
return ch; |
|
first_read = false; |
|
} |
|
} |
|
|
|
#endif /* __API_IO__ */
|
|
|