[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