[Scummvm-cvs-logs] SF.net SVN: scummvm:[42045] tools/branches/gsoc2009-gui

Remere at users.sourceforge.net Remere at users.sourceforge.net
Fri Jul 3 03:28:32 CEST 2009


Revision: 42045
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42045&view=rev
Author:   Remere
Date:     2009-07-03 01:28:31 +0000 (Fri, 03 Jul 2009)

Log Message:
-----------
*Added a File class, RAII like class for file handling, alot easier to use that the standard C functions.
*Added ToolException/FileException to replace calls to exit() and if's to check return values all the time.
*Converted extract_agos to use the new classes (considerably shortened code!). NOTE: parseHelpArguments etc. exit() rather than throw still, so it does not work perfectly yet.
*Changed ULONG to uint32, and UBYTE to uint8

Modified Paths:
--------------
    tools/branches/gsoc2009-gui/compress_agos.cpp
    tools/branches/gsoc2009-gui/extract_agos.cpp
    tools/branches/gsoc2009-gui/util.cpp
    tools/branches/gsoc2009-gui/util.h

Modified: tools/branches/gsoc2009-gui/compress_agos.cpp
===================================================================
--- tools/branches/gsoc2009-gui/compress_agos.cpp	2009-07-02 23:58:05 UTC (rev 42044)
+++ tools/branches/gsoc2009-gui/compress_agos.cpp	2009-07-03 01:28:31 UTC (rev 42045)
@@ -230,9 +230,14 @@
 	}
 }
 
+#define INT 2
+#define INT_STR(x) #x
+
 int export_main(compress_agos)(int argc, char *argv[]) {
 	const char *helptext = "\nUsage: %s [mode] [mode params] [--mac] <infile>\n" kCompressionAudioHelp;
 
+	const char *h = "Something something " INT_STR(INT);
+
 	bool convertMac = false;
 
 	Filename inpath, outpath;

Modified: tools/branches/gsoc2009-gui/extract_agos.cpp
===================================================================
--- tools/branches/gsoc2009-gui/extract_agos.cpp	2009-07-02 23:58:05 UTC (rev 42044)
+++ tools/branches/gsoc2009-gui/extract_agos.cpp	2009-07-03 01:28:31 UTC (rev 42045)
@@ -23,12 +23,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <iostream>
 
 #include "util.h"
 
-typedef unsigned int ULONG;
-typedef unsigned char UBYTE;
-
 size_t filelen;
 #define EndGetM32(a)	((((a)[0])<<24)|(((a)[1])<<16)|(((a)[2])<<8)|((a)[3]))
 
@@ -44,12 +42,12 @@
 #define SD_TYPE_LITERAL (0)
 #define SD_TYPE_MATCH   (1)
 
-int simon_decr(UBYTE *src, UBYTE *dest, ULONG srclen) {
-	UBYTE *s = &src[srclen - 4];
-	ULONG destlen = EndGetM32(s);
-	ULONG bb, x, y;
-	UBYTE *d = &dest[destlen];
-	UBYTE bc, bit, bits, type;
+int simon_decr(uint8 *src, uint8 *dest, uint32 srclen) {
+	uint8 *s = &src[srclen - 4];
+	uint32 destlen = EndGetM32(s);
+	uint32 bb, x, y;
+	uint8 *d = &dest[destlen];
+	uint8 bc, bit, bits, type;
 
 	/* initialise bit buffer */
 	s -= 4;
@@ -134,59 +132,47 @@
 	return 1;
 }
 
-ULONG simon_decr_length(UBYTE *src, ULONG srclen) {
+uint32 simon_decr_length(uint8 *src, uint32 srclen) {
 	return EndGetM32(&src[srclen - 4]);
 }
 
 
-/* - loadfile(filename) loads a file from disk, and returns a pointer to that
- *   loaded file, or returns NULL on failure
- * - call free() on ptr to free memory
- * - size of loaded file is available in global var 'filelen'
+/**
+ * loadfile(filename) loads a file from disk, and returns a pointer to that
+ * loaded file, or returns NULL on failure
+ * call free() on ptr to free memory
+ * size of loaded file is available in global var 'filelen'
+ *
+ * @param name The name of the file to be loaded
  */
-void *loadfile(const char *name) {
-	void *mem = NULL;
-	FILE *fd;
+void *loadfile(const Filename &name) {
+	File file(name, FILEMODE_READ);
 
-	fd = fopen(name, "rb");
-	if (fd != NULL) {
-		if ((fseek(fd, 0, SEEK_END) == 0) && (filelen = ftell(fd))
-		&&	(fseek(fd, 0, SEEK_SET) == 0) && (mem = malloc(filelen))) {
+	// Using global here is not pretty
+	filelen = file.size();
+	void *mem = malloc(file.size());
 
-			if (fread(mem, 1, filelen, fd) < filelen) {
-				free(mem); mem = NULL;
-			}
-		}
+	// Read data
+	file.read(file, 1, filelen);
 
-		fclose(fd);
-	}
-
 	return mem;
 }
 
-/* - savefile(filename, mem, length) saves [length] bytes from [mem] into
- *   the file named by [filename]
- * - returns zero if failed, or non-zero if successful
+/**
+ * Saves N bytes from the buffer to the target file.
+ * Throws FileException on failure
+ * 
+ * @param name The name of the file to save to
+ * @param mem Where to get data from
+ * @param length How many bytes to write
  */
-int savefile(const char *name, void *mem, size_t length) {
-	unsigned int bytesWritten;
-
-	FILE *fd = fopen(name, "wb");
-	if (fd == NULL) {
-		return 0;
-	}
-
-	bytesWritten = fwrite(mem, 1, length, fd);
-	if (bytesWritten != length) {
-		return 0;
-	}
-
-	fclose(fd);
-
-	return 1;
+void savefile(const Filename &name, void *mem, size_t length) {
+	File file(name, FILEMODE_WRITE);
+	file.write(mem, 1, length);
 }
 
-int export_main(extract_agos)(int argc, char *argv[]) {
+// Run the actual tool
+int run(int argc, char *argv[]) {
 	int first_arg = 1;
 	int last_arg = argc;
 
@@ -208,34 +194,40 @@
 	// Loop through all input files
 	for (int parsed_args = first_arg; parsed_args <= last_arg; ++parsed_args) {
 		const char *filename = argv[parsed_args];
-		UBYTE *x = (UBYTE *) loadfile(filename);
+		uint8 *x = (uint8 *)loadfile(filename);
 
 		inpath.setFullPath(filename);
 		outpath.setFullName(inpath.getFullName());
 
-		if (x) {
-			ULONG decrlen = simon_decr_length(x, (ULONG) filelen);
-			UBYTE *out = (UBYTE *) malloc(decrlen);
+		uint32 decrlen = simon_decr_length(x, (uint32) filelen);
+		uint8 *out = (uint8 *) malloc(decrlen);
 
-			if (out) {
-				if (simon_decr(x, out, filelen)) {
-					savefile(outpath.getFullPath(), out, decrlen);
-				}
-				else {
-					notice("%s: decrunch error\n", filename);
-				}
-
-				free((void *) x);
+		if (out) {
+			if (simon_decr(x, out, filelen)) {
+				savefile(outpath.getFullPath(), out, decrlen);
 			}
+			else {
+				notice("%s: decrunch error\n", filename);
+			}
+
+			free((void *) x);
 		}
-		else {
-			notice("Could not load file %s\n", filename);
-		}
 	}
 
 	return 0;
 }
 
+int export_main(extract_agos)(int argc, char *argv[]) {
+	try {
+		run(argc, argv);
+	} catch(ToolException &err) {
+		std::cout << "FATAL ERROR: " << err.what();
+		return err._retcode;
+	}
+	return 0;
+}
+}
+
 #if defined(UNIX) && defined(EXPORT_MAIN)
 int main(int argc, char *argv[]) __attribute__((weak));
 int main(int argc, char *argv[]) {

Modified: tools/branches/gsoc2009-gui/util.cpp
===================================================================
--- tools/branches/gsoc2009-gui/util.cpp	2009-07-02 23:58:05 UTC (rev 42044)
+++ tools/branches/gsoc2009-gui/util.cpp	2009-07-03 01:28:31 UTC (rev 42045)
@@ -146,6 +146,7 @@
 	return sz;
 }
 
+// Filenname implementation
 Filename::Filename(const char *path) {
 	strcpy(_path, path);
 }
@@ -264,6 +265,155 @@
 	return out;
 }
 
+// File interface
+// While this does massive duplication of the code above, it's required to make sure that
+// unconverted tools are backwards-compatible
+
+File::File() {
+	_file = NULL;
+	_mode = FILEMODE_READ;
+}
+
+File::File(const Filename &filepath, FileMode mode) {
+	open(filepath.getFullPath(), mode);
+}
+
+File::File(const char *filepath, FileMode mode) {
+	open(filepath, mode);
+}
+
+File::~File() {
+	if (_file)
+		fclose(_file);
+}
+
+void File::open(const char *filepath, FileMode mode) {
+	assert(mode == FILEMODE_READ || mode == FILEMODE_WRITE);
+
+	if (mode == FILEMODE_READ) {
+		_file = fopen(filepath, "rb");
+	} else {
+		_file = fopen(filepath, "wb");
+	}
+	_mode = mode;
+	_name.setFullPath(filepath);
+
+	if (_file)
+		throw FileException("Could not open file " + std::string(filepath));
+}
+
+uint8 File::readByte() {
+	if (!_file) 
+		throw FileException("File is not open");
+	if (_mode != FILEMODE_READ)
+		throw FileException("Tried to read from file opened in write mode (" + std::string(_name.getFullPath()) + ")");
+
+	int u8 = fgetc(_file);
+	if (u8 == EOF)
+		throw FileException("Read beyond the end of file (" + std::string(_name.getFullPath()) + ")");
+	return (uint8)u8;
+}
+
+uint16 File::readU16BE() {
+	uint16 ret = 0;
+	ret |= readByte() << 8;
+	ret |= readByte();
+	return ret;
+}
+
+uint16 File::readU16LE() {
+	uint16 ret = 0;
+	ret |= readByte();
+	ret |= readByte() << 8;
+	return ret;
+}
+
+uint32 File::readU32BE() {
+	uint32 ret = 0;
+	ret |= readByte() << 24;
+	ret |= readByte() << 16;
+	ret |= readByte() << 8;
+	ret |= readByte();
+	return ret;
+}
+
+uint32 File::readU32LE() {
+	uint32 ret = 0;
+	ret |= readByte();
+	ret |= readByte() << 8;
+	ret |= readByte() << 16;
+	ret |= readByte() << 24;
+	return ret;
+}
+
+void File::read(void *data, size_t elementSize, size_t elementCount) {
+	if (!_file) 
+		throw FileException("File is not open");
+	if (_mode != FILEMODE_READ)
+		throw FileException("Tried to read from file opened in write mode (" + std::string(_name.getFullPath()) + ")");
+
+	size_t data_read = fread(data, elementSize, elementCount, _file);
+	if (data_read != elementCount)
+		throw FileException("Read beyond the end of file (" + std::string(_name.getFullPath()) + ")");
+}
+
+void File::writeByte(uint8 b) {
+	if (!_file) 
+		throw FileException("File  is not open");
+	if (_mode != FILEMODE_WRITE)
+		throw FileException("Tried to write to a file opened in read mode (" + std::string(_name.getFullPath()) + ")");
+
+	if (fwrite(&b, 1, 1, _file) == 1)
+		throw FileException("Could not write to file (" + std::string(_name.getFullPath()) + ")");
+}
+
+void File::writeU16BE(uint16 value) {
+	writeByte((uint8)(value >> 8));
+	writeByte((uint8)(value));
+}
+
+void File::writeU16LE(uint16 value) {
+	writeByte((uint8)(value));
+	writeByte((uint8)(value >> 8));
+}
+
+void File::writeU32BE(uint32 value) {
+	writeByte((uint8)(value >> 24));
+	writeByte((uint8)(value >> 16));
+	writeByte((uint8)(value >> 8));
+	writeByte((uint8)(value));
+}
+
+void File::writeU32LE(uint32 value) {
+	writeByte((uint8)(value));
+	writeByte((uint8)(value >> 8));
+	writeByte((uint8)(value >> 16));
+	writeByte((uint8)(value >> 24));
+}
+
+void File::write(const void *data, size_t elementSize, size_t elementCount) {
+	if (!_file) 
+		throw FileException("File is not open");
+	if (_mode != FILEMODE_WRITE)
+		throw FileException("Tried to write to file opened in read mode (" + std::string(_name.getFullPath()) + ")");
+
+	size_t data_read = fwrite(data, elementSize, elementCount, _file);
+	if (data_read != elementCount)
+		throw FileException("Could not write to file (" + std::string(_name.getFullPath()) + ")");
+}
+
+uint32 File::size() {
+	uint32 sz;
+	uint32 pos = ftell(_file);
+	fseek(_file, 0, SEEK_END);
+	sz = ftell(_file);
+	fseek(_file, pos, SEEK_SET);
+	return sz;
+}
+
+
+// Functions to parse the command line
+
 void displayHelp(const char *msg, const char *exename) {
 	if (!msg) {
 		printf("\nUsage: %s [-o <output dir> = out/] <file 1> ... <file n>\n", exename);

Modified: tools/branches/gsoc2009-gui/util.h
===================================================================
--- tools/branches/gsoc2009-gui/util.h	2009-07-02 23:58:05 UTC (rev 42044)
+++ tools/branches/gsoc2009-gui/util.h	2009-07-03 01:28:31 UTC (rev 42045)
@@ -39,7 +39,9 @@
 #include <process.h>
 #endif
 
+#include <string>
 
+
 /*
  * Some useful types
  */
@@ -220,6 +222,41 @@
 void debug(int level, const char *s, ...);
 void notice(const char *s, ...);
 
+// Below this line are more C++ ish interface
+// Above is kept for compatibility with non-converted tools
+
+/**
+ * Throw an exception of this type (or subtype of it), if the tool fails fatally.
+ * This type is intended for general errors
+ */
+class ToolException : public std::runtime_error {
+public:
+	/**
+	 * Construct an exception, with an appropriate error message
+	 * A return value for the tool should be supplied if none is appropriate
+	 * @todo If the tools are even more C++ized, the tool should decide retcode itself, not by exception
+	 *
+	 * @param error The error message
+	 * @param retcode The return value of the process
+	 */
+	ToolException(std::string error, int retcode = -1) : std::runtime_error(error), _retcode(retcode) {}
+
+	int _retcode;
+};
+
+/**
+ * Something unexpected happened while reading / writing to a file
+ * Usually premature end, or that it could not be opened (write / read protected)
+ */
+class FileException : public ToolException {
+public: 
+	FileException(std::string error, int retcode = -1) : ToolException(error, retcode) {}
+};
+
+/**
+ * A file path, can be queried for different parts
+ * and the parts can be modified seperately
+ */
 struct Filename {
 	char _path[1024];
 
@@ -249,6 +286,133 @@
 	return f1.equals(&f2);
 }
 
+/**
+ * Possible modes for opening files
+ */
+enum FileMode {
+	FILEMODE_READ,
+	FILEMODE_WRITE
+};
+
+/**
+ * A basic wrapper around the FILE class
+ * Offers functionality to write words easily
+ */
+class File {
+public:
+	/**
+	 * Opens the given file path as an in/out stream, depending on the second argument
+	 * File is always opened in binary mode
+	 *
+	 * @param filename The file to open
+	 * @param mode The mode to open the file in
+	 */
+	File(const Filename &filename, FileMode mode);
+	File(const char *filename, FileMode mode);
+	/**
+	 * Create an empty file, used for two-step construction
+	 */
+	File();
+	~File();
+
+	/**
+	 * Opens the given file path as an in/out stream, depending on the second argument
+	 * File is always opened in binary mode
+	 *
+	 * @param filename The file to open
+	 * @param mode The mode to open the file in
+	 */
+	void open(const char *filename, FileMode mode);
+	
+	
+	/**
+	 * Read a single unsigned byte
+	 * Throws FileException if file is not open / if read failed ended prematurely
+	 */
+	uint8 readByte();
+	/**
+	 * Read a single 16-bit word, big endian
+	 * Throws FileException if file is not open / if read failed
+	 */
+	uint16 readU16BE();
+	/**
+	 * Read a single 16-bit word, little endian
+	 * Throws FileException if file is not open / if read failed
+	 */
+	uint16 readU16LE();
+	/**
+	 * Read a single 32-bit word, big endian
+	 * Throws FileException if file is not open / if read failed
+	 */
+	uint32 readU32BE();
+	/**
+	 * Read a single 32-bit word, little endian
+	 * Throws FileException if file is not open / if read failed
+	 */
+	uint32 readU32LE();
+
+	/**
+	 * Works the same way as fread, but throws on error or if it could not read all elements
+	 *
+	 * @param data Where to put the read data
+	 * @param elementSize the size of one element (in bytes)
+	 * @param elementCount the number of elements to read
+	 */
+	void read(void *data, size_t elementSize, size_t elementCount);
+
+	
+	/**
+	 * Writes a single byte to the file
+	 * Throws FileException if file is not open / if write failed
+	 */
+	void writeByte(uint8 b);
+	/**
+	 * Writes a single 16-bit word to the file, big endian
+	 * Throws FileException if file is not open / if write failed
+	 */
+	void writeU16BE(uint16 value);
+	/**
+	 * Writes a single 16-bit word to the file, little endian
+	 * Throws FileException if file is not open / if write failed
+	 */
+	void writeU16LE(uint16 value);
+	/**
+	 * Writes a single 32-bit word to the file, big endian
+	 * Throws FileException if file is not open / if write failed
+	 */
+	void writeU32BE(uint32 value);
+	/**
+	 * Writes a single 32-bit word to the file, little endian
+	 * Throws FileException if file is not open / if write failed
+	 */
+	void writeU32LE(uint32 value);
+
+	/**
+	 * Works the same way as fwrite, but throws on error or if it could not write all data
+	 *
+	 * @param data Where to read data from
+	 * @param elementSize the size of one element (in bytes)
+	 * @param elementCount the number of elements to read
+	 */
+	void write(const void *data, size_t elementSize, size_t elementCount);
+
+	/**
+	 * Returns the length of the file, in bytes, does not move the cursor
+	 */
+	uint32 size();
+
+	/** We implicitly convert into a FILE, so we can use fread() etc. directly */
+	operator FILE *() {return _file;}
+
+protected:
+	/** The mode the file was opened in */
+	FileMode _mode;
+	/** Internal reference to the file */
+	FILE *_file;
+	/** The name of the file, used for better error messages */
+	Filename _name;
+};
+
 void displayHelp(const char *msg = NULL, const char *exename = NULL);
 void parseHelpArguments(const char * const argv[], int argc, const char *msg = NULL);
 bool parseOutputFileArguments(Filename *outputname, const char * const argv[], int argc, int start_arg);


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list