vcs-svn: teach line_buffer about temporary files

It can sometimes be useful to write information temporarily to file,
to read back later.  These functions allow a program to use the
line_buffer facilities when doing so.

It works like this:

 1. find a unique filename with buffer_tmpfile_init.
 2. rewind with buffer_tmpfile_rewind.  This returns a stdio
    handle for writing.
 3. when finished writing, declare so with
    buffer_tmpfile_prepare_to_read.  The return value indicates
    how many bytes were written.
 4. read whatever portion of the file is needed.
 5. if finished, remove the temporary file with buffer_deinit.
    otherwise, go back to step 2,

The svn support would use this to buffer the postimage from delta
application until the length is known and fast-import can receive
the resulting blob.

Based-on-patch-by: David Barr <david.barr@cordelta.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
This commit is contained in:
Jonathan Nieder 2011-01-02 21:10:59 -06:00
parent cb3f87cf1b
commit b1c9b798a6
3 changed files with 52 additions and 1 deletions

View File

@ -25,6 +25,14 @@ int buffer_fdinit(struct line_buffer *buf, int fd)
return 0;
}
int buffer_tmpfile_init(struct line_buffer *buf)
{
buf->infile = tmpfile();
if (!buf->infile)
return -1;
return 0;
}
int buffer_deinit(struct line_buffer *buf)
{
int err;
@ -35,6 +43,22 @@ int buffer_deinit(struct line_buffer *buf)
return err;
}
FILE *buffer_tmpfile_rewind(struct line_buffer *buf)
{
rewind(buf->infile);
return buf->infile;
}
long buffer_tmpfile_prepare_to_read(struct line_buffer *buf)
{
long pos = ftell(buf->infile);
if (pos < 0)
return error("ftell error: %s", strerror(errno));
if (fseek(buf->infile, 0, SEEK_SET))
return error("seek error: %s", strerror(errno));
return pos;
}
int buffer_read_char(struct line_buffer *buf)
{
return fgetc(buf->infile);

View File

@ -15,12 +15,17 @@ struct line_buffer {
int buffer_init(struct line_buffer *buf, const char *filename);
int buffer_fdinit(struct line_buffer *buf, int fd);
int buffer_deinit(struct line_buffer *buf);
void buffer_reset(struct line_buffer *buf);
int buffer_tmpfile_init(struct line_buffer *buf);
FILE *buffer_tmpfile_rewind(struct line_buffer *buf); /* prepare to write. */
long buffer_tmpfile_prepare_to_read(struct line_buffer *buf);
char *buffer_read_line(struct line_buffer *buf);
char *buffer_read_string(struct line_buffer *buf, uint32_t len);
int buffer_read_char(struct line_buffer *buf);
void buffer_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
void buffer_reset(struct line_buffer *buf);
#endif

View File

@ -24,6 +24,28 @@ The calling program:
When finished, the caller can use `buffer_reset` to deallocate
resources.
Using temporary files
---------------------
Temporary files provide a place to store data that should not outlive
the calling program. A program
- initializes a `struct line_buffer` to LINE_BUFFER_INIT
- requests a temporary file with `buffer_tmpfile_init`
- acquires an output handle by calling `buffer_tmpfile_rewind`
- uses standard I/O functions like `fprintf` and `fwrite` to fill
the temporary file
- declares writing is over with `buffer_tmpfile_prepare_to_read`
- can re-read what was written with `buffer_read_line`,
`buffer_read_string`, and so on
- can reuse the temporary file by calling `buffer_tmpfile_rewind`
again
- removes the temporary file with `buffer_deinit`, perhaps to
reuse the line_buffer for some other file.
When finished, the calling program can use `buffer_reset` to deallocate
resources.
Functions
---------