1 /*
2  * Copyright (C) 2002 - David W. Durham
3  *
4  * This file is part of ReZound, an audio editing application, but
5  * could be used for other applications which could use the PoolFile
6  * class's functionality.
7  *
8  * PoolFile is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published
10  * by the Free Software Foundation; either version 2 of the License,
11  * or (at your option) any later version.
12  *
13  * PoolFile is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
21  */
22 
23 #ifndef __CMultiFile_H__
24 #define __CMultiFile_H__
25 
26 #include "../../config/common.h"
27 
28 #include <stddef.h>
29 #include <stdint.h>
30 
31 #include <string>
32 
33 #include <sys/types.h> // for off_t and ssize_t
34 
35 class CMultiFile
36 {
37 public:
38 	#define MAX_OPEN_FILES 64
39 	typedef uint64_t l_addr_t;	// logical address within the whole (note, this is NOT the l_addr_t given to TPoolFile, it's actually TPoolFile's p_addr_t)
40 
41 	typedef off_t f_addr_t;		// physical address within a file
42 
43 	CMultiFile();
44 
45 	virtual ~CMultiFile();
46 
47 	/* -- Opens the file(s)
48 	 * - initialFilename is the filename of the first file in the possible set of multiple files
49 	 */
50 	void open(const string _initialFilename,const bool canCreate);
isOpen()51 	bool isOpen() const { return opened; }
52 	void close(bool removeFiles=false);
53 
54 	void rename(const string newInitialFilename);
55 
56 
57 	// The seek, tell, read and write methods require that one of these
58 	// be instantiated and a pointer be passed when the method is called
59 	class RHandle // ??? for lack of a better term
60 	{
61 	public:
RHandle()62 		RHandle() { position=0; }
63 	private:
64 		friend class CMultiFile;
65 		CMultiFile::l_addr_t position;
66 	};
67 
68 	void seek(const l_addr_t _position,RHandle &handle);
69 	const l_addr_t tell(RHandle &handle) const;
70 
71 	void read(void *buffer,const l_addr_t count,RHandle &handle);
72 	void read(void *buffer,const l_addr_t count,const l_addr_t _position);
73 
74 	void write(const void *buffer,const l_addr_t count,RHandle &handle);
75 	void write(const void *buffer,const l_addr_t count,const l_addr_t _position);
76 
77 	void setSize(const l_addr_t newSize);
78 
79 	void sync() const;
80 
81 	const l_addr_t getAvailableSize() const;
82 	const l_addr_t getActualSize() const;
83 	const l_addr_t getSize() const;
84 
85 
86 private:
87 	bool opened;
88 
89 	// ??? having this limits the max total size to only
90 	// LOGICAL_MAX_FILE_SIZE * MAX_OPEN_FILES.  I could
91 	// conceive of a list which is all the open files and
92 	// we open and close the files as needed between
93 	// operations.
94 	int openFiles[MAX_OPEN_FILES];
95 
96 	string initialFilename;
97 	uint32_t matchSignature;
98 
99 	l_addr_t totalSize;
100 
101 	size_t openFileCount;
102 
103 	// 512 byte header at the beginning of the file
104 	// I do not write(&RFileHeader) because padding can be different on each platform, the methods are used
105 	struct RFileHeader
106 	{
107 		uint32_t signature;		// signature for CMultiFile
108 		uint32_t matchSignature; 	// signature for this set of files
109 		uint64_t fileCount;		// number of files in this set
110 
111 		// returns the number of bytes read or written
112 		ssize_t read(int fd);
113 		ssize_t write(int fd);
114 		void encodeEndianBeforeWrite();
115 	};
116 
117 	void writeHeaderToFiles();
118 
119 	void openFile(const string &filename,RFileHeader &header,const bool openingFirstFile=false,const bool readHeader=true);
120 
121 	const l_addr_t calcTotalSize() const;
122 
123 	void prvSetSize(const l_addr_t newSize,const l_addr_t forWriteSize);
124 	void setFileSize(const int fileHandle,const f_addr_t newFileSize);
125 
126 	const string buildFilename(size_t which);
127 	static const string buildFilename(size_t which,const string &initialFilename);
128 };
129 
130 #endif
131