98 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
| /*
 | |
|  * Licensed under a two-clause BSD-style license.
 | |
|  * See LICENSE for details.
 | |
|  */
 | |
| 
 | |
| #include "git-compat-util.h"
 | |
| #include "line_buffer.h"
 | |
| #include "obj_pool.h"
 | |
| 
 | |
| #define LINE_BUFFER_LEN 10000
 | |
| #define COPY_BUFFER_LEN 4096
 | |
| 
 | |
| /* Create memory pool for char sequence of known length */
 | |
| obj_pool_gen(blob, char, 4096)
 | |
| 
 | |
| static char line_buffer[LINE_BUFFER_LEN];
 | |
| static char byte_buffer[COPY_BUFFER_LEN];
 | |
| static FILE *infile;
 | |
| 
 | |
| int buffer_init(const char *filename)
 | |
| {
 | |
| 	infile = filename ? fopen(filename, "r") : stdin;
 | |
| 	if (!infile)
 | |
| 		return -1;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int buffer_deinit(void)
 | |
| {
 | |
| 	int err;
 | |
| 	if (infile == stdin)
 | |
| 		return ferror(infile);
 | |
| 	err = ferror(infile);
 | |
| 	err |= fclose(infile);
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| /* Read a line without trailing newline. */
 | |
| char *buffer_read_line(void)
 | |
| {
 | |
| 	char *end;
 | |
| 	if (!fgets(line_buffer, sizeof(line_buffer), infile))
 | |
| 		/* Error or data exhausted. */
 | |
| 		return NULL;
 | |
| 	end = line_buffer + strlen(line_buffer);
 | |
| 	if (end[-1] == '\n')
 | |
| 		end[-1] = '\0';
 | |
| 	else if (feof(infile))
 | |
| 		; /* No newline at end of file.  That's fine. */
 | |
| 	else
 | |
| 		/*
 | |
| 		 * Line was too long.
 | |
| 		 * There is probably a saner way to deal with this,
 | |
| 		 * but for now let's return an error.
 | |
| 		 */
 | |
| 		return NULL;
 | |
| 	return line_buffer;
 | |
| }
 | |
| 
 | |
| char *buffer_read_string(uint32_t len)
 | |
| {
 | |
| 	char *s;
 | |
| 	blob_free(blob_pool.size);
 | |
| 	s = blob_pointer(blob_alloc(len + 1));
 | |
| 	s[fread(s, 1, len, infile)] = '\0';
 | |
| 	return ferror(infile) ? NULL : s;
 | |
| }
 | |
| 
 | |
| void buffer_copy_bytes(uint32_t len)
 | |
| {
 | |
| 	uint32_t in;
 | |
| 	while (len > 0 && !feof(infile) && !ferror(infile)) {
 | |
| 		in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
 | |
| 		in = fread(byte_buffer, 1, in, infile);
 | |
| 		len -= in;
 | |
| 		fwrite(byte_buffer, 1, in, stdout);
 | |
| 		if (ferror(stdout)) {
 | |
| 			buffer_skip_bytes(len);
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void buffer_skip_bytes(uint32_t len)
 | |
| {
 | |
| 	uint32_t in;
 | |
| 	while (len > 0 && !feof(infile) && !ferror(infile)) {
 | |
| 		in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
 | |
| 		in = fread(byte_buffer, 1, in, infile);
 | |
| 		len -= in;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void buffer_reset(void)
 | |
| {
 | |
| 	blob_reset();
 | |
| }
 |