--- /dev/null
+/*
+ * PhysicsFS File abstraction - ruby interface
+ *
+ * Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
+ * License:: LGPL
+ */
+
+#include "physfs.h"
+#include "ruby.h"
+
+#include "rb_physfs.h"
+#include "rb_physfs_file.h"
+#include "physfsrwops.h"
+
+VALUE classPhysfsFile;
+
+/*
+ * construct new PhysicsFS::File object
+ */
+VALUE physfs_file_new (PHYSFS_File *file)
+{
+ if (file == 0)
+ return Qnil;
+
+ return Data_Wrap_Struct (classPhysfsFile, 0, 0, file);
+}
+
+/*
+ * PhysicsFS::File#close
+ *
+ * Close the file. It's illegal to use the object after its closure.
+ */
+VALUE physfs_file_close (VALUE self)
+{
+ int result;
+ PHYSFS_File *file;
+ Data_Get_Struct (self, PHYSFS_File, file);
+
+ if (file == 0)
+ return Qfalse;
+
+ result = PHYSFS_close (file);
+ DATA_PTR(self) = 0;
+
+ if (result)
+ return Qtrue;
+ return Qfalse;
+}
+
+/*
+ * PhysicsFS::File#read obj_size, num_objects
+ *
+ * Read *objCount* objects which are *objSize* each.
+ * return String instance containing raw data or nil if failure.
+ * #length of string will reflect real number of objects read.
+ */
+VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount)
+{
+ int objRead;
+ void *buffer;
+ VALUE result;
+ PHYSFS_File *file;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil; //wasted file - no read possible
+
+ buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
+ if (buffer == 0)
+ return Qnil;
+
+ objRead = PHYSFS_read (file, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
+ if (objRead == -1)
+ {
+ free (buffer);
+ return Qnil;
+ }
+
+ result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
+ free (buffer);
+ return result;
+}
+
+/*
+ * PhysicsFS::File#write buffer, obj_size, num_objects
+ *
+ * return nil on failure or number of objects written.
+ */
+VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount)
+{
+ int result;
+ PHYSFS_File *file;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil;
+
+ result = PHYSFS_write (file, STR2CSTR(buf),
+ FIX2UINT(objSize), FIX2UINT(objCount));
+ if (result == -1)
+ return Qnil;
+
+ return INT2FIX(result);
+}
+
+/*
+ * PhysicsFS::File#eof?
+ */
+VALUE physfs_file_eof (VALUE self)
+{
+ int result;
+ PHYSFS_File *file;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil;
+
+ result = PHYSFS_eof (file);
+
+ if (result)
+ return Qtrue;
+
+ return Qfalse;
+}
+
+/*
+ * PhysicsFS::File#tell
+ *
+ * tells current position in file
+ */
+VALUE physfs_file_tell (VALUE self)
+{
+ int result;
+ PHYSFS_File *file;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil;
+
+ result = PHYSFS_tell (file);
+
+ if (result == -1)
+ return Qnil;
+
+ return INT2FIX(result);
+}
+
+/*
+ * PhysicsFS::File#seek pos
+ *
+ * seek to pos in file
+ */
+VALUE physfs_file_seek (VALUE self, VALUE pos)
+{
+ int result;
+ PHYSFS_File *file;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil;
+
+ result = PHYSFS_seek (file, FIX2LONG(pos));
+
+ if (result)
+ return Qtrue;
+
+ return Qfalse;
+}
+
+/*
+ * PhysicsFS::File#length
+ */
+VALUE physfs_file_length (VALUE self)
+{
+ int result;
+ PHYSFS_File *file;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil;
+
+ result = PHYSFS_fileLength (file);
+
+ if (result == -1)
+ return Qnil;
+
+ return INT2FIX(result);
+}
+
+/*
+ * PhysicsFS::File#to_rwops
+ *
+ * File object is converted to RWops object.
+ * File object becomes unusable after that - every operation
+ * should be done through new-born RWops object.
+ */
+VALUE physfs_file_to_rwops (VALUE self)
+{
+ PHYSFS_File *file;
+ SDL_RWops *rwops;
+
+ Data_Get_Struct (self, PHYSFS_File, file);
+ if (file == 0)
+ return Qnil;
+
+ rwops = PHYSFSRWOPS_makeRWops (file);
+ if (rwops == 0)
+ return Qnil;
+
+ DATA_PTR(self) = 0; // oh, gosh, we've sacrificed ourselves!
+ return sdl_rwops_new (rwops);
+}
+
+void init_physfs_file (void)
+{
+ classPhysfsFile = rb_define_class_under (modulePhysfs, "File", rb_cObject);
+
+ rb_define_method (classPhysfsFile, "close", physfs_file_close, 0);
+ rb_define_method (classPhysfsFile, "eof?", physfs_file_eof, 0);
+ rb_define_method (classPhysfsFile, "tell", physfs_file_tell, 0);
+ rb_define_method (classPhysfsFile, "seek", physfs_file_seek, 1);
+ rb_define_method (classPhysfsFile, "length", physfs_file_length, 0);
+ rb_define_method (classPhysfsFile, "read", physfs_file_read, 2);
+ rb_define_method (classPhysfsFile, "write", physfs_file_write, 3);
+ rb_define_method (classPhysfsFile, "to_rwops", physfs_file_to_rwops, 0);
+}