Upload 2.0.2
[physicsfs] / extras / physfs_rb / physfs / rb_physfs_file.c
diff --git a/extras/physfs_rb/physfs/rb_physfs_file.c b/extras/physfs_rb/physfs/rb_physfs_file.c
new file mode 100644 (file)
index 0000000..3e50880
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * 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);
+}