1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/*
* =========================================================================
* big_buf_io_z - A library to allow efficient small reads and writes from gzipped files.
* Copyright (c) 1997 Fred M. Erickson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* =========================================================================
*
*
* Routines that let you do a lot of small reads from a gzip-compressed file,
* without a lot of OS penalty. Simply call buf_read_z() instead of read().
* These routines read a file in large chunks and pass you the data in the
* small chunks that you ask for. Note some caveats:
*
* You can't reset the file pointer with lseek() or you will
* mess up these routines.
*
* You can only use these routines with one file at a time,
* since there is only one buffer to hold the data.
*
* If you only have one file to read, you can simply open it
* and begin calling these routines. If you have more than
* one file to read (consecutively, of course), you should use
* buf_open_z() to open the files, so that proper initialization
* gets done. buf_close_z() has been added for completeness, but
* it doesn't do anything except call close().
*
* get_a_line_z() fills a buffer with information until it finds a newline,
* or runs out of space.
*
* These routines depend on the zread() function, in the file gunzip.c
*/
#include <sys/types.h>
#include <fcntl.h>
#include "gzip.h"
int buf_open_z(const char *, int, mode_t, ...);
int buf_close_z(int);
ssize_t buf_read_z(int, void *, size_t);
ssize_t get_a_line_z(int, void *, size_t);
#define BUF_SIZE WSIZE /* This MUST be at least as large as WSIZE, or zread() won't work properly */
static r_place = 0;
static r_size = 0;
static w_place = 0;
static new_flag = 1;
int buf_open_z(const char *pathname, int flags, mode_t mode, ...)
{
r_place = 0;
r_size = 0;
w_place = 0;
new_flag = 1;
if (flags & O_CREAT) {
return(open(pathname, flags, mode));
}
else {
return(open(pathname, flags));
}
}
int
buf_close_z(int fdesc)
{
return(close(fdesc));
}
ssize_t buf_read_z(int filedes, void *buf, size_t nbyte)
{
static char bigbuf[BUF_SIZE];
long amount;
long tmp_nbyte;
char *local_buf;
local_buf = (char *)buf;
tmp_nbyte = nbyte;
while (tmp_nbyte > 0) {
if ((r_size <= 0) || (r_place == r_size)) {
r_size = zread(filedes, bigbuf, BUF_SIZE, new_flag);
if (r_size <= 0) {
return(r_size);
}
r_place = 0;
new_flag = 0;
}
amount = (r_size - r_place) >= tmp_nbyte ? tmp_nbyte : r_size - r_place;
memcpy(local_buf, &bigbuf[r_place], amount);
local_buf = local_buf + amount;
r_place = r_place + amount;
tmp_nbyte = tmp_nbyte - amount;
}
return(nbyte);
}
ssize_t get_a_line_z(int filedes, void *buf, size_t nbyte)
{
long i = 0;
ssize_t ret_val;
while (i < nbyte) {
ret_val = buf_read_z(filedes, buf + i, 1);
if (ret_val != 1) {
return(i);
}
if (*((unsigned char *)buf + i) == '\n') {
return(i + 1);
}
i++;
}
}
|