3e50880a3e6d431caf59a0a803aed64286c86d65
[physicsfs] / extras / physfs_rb / physfs / rb_physfs_file.c
1 /*
2  * PhysicsFS File abstraction - ruby interface
3  * 
4  * Author::  Ed Sinjiashvili (slimb@vlinkmail.com)
5  * License:: LGPL
6  */
7
8 #include "physfs.h"
9 #include "ruby.h"
10
11 #include "rb_physfs.h"
12 #include "rb_physfs_file.h"
13 #include "physfsrwops.h"
14
15 VALUE classPhysfsFile;
16
17 /*
18  * construct new PhysicsFS::File object
19  */
20 VALUE physfs_file_new (PHYSFS_File *file)
21 {
22     if (file == 0)
23         return Qnil;
24
25     return Data_Wrap_Struct (classPhysfsFile, 0, 0, file);
26 }
27
28 /*
29  * PhysicsFS::File#close 
30  *
31  * Close the file. It's illegal to use the object after its closure.
32  */
33 VALUE physfs_file_close (VALUE self)
34 {
35     int result;
36     PHYSFS_File *file;
37     Data_Get_Struct (self, PHYSFS_File, file);
38
39     if (file == 0)
40         return Qfalse;
41
42     result = PHYSFS_close (file);
43     DATA_PTR(self) = 0;
44
45     if (result)
46         return Qtrue;
47     return Qfalse;
48 }
49
50 /*
51  * PhysicsFS::File#read obj_size, num_objects
52  *
53  * Read *objCount* objects which are *objSize* each.
54  * return String instance containing raw data or nil if failure.
55  * #length of string will reflect real number of objects read.
56  */
57 VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount)
58 {
59     int objRead;
60     void *buffer;
61     VALUE result;
62     PHYSFS_File *file;
63
64     Data_Get_Struct (self, PHYSFS_File, file);
65     if (file == 0)
66         return Qnil; //wasted file - no read possible
67
68     buffer  = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
69     if (buffer == 0)
70         return Qnil;
71
72     objRead = PHYSFS_read (file, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
73     if (objRead == -1)
74     {
75         free (buffer);
76         return Qnil;
77     }
78
79     result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
80     free (buffer);
81     return result;
82 }
83
84 /*
85  * PhysicsFS::File#write buffer, obj_size, num_objects
86  *
87  * return nil on failure or number of objects written.
88  */
89 VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount)
90 {
91     int result;
92     PHYSFS_File *file;
93
94     Data_Get_Struct (self, PHYSFS_File, file);
95     if (file == 0)
96         return Qnil;
97
98     result = PHYSFS_write (file, STR2CSTR(buf), 
99                            FIX2UINT(objSize), FIX2UINT(objCount));
100     if (result == -1)
101         return Qnil;
102
103     return INT2FIX(result);
104 }
105
106 /*
107  * PhysicsFS::File#eof? 
108  */
109 VALUE physfs_file_eof (VALUE self)
110 {
111     int result;
112     PHYSFS_File *file;
113
114     Data_Get_Struct (self, PHYSFS_File, file);
115     if (file == 0)
116         return Qnil;
117
118     result = PHYSFS_eof (file);
119
120     if (result)
121         return Qtrue;
122
123     return Qfalse;
124 }
125
126 /*
127  * PhysicsFS::File#tell
128  *
129  * tells current position in file
130  */
131 VALUE physfs_file_tell (VALUE self)
132 {
133     int result;
134     PHYSFS_File *file;
135
136     Data_Get_Struct (self, PHYSFS_File, file);
137     if (file == 0)
138         return Qnil;
139
140     result = PHYSFS_tell (file);
141
142     if (result == -1)
143         return Qnil;
144
145     return INT2FIX(result);
146 }    
147
148 /*
149  * PhysicsFS::File#seek pos
150  *
151  * seek to pos in file
152  */
153 VALUE physfs_file_seek (VALUE self, VALUE pos)
154 {
155     int result;
156     PHYSFS_File *file;
157
158     Data_Get_Struct (self, PHYSFS_File, file);
159     if (file == 0)
160         return Qnil;
161
162     result = PHYSFS_seek (file, FIX2LONG(pos));
163
164     if (result)
165         return Qtrue;
166
167     return Qfalse;    
168 }
169
170 /*
171  * PhysicsFS::File#length 
172  */
173 VALUE physfs_file_length (VALUE self)
174 {
175     int result;
176     PHYSFS_File *file;
177
178     Data_Get_Struct (self, PHYSFS_File, file);
179     if (file == 0)
180         return Qnil;
181
182     result = PHYSFS_fileLength (file);
183
184     if (result == -1)
185         return Qnil;
186
187     return INT2FIX(result);
188 }
189
190 /*
191  * PhysicsFS::File#to_rwops
192  *
193  * File object is converted to RWops object. 
194  * File object becomes unusable after that - every operation
195  * should be done through new-born RWops object. 
196  */
197 VALUE physfs_file_to_rwops (VALUE self)
198 {
199     PHYSFS_File *file;
200     SDL_RWops   *rwops;
201
202     Data_Get_Struct (self, PHYSFS_File, file);
203     if (file == 0)
204         return Qnil;
205
206     rwops = PHYSFSRWOPS_makeRWops (file);
207     if (rwops == 0)
208         return Qnil;
209
210     DATA_PTR(self) = 0; // oh, gosh, we've sacrificed ourselves!
211     return sdl_rwops_new (rwops);
212 }
213
214 void init_physfs_file (void)
215 {
216     classPhysfsFile = rb_define_class_under (modulePhysfs, "File", rb_cObject);
217
218     rb_define_method (classPhysfsFile, "close",    physfs_file_close,    0);
219     rb_define_method (classPhysfsFile, "eof?",     physfs_file_eof,      0);
220     rb_define_method (classPhysfsFile, "tell",     physfs_file_tell,     0);
221     rb_define_method (classPhysfsFile, "seek",     physfs_file_seek,     1);
222     rb_define_method (classPhysfsFile, "length",   physfs_file_length,   0);
223     rb_define_method (classPhysfsFile, "read",     physfs_file_read,     2);
224     rb_define_method (classPhysfsFile, "write",    physfs_file_write,    3);
225     rb_define_method (classPhysfsFile, "to_rwops", physfs_file_to_rwops, 0);
226 }