e7bc230fcbf5dc021e8a5e8aa6f9ec66ce06ad6d
   1/*
   2 * Licensed under a two-clause BSD-style license.
   3 * See LICENSE for details.
   4 */
   5
   6#include "git-compat-util.h"
   7#include "line_buffer.h"
   8#include "strbuf.h"
   9
  10#define COPY_BUFFER_LEN 4096
  11static struct line_buffer buf_ = LINE_BUFFER_INIT;
  12static struct line_buffer *buf;
  13
  14int buffer_init(const char *filename)
  15{
  16        buf = &buf_;
  17
  18        buf->infile = filename ? fopen(filename, "r") : stdin;
  19        if (!buf->infile)
  20                return -1;
  21        return 0;
  22}
  23
  24int buffer_deinit(void)
  25{
  26        int err;
  27        if (buf->infile == stdin)
  28                return ferror(buf->infile);
  29        err = ferror(buf->infile);
  30        err |= fclose(buf->infile);
  31        return err;
  32}
  33
  34/* Read a line without trailing newline. */
  35char *buffer_read_line(void)
  36{
  37        char *end;
  38        if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile))
  39                /* Error or data exhausted. */
  40                return NULL;
  41        end = buf->line_buffer + strlen(buf->line_buffer);
  42        if (end[-1] == '\n')
  43                end[-1] = '\0';
  44        else if (feof(buf->infile))
  45                ; /* No newline at end of file.  That's fine. */
  46        else
  47                /*
  48                 * Line was too long.
  49                 * There is probably a saner way to deal with this,
  50                 * but for now let's return an error.
  51                 */
  52                return NULL;
  53        return buf->line_buffer;
  54}
  55
  56char *buffer_read_string(uint32_t len)
  57{
  58        strbuf_reset(&buf->blob_buffer);
  59        strbuf_fread(&buf->blob_buffer, len, buf->infile);
  60        return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
  61}
  62
  63void buffer_copy_bytes(uint32_t len)
  64{
  65        char byte_buffer[COPY_BUFFER_LEN];
  66        uint32_t in;
  67        while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
  68                in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
  69                in = fread(byte_buffer, 1, in, buf->infile);
  70                len -= in;
  71                fwrite(byte_buffer, 1, in, stdout);
  72                if (ferror(stdout)) {
  73                        buffer_skip_bytes(len);
  74                        return;
  75                }
  76        }
  77}
  78
  79void buffer_skip_bytes(uint32_t len)
  80{
  81        char byte_buffer[COPY_BUFFER_LEN];
  82        uint32_t in;
  83        while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
  84                in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
  85                in = fread(byte_buffer, 1, in, buf->infile);
  86                len -= in;
  87        }
  88}
  89
  90void buffer_reset(void)
  91{
  92        strbuf_release(&buf->blob_buffer);
  93}