use the VERSION instead of master in the revno.h generated from a src tarball
[gnash.git] / extensions / fileio / fileio.cpp
blob524bedb719095d69145e295ce66e61e2247b58f3
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifdef HAVE_CONFIG_H
20 #include "gnashconfig.h"
21 #endif
23 #include <map>
24 #include <iostream>
25 #include <string>
26 #include <cstdio>
27 #include <boost/algorithm/string/case_conv.hpp>
29 #include <dirent.h> // used by scandir()
30 #include "GnashSystemIOHeaders.h" // used by unlink()
31 #include <fcntl.h> // used by asyncmode()
33 //#include "VM.h"
34 #include "log.h"
35 #include "fn_call.h"
36 #include "as_object.h"
37 #include "Global_as.h"
38 #include "fileio.h"
39 #include "Array_as.h" // used by scandir()
40 #include "as_function.h"
42 using namespace std;
44 namespace gnash
47 static const int BUFSIZE = 1024;
49 as_value fileio_fopen(const fn_call& fn);
50 as_value fileio_fread(const fn_call& fn);
51 as_value fileio_fgetc(const fn_call& fn);
52 as_value fileio_fgets(const fn_call& fn);
53 as_value fileio_gets(const fn_call& fn);
54 as_value fileio_fwrite(const fn_call& fn);
55 as_value fileio_fputc(const fn_call& fn);
56 as_value fileio_fputs(const fn_call& fn);
57 as_value fileio_puts(const fn_call& fn);
58 as_value fileio_fclose(const fn_call& fn);
59 as_value fileio_getchar(const fn_call& fn);
60 as_value fileio_putchar(const fn_call& fn);
61 as_value fileio_fflush(const fn_call& fn);
62 as_value fileio_ftell(const fn_call& fn);
63 as_value fileio_feof(const fn_call& fn);
64 as_value fileio_fseek(const fn_call& fn);
65 as_value fileio_unlink(const fn_call& fn);
66 as_value fileio_asyncmode(const fn_call& fn);
68 // <Udo> I needed a scandir() function and implemented it here for simplicity.
69 // Maybe this should be moved to a dedicated extension and a different class?
70 // The scandir() syntax comes from PHP, since the C syntax is not quite
71 // applicable in ActionScript.
72 // Same applies for unlink(). Maybe a class FileOP or sim. would be
73 // appriopriate.
74 as_value fileio_scandir(const fn_call& fn);
76 LogFile& dbglogfile = LogFile::getDefaultInstance();
78 // TODO: Document this class !!
79 class FileIO : public Relay
81 public:
82 FileIO();
83 ~FileIO();
85 bool fopen(const std::string &filespec, const std::string &mode);
87 int fread(std::string &str);
88 int fgetc();
89 std::string &fgets(std::string &str);
91 int fwrite(const std::string &str);
92 bool fputc(int c);
93 bool fputs(const std::string &str);
94 int fclose();
95 int fflush();
96 void rewind();
97 int fseek(long offset);
98 int fseek(long offset, int whence);
99 long ftell();
100 bool asyncmode(bool async);
101 bool feof();
102 bool unlink(const std::string &filespec);
103 private:
104 FILE *_stream;
105 std::string _filespec;
108 static void
109 attachInterface(as_object& obj)
111 Global_as& gl = getGlobal(obj);
113 obj.init_member("fopen", gl.createFunction(fileio_fopen));
114 obj.init_member("fread", gl.createFunction(fileio_fread));
115 obj.init_member("fgetc", gl.createFunction(fileio_fgetc));
116 obj.init_member("fgets", gl.createFunction(fileio_fgets));
117 obj.init_member("gets", gl.createFunction(fileio_fgets));
118 obj.init_member("getchar", gl.createFunction(fileio_getchar));
120 obj.init_member("fwrite", gl.createFunction(fileio_fwrite));
121 obj.init_member("fputc", gl.createFunction(fileio_fputc));
122 obj.init_member("fputs", gl.createFunction(fileio_fputs));
123 obj.init_member("puts", gl.createFunction(fileio_puts));
124 obj.init_member("putchar", gl.createFunction(fileio_putchar));
126 obj.init_member("fflush", gl.createFunction(fileio_fflush));
127 obj.init_member("fseek", gl.createFunction(fileio_fseek));
128 obj.init_member("ftell", gl.createFunction(fileio_ftell));
129 obj.init_member("asyncmode", gl.createFunction(fileio_asyncmode));
130 obj.init_member("feof", gl.createFunction(fileio_feof));
131 obj.init_member("fclose", gl.createFunction(fileio_fclose));
133 obj.init_member("unlink", gl.createFunction(fileio_unlink));
135 obj.init_member("scandir", gl.createFunction(fileio_scandir));
138 static as_value
139 fileio_ctor(const fn_call& fn)
141 as_object* obj = ensure<ValidThis>(fn);
142 obj->setRelay(new FileIO());
144 if (fn.nargs > 0) {
145 IF_VERBOSE_ASCODING_ERRORS(
146 std::stringstream ss; fn.dump_args(ss);
147 log_aserror("new FileIO(%s): all arguments discarded",
148 ss.str().c_str());
152 return as_value();
156 FileIO::FileIO()
158 _stream(0)
162 FileIO::~FileIO()
164 // GNASH_REPORT_FUNCTION;
165 fclose();
169 FileIO::fflush()
171 // GNASH_REPORT_FUNCTION;
172 if (_stream) {
173 return ::fflush(_stream);
175 return -1;
178 void
179 FileIO::rewind()
181 // GNASH_REPORT_FUNCTION;
182 if (_stream) {
183 ::fseek(_stream, 0L, SEEK_SET);
188 FileIO::fseek(long offset)
190 // GNASH_REPORT_FUNCTION;
191 if (_stream) {
192 return ::fseek(_stream, offset, SEEK_SET);
194 return -1;
198 FileIO::fseek(long offset, int whence)
200 // GNASH_REPORT_FUNCTION;
201 if (_stream) {
202 return ::fseek(_stream, offset, whence);
204 return -1;
207 long
208 FileIO::ftell()
210 // GNASH_REPORT_FUNCTION;
211 if (_stream) {
212 return ::ftell(_stream);
214 return -1;
217 bool
218 FileIO::asyncmode(bool async)
220 // GNASH_REPORT_FUNCTION;
221 if (_stream) {
223 int fd = fileno(_stream);
225 long flags = fcntl(fd, F_GETFL);
227 int res;
229 if (async)
230 res = fcntl(fd, F_SETFL, flags|O_NONBLOCK);
231 else
232 res = fcntl(fd, F_SETFL, flags&(~O_NONBLOCK));
234 return res>=0;
236 return false;
239 bool
240 FileIO::feof()
242 // GNASH_REPORT_FUNCTION;
243 if (_stream) {
244 return ::feof(_stream);
246 return -1;
249 bool
250 FileIO::fopen(const string &filespec, const string &mode)
252 // GNASH_REPORT_FUNCTION;
253 _stream = ::fopen(filespec.c_str(), mode.c_str());
254 if (_stream) {
255 return true;
256 } else {
257 return false;
263 FileIO::fread(string &str)
265 // GNASH_REPORT_FUNCTION;
266 int ret = -1;
267 if (_stream) {
268 char buf[BUFSIZE];
269 memset(buf, 0, BUFSIZE);
270 ret = ::fread(buf, 1, BUFSIZE, _stream);
271 if (ret) {
272 str = buf;
275 return ret;
279 FileIO::fgetc()
281 // GNASH_REPORT_FUNCTION;
282 if (_stream) {
283 return ::fgetc(_stream);
285 return -1;
288 string &
289 FileIO::fgets(std::string &str)
291 // GNASH_REPORT_FUNCTION;
292 if (_stream) {
293 char buf[BUFSIZE];
294 memset(buf, 0, BUFSIZE);
295 char* res = ::fgets(buf, BUFSIZE, _stream);
296 if (res)
297 str = res;
298 else
299 str = ""; // we might want to return NULL to the VM ?
300 return str;
302 return str;
306 FileIO::fwrite(const string &str)
308 // GNASH_REPORT_FUNCTION;
309 return ::fwrite(str.c_str(), str.size(), 1, _stream);
313 bool
314 FileIO::fputc(int c)
316 // GNASH_REPORT_FUNCTION;
317 if (_stream) {
318 if (::fputc(c, _stream)) {
319 return true;
322 return false;
325 bool
326 FileIO::fputs(const string &str)
328 // GNASH_REPORT_FUNCTION;
329 if (_stream) {
330 if (::fputs(str.c_str(), _stream)) {
331 return true;
334 return false;
338 FileIO::fclose()
340 // GNASH_REPORT_FUNCTION;
341 if (_stream) {
342 int ret = ::fclose(_stream);
343 _stream = 0;
344 return ret;
346 return -1;
349 bool
350 FileIO::unlink(const std::string &filespec)
352 // GNASH_REPORT_FUNCTION;
353 return ::unlink(filespec.c_str()) >= 0;
357 as_value
358 fileio_fopen(const fn_call& fn)
360 // GNASH_REPORT_FUNCTION;
361 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
362 assert(ptr);
364 if (fn.nargs < 2) {
365 IF_VERBOSE_ASCODING_ERRORS(
366 std::stringstream ss; fn.dump_args(ss);
367 log_aserror("FileIO.fopen(%s): need two arguments", ss.str().c_str());
369 return as_value(false);
372 string filespec = fn.arg(0).to_string();
373 string mode = fn.arg(1).to_string();
374 return as_value(ptr->fopen(filespec, mode));
378 as_value
379 fileio_fclose(const fn_call& fn)
381 // GNASH_REPORT_FUNCTION;
382 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
383 assert(ptr);
385 return as_value(ptr->fclose());
388 as_value
389 fileio_fread(const fn_call& fn)
391 // GNASH_REPORT_FUNCTION;
392 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
393 assert(ptr);
395 string str;
396 int count = ptr->fread(str);
398 if (count<0) {
399 return as_value(false);
400 } else {
401 return as_value(str.c_str());
405 as_value
406 fileio_fgetc(const fn_call& fn)
408 // GNASH_REPORT_FUNCTION;
409 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
410 assert(ptr);
411 int i = ptr->fgetc();
413 if ((i==EOF) || (i<0)) {
414 return as_value(false); // possible in async mode
415 } else {
416 char c[2]="x"; // set to 1 char to get the zero byte!
417 c[0] = i;
418 return as_value(c);
422 as_value
423 fileio_fgets(const fn_call& fn)
425 // GNASH_REPORT_FUNCTION;
426 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
427 assert(ptr);
428 string str;
429 str = ptr->fgets(str);
430 return as_value(str.c_str());
433 as_value
434 fileio_gets(const fn_call& fn)
436 // GNASH_REPORT_FUNCTION;
437 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
438 assert(ptr);
439 char buf[BUFSIZE];
440 memset(buf, 0, BUFSIZE);
441 string str = ::gets(buf);
442 return as_value(buf);
445 // Read a single character from standard in
446 as_value
447 fileio_getchar(const fn_call& fn)
449 // GNASH_REPORT_FUNCTION;
450 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
451 assert(ptr);
452 int i = ::getchar();
453 char *c = reinterpret_cast<char *>(&i);
454 return as_value(c);
457 as_value
458 fileio_fwrite(const fn_call& fn)
460 // GNASH_REPORT_FUNCTION;
461 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
462 assert(ptr);
463 string str = fn.arg(0).to_string();
464 return as_value(ptr->fputs(str));
467 as_value
468 fileio_fputc(const fn_call& fn)
470 // GNASH_REPORT_FUNCTION;
471 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
472 assert(ptr);
473 int c = (int) toNumber(fn.arg(0), getVM(fn));
474 return as_value(ptr->fputc(c));
477 as_value
478 fileio_fputs(const fn_call& fn)
480 // GNASH_REPORT_FUNCTION;
481 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
483 string str = fn.arg(0).to_string();
484 return as_value(ptr->fputs(str));
487 // print to standard put
488 as_value
489 fileio_puts(const fn_call& fn)
491 // GNASH_REPORT_FUNCTION;
492 string str = fn.arg(0).to_string();
493 return as_value(::puts(str.c_str()));
496 as_value
497 fileio_putchar(const fn_call& fn)
499 // GNASH_REPORT_FUNCTION;
500 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
501 assert(ptr);
502 string x = fn.arg(0).to_string();
503 return as_value(::putchar(x[0]));
506 as_value
507 fileio_fflush(const fn_call& fn)
509 // GNASH_REPORT_FUNCTION;
510 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
511 assert(ptr);
512 return as_value(ptr->fflush());
515 as_value
516 fileio_fseek(const fn_call& fn)
518 // GNASH_REPORT_FUNCTION;
519 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
520 assert(ptr);
521 long c = static_cast<long>(toNumber(fn.arg(0), getVM(fn)));
522 return as_value(ptr->fseek(c));
525 as_value
526 fileio_ftell(const fn_call& fn)
528 // GNASH_REPORT_FUNCTION;
529 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
530 assert(ptr);
531 int i = ptr->ftell();
532 return as_value(i);
535 as_value
536 fileio_asyncmode(const fn_call& fn)
538 // GNASH_REPORT_FUNCTION;
539 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
540 assert(ptr);
541 bool b = toBool(fn.arg(0), getVM(fn));
542 return as_value(ptr->asyncmode(b));
545 as_value
546 fileio_feof(const fn_call& fn)
548 // GNASH_REPORT_FUNCTION;
549 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
550 assert(ptr);
551 bool b = ptr->feof();
552 return as_value(b);
555 as_value
556 fileio_unlink(const fn_call& fn)
558 // GNASH_REPORT_FUNCTION;
559 FileIO* ptr = ensure<ThisIsNative<FileIO> >(fn);
560 assert(ptr);
561 string str = fn.arg(0).to_string();
562 return as_value(ptr->unlink(str));
565 as_value
566 fileio_scandir(const fn_call& fn)
568 // GNASH_REPORT_FUNCTION;
570 // TODO: Check optional second parameter and sort array if it's true
571 // or missing.
573 if (!fn.nargs) return as_value(false);
575 const std::string& dir = fn.arg(0).to_string();
577 struct dirent **namelist;
579 const int n = ::scandir(dir.c_str(), &namelist, 0, alphasort);
581 if (n < 0) {
582 return as_value(false);
585 Global_as& gl = getGlobal(fn);
586 VM& vm = getVM(fn);
587 as_object* array = gl.createArray();
589 for (int idx = 0; idx < n; ++idx) {
590 array->set_member(arrayKey(vm, idx), namelist[idx]->d_name);
591 free(namelist[idx]);
593 free(namelist);
595 return as_value(array);
598 extern "C" {
600 void
601 fileio_class_init(as_object& where, const ObjectURI& /* uri */)
603 // GNASH_REPORT_FUNCTION;
604 Global_as& gl = getGlobal(where);
606 as_object* proto = createObject(gl);
607 attachInterface(*proto);
608 as_object* cl = gl.createClass(&fileio_ctor, proto);
610 where.init_member("FileIO", cl);
612 } // end of extern C
615 } // end of gnash namespace
617 // Local Variables:
618 // mode: C++
619 // indent-tabs-mode: nil
620 // End: