linux/tools/lib/api/io.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Lightweight buffered reading library.
   4 *
   5 * Copyright 2019 Google LLC.
   6 */
   7#ifndef __API_IO__
   8#define __API_IO__
   9
  10#include <stdlib.h>
  11#include <unistd.h>
  12
  13struct io {
  14        /* File descriptor being read/ */
  15        int fd;
  16        /* Size of the read buffer. */
  17        unsigned int buf_len;
  18        /* Pointer to storage for buffering read. */
  19        char *buf;
  20        /* End of the storage. */
  21        char *end;
  22        /* Currently accessed data pointer. */
  23        char *data;
  24        /* Set true on when the end of file on read error. */
  25        bool eof;
  26};
  27
  28static inline void io__init(struct io *io, int fd,
  29                            char *buf, unsigned int buf_len)
  30{
  31        io->fd = fd;
  32        io->buf_len = buf_len;
  33        io->buf = buf;
  34        io->end = buf;
  35        io->data = buf;
  36        io->eof = false;
  37}
  38
  39/* Reads one character from the "io" file with similar semantics to fgetc. */
  40static inline int io__get_char(struct io *io)
  41{
  42        char *ptr = io->data;
  43
  44        if (io->eof)
  45                return -1;
  46
  47        if (ptr == io->end) {
  48                ssize_t n = read(io->fd, io->buf, io->buf_len);
  49
  50                if (n <= 0) {
  51                        io->eof = true;
  52                        return -1;
  53                }
  54                ptr = &io->buf[0];
  55                io->end = &io->buf[n];
  56        }
  57        io->data = ptr + 1;
  58        return *ptr;
  59}
  60
  61/* Read a hexadecimal value with no 0x prefix into the out argument hex. If the
  62 * first character isn't hexadecimal returns -2, io->eof returns -1, otherwise
  63 * returns the character after the hexadecimal value which may be -1 for eof.
  64 * If the read value is larger than a u64 the high-order bits will be dropped.
  65 */
  66static inline int io__get_hex(struct io *io, __u64 *hex)
  67{
  68        bool first_read = true;
  69
  70        *hex = 0;
  71        while (true) {
  72                int ch = io__get_char(io);
  73
  74                if (ch < 0)
  75                        return ch;
  76                if (ch >= '0' && ch <= '9')
  77                        *hex = (*hex << 4) | (ch - '0');
  78                else if (ch >= 'a' && ch <= 'f')
  79                        *hex = (*hex << 4) | (ch - 'a' + 10);
  80                else if (ch >= 'A' && ch <= 'F')
  81                        *hex = (*hex << 4) | (ch - 'A' + 10);
  82                else if (first_read)
  83                        return -2;
  84                else
  85                        return ch;
  86                first_read = false;
  87        }
  88}
  89
  90/* Read a positive decimal value with out argument dec. If the first character
  91 * isn't a decimal returns -2, io->eof returns -1, otherwise returns the
  92 * character after the decimal value which may be -1 for eof. If the read value
  93 * is larger than a u64 the high-order bits will be dropped.
  94 */
  95static inline int io__get_dec(struct io *io, __u64 *dec)
  96{
  97        bool first_read = true;
  98
  99        *dec = 0;
 100        while (true) {
 101                int ch = io__get_char(io);
 102
 103                if (ch < 0)
 104                        return ch;
 105                if (ch >= '0' && ch <= '9')
 106                        *dec = (*dec * 10) + ch - '0';
 107                else if (first_read)
 108                        return -2;
 109                else
 110                        return ch;
 111                first_read = false;
 112        }
 113}
 114
 115#endif /* __API_IO__ */
 116