/*(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