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
|
/*(LGPL)
---------------------------------------------------------------------------
pfile.h - Portable File Access Toolkit
---------------------------------------------------------------------------
* Copyright (C) 2002, David Olofson
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _PFILE_H_
#define _PFILE_H_
////////////////////////////////////////////////////////////
// Note that these classes can keep track of only one
// chunk at a time! Recursive chunk-inside-chunk is *NOT*
// supported.
////////////////////////////////////////////////////////////
//Create a little endian "FOURCC" ID code. (That is, 'a' will be
//first if the integer result is stored in little endian format
//in a file.)
#define MAKE_4CC(a, b, c, d) \
((a)&0xff | ((b)<<8)&0xff00 | \
((c)<<16)&0xff0000 | ((d)<<24)&0xff000000)
////////////////////////////////////////////////////////////
// pfile_t - Portable File Access Base Class
////////////////////////////////////////////////////////////
// Handles the reading and writing of data from/to file
// via the internal buffer.
//
// Reading can be done either directly from the file, or
// through the internal buffer.
//
// To read through the buffer, the desired number of
// bytes (for example, all bytes of a chunk) must be
// read into the buffer using read_buffer(). Subsequent
// reads will be from the buffer, and end-of-buffer is
// treated like EOF.
//
// Writing is always done to the buffer. To actually
// write data to file, call write_buffer().
//
// IMPORTANT:
// Written data is *lost* if the pfile object
// is destroyed before write_buffer() is called!
//
// Reading RIFF style chunks:
// Use chunk_read() to read the entire chunk into
// the internal buffer. If this succeeds,
// chunk_type() and chunk_size() will return
// information about the chunk, and subsequent
// read() calls will read from the data section of
// the chunk. Use chunk_end() to stop reading, and
// discard the buffer. The next read() will start
// at the first byte after the end of the chunk.
//
// Writing RIFF style chunks:
// Use chunk_write() to set the type of the chunk
// to write. Subsequent write()ing will be done to
// the internal buffer, which will grow as needed.
// Use chunk_end() to write the whole chunk, with
// the correct size and all data. chunk_end() will
// discard the buffer and return the object to
// "direct" operation.
//
class pfile_t
{
FILE *f; //Just a plain file handle...
int _status; // < 0 if there was an error
int bufsize; //Actual malloc()ed size of buffer
int bufused; //Current buffer write position
int bufpos; //Current buffer read position
char *buffer; //Read/write buffer
int chunk_id; //Chunk type ID
int chunk_writing; //1 if we're building a chunk for writing
// Initialize buffer for writing. Subsequent write() calls
// will write to the buffer instead of the file.
int buffer_init();
// Initialize buffer, and read 'len' bytes into it.
// Subsequent read() calls will read from the buffer
// instead of the file.
int buffer_read(int len);
//Unbuffered write operations
int write_ub(void *data, int len);
int write_ub(unsigned int x);
int write_ub(int x);
public:
pfile_t(FILE *file);
virtual ~pfile_t();
int status(); //Read and reset current status.
int status(int new_status); //Set (provided the current status
// >= 0) and return (new) status
//These return # of bytes read, or -1 in case of EOF, or an error.
int read(void *data, int len);
int read(unsigned int &x);
int read(int &x);
void buffer_close(); //Discard the buffer and return to
//"direct" operation.
//These return # of bytes written, or -1 in case of EOF, or an error.
int write(void *data, int len);
int write(unsigned int x);
int write(int x);
int buffer_write(); //Write the whole buffer to the file.
//This will flush the buffer as well.
//RIFF style chunk handling
int chunk_read();
int chunk_type() { return chunk_id; }
int chunk_size() { return bufused; }
int chunk_write(int id);
int chunk_end();
};
#endif
|