Add missing files
This commit is contained in:
		
							parent
							
								
									ff25887f41
								
							
						
					
					
						commit
						ec90458925
					
				
					 8 changed files with 2360 additions and 0 deletions
				
			
		
							
								
								
									
										622
									
								
								binding-mruby/mrb-ext/file.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										622
									
								
								binding-mruby/mrb-ext/file.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,622 @@
 | 
			
		|||
/*
 | 
			
		||||
** file.cpp
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "file.h"
 | 
			
		||||
 | 
			
		||||
#include "../binding-util.h"
 | 
			
		||||
#include "mruby/string.h"
 | 
			
		||||
#include "mruby/array.h"
 | 
			
		||||
#include "mruby/class.h"
 | 
			
		||||
 | 
			
		||||
#include "SDL2/SDL_rwops.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
#include <QVector>
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
extern mrb_value timeFromSecondsInt(mrb_state *mrb, time_t seconds);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
checkValid(mrb_state *mrb, FileImpl *p, int rwMode = FileImpl::ReadWrite)
 | 
			
		||||
{
 | 
			
		||||
	MrbData *data = getMrbData(mrb);
 | 
			
		||||
 | 
			
		||||
	if (p->closed)
 | 
			
		||||
		mrb_raise(mrb, data->exc[IO], "closed stream");
 | 
			
		||||
 | 
			
		||||
	if (!(p->mode & rwMode))
 | 
			
		||||
	{
 | 
			
		||||
		const char *errorMsg = 0;
 | 
			
		||||
 | 
			
		||||
		switch (rwMode)
 | 
			
		||||
		{
 | 
			
		||||
		case FileImpl::Read :
 | 
			
		||||
			errorMsg = "not openend for reading"; break;
 | 
			
		||||
		case FileImpl::Write :
 | 
			
		||||
			errorMsg = "not openend for writing"; break;
 | 
			
		||||
		default: break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mrb_raise(mrb, data->exc[IO], errorMsg);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern const mrb_data_type FileType =
 | 
			
		||||
{
 | 
			
		||||
    "File",
 | 
			
		||||
    freeInstance<FileImpl>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
getOpenMode(const char *mode)
 | 
			
		||||
{
 | 
			
		||||
#define STR_CASE(cs, ret) else if (!strcmp(mode, cs)) { return FileImpl:: ret; }
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(mode, "r"))
 | 
			
		||||
		return FileImpl::Read;
 | 
			
		||||
	STR_CASE("rb", Read)
 | 
			
		||||
	STR_CASE("r+", ReadWrite)
 | 
			
		||||
	STR_CASE("w", Write)
 | 
			
		||||
	STR_CASE("wb", Write)
 | 
			
		||||
	STR_CASE("w+", ReadWrite)
 | 
			
		||||
	STR_CASE("rw", ReadWrite)
 | 
			
		||||
	STR_CASE("a", Write)
 | 
			
		||||
	STR_CASE("a+", ReadWrite)
 | 
			
		||||
 | 
			
		||||
	qDebug() << "getOpenMode failed for:" << mode;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handleErrno(mrb_state *mrb)
 | 
			
		||||
{
 | 
			
		||||
	MrbException exc;
 | 
			
		||||
	const char *msg;
 | 
			
		||||
	mrb_value arg1;
 | 
			
		||||
 | 
			
		||||
#define ENO(_eno, _msg) \
 | 
			
		||||
	case _eno: { exc = Errno##_eno; msg = _msg; break; }
 | 
			
		||||
 | 
			
		||||
	switch (errno)
 | 
			
		||||
	{
 | 
			
		||||
	ENO(EACCES, "");
 | 
			
		||||
	ENO(EBADF, "");
 | 
			
		||||
	ENO(EEXIST, "");
 | 
			
		||||
	ENO(EINVAL, "");
 | 
			
		||||
	ENO(EMFILE, "");
 | 
			
		||||
	ENO(ENOMEM, "");
 | 
			
		||||
	ENO(ERANGE, "");
 | 
			
		||||
	default:
 | 
			
		||||
		exc = IO; msg = "Unknown Errno: %S";
 | 
			
		||||
		arg1 = mrb_any_to_s(mrb, mrb_fixnum_value(errno));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#undef ENO
 | 
			
		||||
 | 
			
		||||
	mrb_raisef(mrb, getMrbData(mrb)->exc[exc], msg, arg1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define GUARD_ERRNO(stmnt) \
 | 
			
		||||
{ \
 | 
			
		||||
	errno = 0; \
 | 
			
		||||
	{ stmnt } \
 | 
			
		||||
	if (errno != 0) \
 | 
			
		||||
		handleErrno(mrb); \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
findLastDot(char *str)
 | 
			
		||||
{
 | 
			
		||||
	char *find = 0;
 | 
			
		||||
	char *ptr = str;
 | 
			
		||||
 | 
			
		||||
	/* Dot in front is not considered */
 | 
			
		||||
	if (*ptr == '.')
 | 
			
		||||
		ptr++;
 | 
			
		||||
 | 
			
		||||
	for (; *ptr; ++ptr)
 | 
			
		||||
	{
 | 
			
		||||
		/* Dot in dirpath is not considered */
 | 
			
		||||
		if (*ptr == '/')
 | 
			
		||||
		{
 | 
			
		||||
			ptr++;
 | 
			
		||||
			if (*ptr == '.')
 | 
			
		||||
				ptr++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (*ptr == '.')
 | 
			
		||||
			find = ptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return find;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* File class methods */
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileBasename(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value filename;
 | 
			
		||||
	const char *suffix = 0;
 | 
			
		||||
 | 
			
		||||
	mrb_get_args(mrb, "S|z", &filename, &suffix);
 | 
			
		||||
 | 
			
		||||
	char *_filename = RSTRING_PTR(filename);
 | 
			
		||||
	char *base = basename(_filename);
 | 
			
		||||
 | 
			
		||||
	char *ext = 0;
 | 
			
		||||
 | 
			
		||||
	if (suffix)
 | 
			
		||||
	{
 | 
			
		||||
		ext = findLastDot(base);
 | 
			
		||||
		if (ext && !strcmp(ext, suffix))
 | 
			
		||||
			*ext = '\0';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mrb_value str = mrb_str_new_cstr(mrb, base);
 | 
			
		||||
 | 
			
		||||
	/* Restore param string */
 | 
			
		||||
	if (ext)
 | 
			
		||||
		*ext = '.';
 | 
			
		||||
 | 
			
		||||
	return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileDelete(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_int argc;
 | 
			
		||||
	mrb_value *argv;
 | 
			
		||||
 | 
			
		||||
	mrb_get_args(mrb, "*", &argv, &argc);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < argc; ++i)
 | 
			
		||||
	{
 | 
			
		||||
		mrb_value &v = argv[i];
 | 
			
		||||
 | 
			
		||||
		if (!mrb_string_p(v))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		const char *filename = RSTRING_PTR(v);
 | 
			
		||||
		GUARD_ERRNO( unlink(filename); )
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return mrb_nil_value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileDirname(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value filename;
 | 
			
		||||
	mrb_get_args(mrb, "S", &filename);
 | 
			
		||||
 | 
			
		||||
	char *_filename = RSTRING_PTR(filename);
 | 
			
		||||
	char *dir = dirname(_filename);
 | 
			
		||||
 | 
			
		||||
	return mrb_str_new_cstr(mrb, dir);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileExpandPath(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	const char *path;
 | 
			
		||||
	const char *defDir = 0;
 | 
			
		||||
 | 
			
		||||
	mrb_get_args(mrb, "z|z", &path, &defDir);
 | 
			
		||||
 | 
			
		||||
	// FIXME No idea how to integrate 'default_dir' right now
 | 
			
		||||
	if (defDir)
 | 
			
		||||
		qDebug() << "FIXME: File.expand_path: default_dir not implemented";
 | 
			
		||||
 | 
			
		||||
	char buffer[512];
 | 
			
		||||
	char *unused = realpath(path, buffer);
 | 
			
		||||
	(void) unused;
 | 
			
		||||
 | 
			
		||||
	return mrb_str_new_cstr(mrb, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileExtname(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value filename;
 | 
			
		||||
	mrb_get_args(mrb, "S", &filename);
 | 
			
		||||
 | 
			
		||||
	char *ext = findLastDot(RSTRING_PTR(filename));
 | 
			
		||||
 | 
			
		||||
	return mrb_str_new_cstr(mrb, ext);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileOpen(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value path;
 | 
			
		||||
	const char *mode = "r";
 | 
			
		||||
	mrb_value block = mrb_nil_value();
 | 
			
		||||
 | 
			
		||||
	mrb_get_args(mrb, "S|z&", &path, &mode, &block);
 | 
			
		||||
 | 
			
		||||
	/* We manually check errno because we're supplying the
 | 
			
		||||
	 * filename on ENOENT */
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	FILE *f = fopen(RSTRING_PTR(path), mode);
 | 
			
		||||
	if (!f)
 | 
			
		||||
	{
 | 
			
		||||
		if (errno == ENOENT)
 | 
			
		||||
			mrb_raisef(mrb, getMrbData(mrb)->exc[ErrnoENOENT],
 | 
			
		||||
					   "No such file or directory - %S", path);
 | 
			
		||||
		else
 | 
			
		||||
			handleErrno(mrb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_RWops *ops = SDL_RWFromFP(f, SDL_TRUE);
 | 
			
		||||
	FileImpl *p = new FileImpl(ops, getOpenMode(mode));
 | 
			
		||||
 | 
			
		||||
	mrb_value obj = wrapObject(mrb, p, FileType);
 | 
			
		||||
	setProperty(mrb, obj, CSpath, path);
 | 
			
		||||
 | 
			
		||||
	if (mrb_type(block) == MRB_TT_PROC)
 | 
			
		||||
	{
 | 
			
		||||
		// FIXME inquire how GC behaviour works here for obj
 | 
			
		||||
		mrb_value ret = mrb_yield(mrb, block, obj);
 | 
			
		||||
		p->close();
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileRename(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	const char *from, *to;
 | 
			
		||||
	mrb_get_args(mrb, "zz", &from, &to);
 | 
			
		||||
 | 
			
		||||
	GUARD_ERRNO( rename(from, to); )
 | 
			
		||||
 | 
			
		||||
	return mrb_fixnum_value(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
mrbNoop(mrb_state *, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* File instance methods */
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileClose(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p);
 | 
			
		||||
 | 
			
		||||
	GUARD_ERRNO( p->close(); )
 | 
			
		||||
 | 
			
		||||
	return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
readLine(FILE *f, QVector<char> &buffer)
 | 
			
		||||
{
 | 
			
		||||
	buffer.clear();
 | 
			
		||||
 | 
			
		||||
	while (true)
 | 
			
		||||
	{
 | 
			
		||||
		if (feof(f))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		char c = fgetc(f);
 | 
			
		||||
 | 
			
		||||
		if (c == '\n' || c == EOF)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		buffer.append(c);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileEachLine(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p, FileImpl::Read);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	mrb_value block;
 | 
			
		||||
	mrb_get_args(mrb, "&", &block);
 | 
			
		||||
 | 
			
		||||
	(void) f;
 | 
			
		||||
	QVector<char> buffer;
 | 
			
		||||
 | 
			
		||||
	mrb_value str = mrb_str_buf_new(mrb, 0);
 | 
			
		||||
 | 
			
		||||
	while (feof(f) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		GUARD_ERRNO( readLine(f, buffer); )
 | 
			
		||||
		if (buffer.isEmpty() && feof(f) != 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		size_t lineLen = buffer.count();
 | 
			
		||||
		mrb_str_resize(mrb, str, lineLen);
 | 
			
		||||
		memcpy(RSTRING_PTR(str), buffer.constData(), lineLen);
 | 
			
		||||
 | 
			
		||||
		mrb_yield(mrb, block, str);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileEachByte(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p, FileImpl::Read);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	mrb_value block;
 | 
			
		||||
	mrb_get_args(mrb, "&", &block);
 | 
			
		||||
 | 
			
		||||
	GUARD_ERRNO(
 | 
			
		||||
	while (feof(f) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		mrb_int byte = fgetc(f);
 | 
			
		||||
		if (byte == -1)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		mrb_yield(mrb, block, mrb_fixnum_value(byte));
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileIsEof(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	bool isEof;
 | 
			
		||||
	GUARD_ERRNO( isEof = feof(f) != 0; )
 | 
			
		||||
 | 
			
		||||
	return mrb_bool_value(isEof);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileSetPos(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	mrb_int pos;
 | 
			
		||||
	mrb_get_args(mrb, "i", &pos);
 | 
			
		||||
 | 
			
		||||
	GUARD_ERRNO( fseek(f, pos, SEEK_SET); )
 | 
			
		||||
 | 
			
		||||
	return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileGetPos(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	long pos;
 | 
			
		||||
	GUARD_ERRNO( pos = ftell(f); )
 | 
			
		||||
 | 
			
		||||
	return mrb_fixnum_value(pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileRead(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p, FileImpl::Read);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	long cur, size;
 | 
			
		||||
	GUARD_ERRNO( cur = ftell(f); )
 | 
			
		||||
	GUARD_ERRNO( fseek(f, 0, SEEK_END); )
 | 
			
		||||
	GUARD_ERRNO( size = ftell(f); )
 | 
			
		||||
	GUARD_ERRNO( fseek(f, cur, SEEK_SET); )
 | 
			
		||||
 | 
			
		||||
	mrb_int length = size - cur;
 | 
			
		||||
	mrb_get_args(mrb, "|i", &length);
 | 
			
		||||
 | 
			
		||||
	mrb_value str = mrb_str_new(mrb, 0, 0);
 | 
			
		||||
	mrb_str_resize(mrb, str, length);
 | 
			
		||||
 | 
			
		||||
	GUARD_ERRNO( int unused = fread(RSTRING_PTR(str), 1, length, f); (void) unused; )
 | 
			
		||||
 | 
			
		||||
	return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME this function always splits on newline right now,
 | 
			
		||||
// to make rs fully work, I'll have to use some strrstr magic I guess
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileReadLines(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p, FileImpl::Read);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	mrb_value arg;
 | 
			
		||||
	mrb_get_args(mrb, "|o", &arg);
 | 
			
		||||
 | 
			
		||||
	const char *rs = "\n"; (void) rs;
 | 
			
		||||
	if (mrb->c->ci->argc > 0)
 | 
			
		||||
	{
 | 
			
		||||
		qDebug() << "FIXME: File.readlines: rs not implemented";
 | 
			
		||||
 | 
			
		||||
		if (mrb_string_p(arg))
 | 
			
		||||
			rs = RSTRING_PTR(arg);
 | 
			
		||||
		else if (mrb_nil_p(arg))
 | 
			
		||||
			rs = "\n";
 | 
			
		||||
		else
 | 
			
		||||
			mrb_raise(mrb, getMrbData(mrb)->exc[TypeError], "Expected string or nil"); // FIXME add "got <> instead" remark
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mrb_value ary = mrb_ary_new(mrb);
 | 
			
		||||
	QVector<char> buffer;
 | 
			
		||||
 | 
			
		||||
	while (feof(f) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		GUARD_ERRNO( readLine(f, buffer); )
 | 
			
		||||
		if (buffer.isEmpty() && feof(f) != 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		mrb_value str = mrb_str_new(mrb, buffer.constData(), buffer.size());
 | 
			
		||||
		mrb_ary_push(mrb, ary, str);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileWrite(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p, FileImpl::Write);
 | 
			
		||||
	FILE *f = p->fp();
 | 
			
		||||
 | 
			
		||||
	mrb_value str;
 | 
			
		||||
	mrb_get_args(mrb, "S", &str);
 | 
			
		||||
 | 
			
		||||
	size_t count;
 | 
			
		||||
	GUARD_ERRNO( count = fwrite(RSTRING_PTR(str), 1, RSTRING_LEN(str), f); )
 | 
			
		||||
 | 
			
		||||
	return mrb_fixnum_value(count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileGetPath(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	FileImpl *p = getPrivateData<FileImpl>(mrb, self);
 | 
			
		||||
	checkValid(mrb, p);
 | 
			
		||||
 | 
			
		||||
	return getProperty(mrb, self, CSpath);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
getFileStat(mrb_state *mrb, struct stat &fileStat)
 | 
			
		||||
{
 | 
			
		||||
	const char *filename;
 | 
			
		||||
	mrb_get_args(mrb, "z", &filename);
 | 
			
		||||
 | 
			
		||||
	stat(filename, &fileStat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileGetMtime(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value path = getProperty(mrb, self, CSpath);
 | 
			
		||||
 | 
			
		||||
	struct stat fileStat;
 | 
			
		||||
	stat(RSTRING_PTR(path), &fileStat);
 | 
			
		||||
 | 
			
		||||
	return timeFromSecondsInt(mrb, fileStat.st_mtim.tv_sec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FileTest module functions */
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileTestDoesExist(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	const char *filename;
 | 
			
		||||
	mrb_get_args(mrb, "z", &filename);
 | 
			
		||||
 | 
			
		||||
	int result = access(filename, F_OK);
 | 
			
		||||
 | 
			
		||||
	return mrb_bool_value(result == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileTestIsFile(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	struct stat fileStat;
 | 
			
		||||
	getFileStat(mrb, fileStat);
 | 
			
		||||
 | 
			
		||||
	return mrb_bool_value(S_ISREG(fileStat.st_mode));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileTestIsDirectory(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	struct stat fileStat;
 | 
			
		||||
	getFileStat(mrb, fileStat);
 | 
			
		||||
 | 
			
		||||
	return mrb_bool_value(S_ISDIR(fileStat.st_mode));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
fileTestSize(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	struct stat fileStat;
 | 
			
		||||
	getFileStat(mrb, fileStat);
 | 
			
		||||
 | 
			
		||||
	return mrb_fixnum_value(fileStat.st_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
fileBindingInit(mrb_state *mrb)
 | 
			
		||||
{
 | 
			
		||||
	mrb_define_method(mrb, mrb->kernel_module, "open", fileOpen, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
 | 
			
		||||
 | 
			
		||||
	RClass *klass = mrb_define_class(mrb, "IO", 0);
 | 
			
		||||
	klass = mrb_define_class(mrb, "File", klass);
 | 
			
		||||
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "basename", fileBasename, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "delete", fileDelete, MRB_ARGS_REQ(1) | MRB_ARGS_ANY());
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "dirname", fileDirname, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "expand_path", fileExpandPath, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "extname", fileExtname, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "open", fileOpen, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "rename", fileRename, MRB_ARGS_REQ(2));
 | 
			
		||||
 | 
			
		||||
	/* IO */
 | 
			
		||||
	mrb_define_method(mrb, klass, "binmode", mrbNoop, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_method(mrb, klass, "close", fileClose, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_method(mrb, klass, "each_line", fileEachLine, MRB_ARGS_BLOCK());
 | 
			
		||||
	mrb_define_method(mrb, klass, "each_byte", fileEachByte, MRB_ARGS_BLOCK());
 | 
			
		||||
	mrb_define_method(mrb, klass, "eof?", fileIsEof, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_method(mrb, klass, "pos", fileGetPos, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_method(mrb, klass, "pos=", fileSetPos, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_method(mrb, klass, "read", fileRead, MRB_ARGS_OPT(1));
 | 
			
		||||
	mrb_define_method(mrb, klass, "readlines", fileReadLines, MRB_ARGS_OPT(1));
 | 
			
		||||
	mrb_define_method(mrb, klass, "write", fileWrite, MRB_ARGS_REQ(1));
 | 
			
		||||
 | 
			
		||||
	/* File */
 | 
			
		||||
	mrb_define_method(mrb, klass, "mtime", fileGetMtime, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_method(mrb, klass, "path", fileGetPath, MRB_ARGS_NONE());
 | 
			
		||||
 | 
			
		||||
	/* FileTest */
 | 
			
		||||
	RClass *module = mrb_define_module(mrb, "FileTest");
 | 
			
		||||
	mrb_define_module_function(mrb, module, "exist?", fileTestDoesExist, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "directory?", fileTestIsDirectory, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "file?", fileTestIsFile, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "size", fileTestSize, MRB_ARGS_REQ(1));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								binding-mruby/mrb-ext/file.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								binding-mruby/mrb-ext/file.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
/*
 | 
			
		||||
** file.h
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef BINDING_FILE_H
 | 
			
		||||
#define BINDING_FILE_H
 | 
			
		||||
 | 
			
		||||
#include "../binding-util.h"
 | 
			
		||||
 | 
			
		||||
#include "SDL2/SDL_rwops.h"
 | 
			
		||||
 | 
			
		||||
struct FileImpl
 | 
			
		||||
{
 | 
			
		||||
	SDL_RWops *ops;
 | 
			
		||||
	bool closed;
 | 
			
		||||
 | 
			
		||||
	enum OpenMode
 | 
			
		||||
	{
 | 
			
		||||
		Read =  1 << 0,
 | 
			
		||||
		Write = 1 << 1,
 | 
			
		||||
		ReadWrite = Read | Write
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	int mode;
 | 
			
		||||
 | 
			
		||||
	FileImpl(SDL_RWops *ops, int mode)
 | 
			
		||||
	    : ops(ops),
 | 
			
		||||
	      closed(false),
 | 
			
		||||
	      mode(mode)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	void close()
 | 
			
		||||
	{
 | 
			
		||||
		if (closed)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		SDL_RWclose(ops);
 | 
			
		||||
		closed = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	FILE *fp()
 | 
			
		||||
	{
 | 
			
		||||
		return ops->hidden.stdio.fp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~FileImpl()
 | 
			
		||||
	{
 | 
			
		||||
		close();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DECL_TYPE(File);
 | 
			
		||||
 | 
			
		||||
#endif // BINDING_FILE_H
 | 
			
		||||
							
								
								
									
										243
									
								
								binding-mruby/mrb-ext/kernel.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								binding-mruby/mrb-ext/kernel.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,243 @@
 | 
			
		|||
/*
 | 
			
		||||
** kernel.cpp
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "mruby.h"
 | 
			
		||||
#include "mruby/string.h"
 | 
			
		||||
#include "mruby/compile.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
 | 
			
		||||
#include "SDL2/SDL_messagebox.h"
 | 
			
		||||
 | 
			
		||||
#include "../binding-util.h"
 | 
			
		||||
#include "marshal.h"
 | 
			
		||||
#include "globalstate.h"
 | 
			
		||||
#include "eventthread.h"
 | 
			
		||||
#include "exception.h"
 | 
			
		||||
#include "filesystem.h"
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
void mrbBindingTerminate();
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelEval(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	const char *exp;
 | 
			
		||||
	mrb_int expLen;
 | 
			
		||||
	mrb_get_args(mrb, "s", &exp, &expLen);
 | 
			
		||||
 | 
			
		||||
	return mrb_load_nstring(mrb, exp, expLen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void printP(mrb_state *mrb,
 | 
			
		||||
                   const char *conv, const char *sep)
 | 
			
		||||
{
 | 
			
		||||
	mrb_int argc;
 | 
			
		||||
	mrb_value *argv;
 | 
			
		||||
	mrb_get_args(mrb, "*", &argv, &argc);
 | 
			
		||||
 | 
			
		||||
	mrb_value buffer = mrb_str_buf_new(mrb, 128);
 | 
			
		||||
	mrb_value arg;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < argc; ++i)
 | 
			
		||||
	{
 | 
			
		||||
		arg = argv[i];
 | 
			
		||||
		arg = mrb_funcall(mrb, arg, conv, 0);
 | 
			
		||||
 | 
			
		||||
		mrb_str_buf_append(mrb, buffer, arg);
 | 
			
		||||
 | 
			
		||||
		if (i < argc)
 | 
			
		||||
			mrb_str_buf_cat(mrb, buffer, sep, strlen(sep));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gState->eThread().showMessageBox(RSTRING_PTR(buffer), SDL_MESSAGEBOX_INFORMATION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelP(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	printP(mrb, "inspect", "\n");
 | 
			
		||||
 | 
			
		||||
	return mrb_nil_value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelPrint(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	printP(mrb, "to_s", "");
 | 
			
		||||
 | 
			
		||||
	return mrb_nil_value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME store this in kernel module
 | 
			
		||||
static int currentSeed = 1;
 | 
			
		||||
bool srandCalled = false;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
srandCurrentTime(int *currentSeed)
 | 
			
		||||
{
 | 
			
		||||
	timeval tv;
 | 
			
		||||
	gettimeofday(&tv, 0);
 | 
			
		||||
 | 
			
		||||
	// FIXME could check how MRI does this
 | 
			
		||||
	*currentSeed = tv.tv_sec * tv.tv_usec;
 | 
			
		||||
 | 
			
		||||
	srand(*currentSeed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelRand(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	if (!srandCalled)
 | 
			
		||||
	{
 | 
			
		||||
		srandCurrentTime(¤tSeed);
 | 
			
		||||
		srandCalled = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mrb_value arg;
 | 
			
		||||
 | 
			
		||||
	mrb_get_args(mrb, "o", &arg);
 | 
			
		||||
 | 
			
		||||
	if (mrb_fixnum_p(arg) && mrb_fixnum(arg) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		return mrb_fixnum_value(rand() % mrb_fixnum(arg));
 | 
			
		||||
	}
 | 
			
		||||
	else if ((mrb_fixnum_p(arg) && mrb_fixnum(arg) == 0) || mrb_nil_p(arg))
 | 
			
		||||
	{
 | 
			
		||||
		return mrb_float_value(mrb, (float) rand() / RAND_MAX);
 | 
			
		||||
	}
 | 
			
		||||
	else if (mrb_float_p(arg))
 | 
			
		||||
	{
 | 
			
		||||
		return mrb_float_value(mrb, (float) rand() / RAND_MAX);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		mrb_raisef(mrb, E_TYPE_ERROR, "Expected Fixnum or Float, got %S",
 | 
			
		||||
		           mrb_str_new_cstr(mrb, mrb_class_name(mrb, mrb_class(mrb, arg))));
 | 
			
		||||
		return mrb_nil_value();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelSrand(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	srandCalled = true;
 | 
			
		||||
 | 
			
		||||
	if (mrb->c->ci->argc == 1)
 | 
			
		||||
	{
 | 
			
		||||
		mrb_int seed;
 | 
			
		||||
		mrb_get_args(mrb, "i", &seed);
 | 
			
		||||
		srand(seed);
 | 
			
		||||
 | 
			
		||||
		int oldSeed = currentSeed;
 | 
			
		||||
		currentSeed = seed;
 | 
			
		||||
 | 
			
		||||
		return mrb_fixnum_value(oldSeed);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		int oldSeed = currentSeed;
 | 
			
		||||
		srandCurrentTime(¤tSeed);
 | 
			
		||||
 | 
			
		||||
		return mrb_fixnum_value(oldSeed);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelExit(mrb_state *, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrbBindingTerminate();
 | 
			
		||||
 | 
			
		||||
	return mrb_nil_value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelLoadData(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	const char *filename;
 | 
			
		||||
	mrb_get_args(mrb, "z", &filename);
 | 
			
		||||
 | 
			
		||||
	SDL_RWops ops;
 | 
			
		||||
	GUARD_EXC( gState->fileSystem().openRead(ops, filename); )
 | 
			
		||||
 | 
			
		||||
	mrb_value obj;
 | 
			
		||||
	try { obj = marshalLoadInt(mrb, &ops); }
 | 
			
		||||
	catch (const Exception &e)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_RWclose(&ops);
 | 
			
		||||
		raiseMrbExc(mrb, e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_RWclose(&ops);
 | 
			
		||||
 | 
			
		||||
	return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelSaveData(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value obj;
 | 
			
		||||
	const char *filename;
 | 
			
		||||
 | 
			
		||||
	mrb_get_args(mrb, "oz", &obj, &filename);
 | 
			
		||||
 | 
			
		||||
	SDL_RWops *ops = SDL_RWFromFile(filename, "w");
 | 
			
		||||
	if (!ops)
 | 
			
		||||
		mrb_raise(mrb, getMrbData(mrb)->exc[SDL], SDL_GetError());
 | 
			
		||||
 | 
			
		||||
	try { marshalDumpInt(mrb, ops, obj); }
 | 
			
		||||
	catch (const Exception &e)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_RWclose(ops);
 | 
			
		||||
		raiseMrbExc(mrb, e);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_RWclose(ops);
 | 
			
		||||
 | 
			
		||||
	return mrb_nil_value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
kernelInteger(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value obj;
 | 
			
		||||
	mrb_get_args(mrb, "o", &obj);
 | 
			
		||||
 | 
			
		||||
	return mrb_to_int(mrb, obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kernelBindingInit(mrb_state *mrb)
 | 
			
		||||
{
 | 
			
		||||
	RClass *module = mrb->kernel_module;
 | 
			
		||||
 | 
			
		||||
	mrb_define_module_function(mrb, module, "eval", kernelEval, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "p", kernelP, MRB_ARGS_REQ(1) | MRB_ARGS_REST());
 | 
			
		||||
	mrb_define_module_function(mrb, module, "print", kernelPrint, MRB_ARGS_REQ(1) | MRB_ARGS_REST());
 | 
			
		||||
	mrb_define_module_function(mrb, module, "rand", kernelRand, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "srand", kernelSrand, MRB_ARGS_OPT(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "exit", kernelExit, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_module_function(mrb, module, "load_data", kernelLoadData, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "save_data", kernelSaveData, MRB_ARGS_REQ(2));
 | 
			
		||||
	mrb_define_module_function(mrb, module, "exit", kernelExit, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_module_function(mrb, module, "Integer", kernelInteger, MRB_ARGS_REQ(1));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1032
									
								
								binding-mruby/mrb-ext/marshal.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1032
									
								
								binding-mruby/mrb-ext/marshal.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										31
									
								
								binding-mruby/mrb-ext/marshal.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								binding-mruby/mrb-ext/marshal.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
/*
 | 
			
		||||
** marshal.h
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef MARSHAL_H
 | 
			
		||||
#define MARSHAL_H
 | 
			
		||||
 | 
			
		||||
#include "mruby.h"
 | 
			
		||||
#include "SDL2/SDL_rwops.h"
 | 
			
		||||
 | 
			
		||||
void marshalDumpInt(mrb_state *, SDL_RWops *, mrb_value);
 | 
			
		||||
mrb_value marshalLoadInt(mrb_state *, SDL_RWops *);
 | 
			
		||||
 | 
			
		||||
#endif // MARSHAL_H
 | 
			
		||||
							
								
								
									
										106
									
								
								binding-mruby/mrb-ext/rwmem.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								binding-mruby/mrb-ext/rwmem.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,106 @@
 | 
			
		|||
/*
 | 
			
		||||
** rwmem.cpp
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "rwmem.h"
 | 
			
		||||
 | 
			
		||||
#include "SDL2/SDL_rwops.h"
 | 
			
		||||
#include <QVector>
 | 
			
		||||
 | 
			
		||||
typedef QVector<char> ByteVec;
 | 
			
		||||
 | 
			
		||||
static inline ByteVec *
 | 
			
		||||
getRWPrivate(SDL_RWops *ops)
 | 
			
		||||
{
 | 
			
		||||
	return static_cast<ByteVec*>(ops->hidden.unknown.data1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Sint64 SDL_RWopsSize(SDL_RWops *ops)
 | 
			
		||||
{
 | 
			
		||||
	ByteVec *v = getRWPrivate(ops);
 | 
			
		||||
 | 
			
		||||
	return v->size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Sint64 SDL_RWopsSeek(SDL_RWops *, Sint64, int)
 | 
			
		||||
{
 | 
			
		||||
	/* No need for implementation */
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t SDL_RWopsRead(SDL_RWops *, void *, size_t, size_t)
 | 
			
		||||
{
 | 
			
		||||
	/* No need for implementation */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t SDL_RWopsWrite(SDL_RWops *ops, const void *buffer, size_t size, size_t num)
 | 
			
		||||
{
 | 
			
		||||
	ByteVec *v = getRWPrivate(ops);
 | 
			
		||||
 | 
			
		||||
	size_t writeBytes = size * num;
 | 
			
		||||
 | 
			
		||||
	if (writeBytes == 1)
 | 
			
		||||
	{
 | 
			
		||||
		char byte = *static_cast<const char*>(buffer);
 | 
			
		||||
		v->append(byte);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t writeInd = v->size();
 | 
			
		||||
	v->resize(writeInd + writeBytes);
 | 
			
		||||
 | 
			
		||||
	memcpy(&(*v)[writeInd], buffer, writeBytes);
 | 
			
		||||
 | 
			
		||||
	return num;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int SDL_RWopsClose(SDL_RWops *ops)
 | 
			
		||||
{
 | 
			
		||||
	ByteVec *v = getRWPrivate(ops);
 | 
			
		||||
 | 
			
		||||
	delete v;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RWMemOpen(SDL_RWops *ops)
 | 
			
		||||
{
 | 
			
		||||
	ByteVec *v = new ByteVec;
 | 
			
		||||
	ops->hidden.unknown.data1 = v;
 | 
			
		||||
 | 
			
		||||
	ops->size  = SDL_RWopsSize;
 | 
			
		||||
	ops->seek  = SDL_RWopsSeek;
 | 
			
		||||
	ops->read  = SDL_RWopsRead;
 | 
			
		||||
	ops->write = SDL_RWopsWrite;
 | 
			
		||||
	ops->close = SDL_RWopsClose;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RWMemGetData(SDL_RWops *ops, void *buffer)
 | 
			
		||||
{
 | 
			
		||||
	ByteVec *v = getRWPrivate(ops);
 | 
			
		||||
 | 
			
		||||
	if (buffer)
 | 
			
		||||
		memcpy(buffer, v->constData(), v->size());
 | 
			
		||||
 | 
			
		||||
	return v->size();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								binding-mruby/mrb-ext/rwmem.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								binding-mruby/mrb-ext/rwmem.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
/*
 | 
			
		||||
** rwmem.h
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RWMEM_H
 | 
			
		||||
#define RWMEM_H
 | 
			
		||||
 | 
			
		||||
struct SDL_RWops;
 | 
			
		||||
 | 
			
		||||
void RWMemOpen(SDL_RWops *ops);
 | 
			
		||||
 | 
			
		||||
int RWMemGetData(SDL_RWops *ops, void *buffer);
 | 
			
		||||
 | 
			
		||||
#endif // RWMEM_H
 | 
			
		||||
							
								
								
									
										224
									
								
								binding-mruby/mrb-ext/time.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								binding-mruby/mrb-ext/time.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,224 @@
 | 
			
		|||
/*
 | 
			
		||||
** time.cpp
 | 
			
		||||
**
 | 
			
		||||
** This file is part of mkxp.
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
 | 
			
		||||
**
 | 
			
		||||
** mkxp is free software: you can redistribute it and/or modify
 | 
			
		||||
** it under the terms of the GNU General Public License as published by
 | 
			
		||||
** the Free Software Foundation, either version 2 of the License, or
 | 
			
		||||
** (at your option) any later version.
 | 
			
		||||
**
 | 
			
		||||
** mkxp is distributed in the hope that it will be useful,
 | 
			
		||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
** GNU General Public License for more details.
 | 
			
		||||
**
 | 
			
		||||
** You should have received a copy of the GNU General Public License
 | 
			
		||||
** along with mkxp.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "../binding-util.h"
 | 
			
		||||
#include "mruby/string.h"
 | 
			
		||||
#include "mruby/array.h"
 | 
			
		||||
#include "mruby/class.h"
 | 
			
		||||
 | 
			
		||||
#include "time.h"
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct TimeImpl
 | 
			
		||||
{
 | 
			
		||||
	struct tm _tm;
 | 
			
		||||
	struct timeval _tv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const mrb_data_type TimeType =
 | 
			
		||||
{
 | 
			
		||||
    "Time",
 | 
			
		||||
    freeInstance<TimeImpl>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern mrb_value
 | 
			
		||||
timeFromSecondsInt(mrb_state *mrb, time_t seconds)
 | 
			
		||||
{
 | 
			
		||||
	TimeImpl *p = new TimeImpl;
 | 
			
		||||
 | 
			
		||||
	p->_tv.tv_sec = seconds;
 | 
			
		||||
	p->_tm = *localtime(&p->_tv.tv_sec);
 | 
			
		||||
 | 
			
		||||
	mrb_value obj = wrapObject(mrb, p, TimeType);
 | 
			
		||||
 | 
			
		||||
	return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
timeAt(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	mrb_int seconds;
 | 
			
		||||
	mrb_get_args(mrb, "i", &seconds);
 | 
			
		||||
 | 
			
		||||
	return timeFromSecondsInt(mrb, seconds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
timeNow(mrb_state *mrb, mrb_value)
 | 
			
		||||
{
 | 
			
		||||
	TimeImpl *p = new TimeImpl;
 | 
			
		||||
 | 
			
		||||
	gettimeofday(&p->_tv, 0);
 | 
			
		||||
	p->_tm = *localtime(&p->_tv.tv_sec);
 | 
			
		||||
 | 
			
		||||
	mrb_value obj = wrapObject(mrb, p, TimeType);
 | 
			
		||||
 | 
			
		||||
	return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
secondsAdded(mrb_state *mrb, TimeImpl *p, mrb_int seconds)
 | 
			
		||||
{
 | 
			
		||||
	TimeImpl *newP = new TimeImpl;
 | 
			
		||||
	*newP = *p;
 | 
			
		||||
 | 
			
		||||
	newP->_tv.tv_sec += seconds;
 | 
			
		||||
	p->_tm = *localtime(&p->_tv.tv_sec);
 | 
			
		||||
 | 
			
		||||
	return wrapObject(mrb, newP, TimeType);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
timePlus(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	mrb_int seconds;
 | 
			
		||||
	mrb_get_args(mrb, "i", &seconds);
 | 
			
		||||
 | 
			
		||||
	TimeImpl *p = getPrivateData<TimeImpl>(mrb, self);
 | 
			
		||||
 | 
			
		||||
	TimeImpl *newP = new TimeImpl;
 | 
			
		||||
	*newP = *p;
 | 
			
		||||
 | 
			
		||||
	newP->_tv.tv_sec += seconds;
 | 
			
		||||
	p->_tm = *localtime(&p->_tv.tv_sec);
 | 
			
		||||
 | 
			
		||||
	return wrapObject(mrb, newP, TimeType);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
timeMinus(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value minuent;
 | 
			
		||||
	mrb_get_args(mrb, "o", &minuent);
 | 
			
		||||
 | 
			
		||||
	TimeImpl *p = getPrivateData<TimeImpl>(mrb, self);
 | 
			
		||||
 | 
			
		||||
	if (mrb_fixnum_p(minuent))
 | 
			
		||||
	{
 | 
			
		||||
		mrb_int seconds = mrb_fixnum(minuent);
 | 
			
		||||
 | 
			
		||||
		return secondsAdded(mrb, p, -seconds);
 | 
			
		||||
	}
 | 
			
		||||
	else if (mrb_type(minuent) == MRB_TT_OBJECT)
 | 
			
		||||
	{
 | 
			
		||||
		TimeImpl *o = getPrivateDataCheck<TimeImpl>(mrb, minuent, TimeType);
 | 
			
		||||
 | 
			
		||||
		return mrb_float_value(mrb, p->_tv.tv_sec - o->_tv.tv_sec);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		mrb_raisef(mrb, E_TYPE_ERROR, "Expected Fixnum or Time, got %S",
 | 
			
		||||
		           mrb_str_new_cstr(mrb, mrb_class_name(mrb, mrb_class(mrb, minuent))));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return mrb_nil_value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
timeCompare(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	mrb_value cmpTo;
 | 
			
		||||
	mrb_get_args(mrb, "o", &cmpTo);
 | 
			
		||||
 | 
			
		||||
	mrb_int cmpToS = 0;
 | 
			
		||||
 | 
			
		||||
	if (mrb_fixnum_p(cmpTo))
 | 
			
		||||
	{
 | 
			
		||||
		cmpToS = mrb_fixnum(cmpTo);
 | 
			
		||||
	}
 | 
			
		||||
	else if (mrb_type(cmpTo) == MRB_TT_OBJECT)
 | 
			
		||||
	{
 | 
			
		||||
		TimeImpl *cmpToP = getPrivateDataCheck<TimeImpl>(mrb, cmpTo, TimeType);
 | 
			
		||||
		cmpToS = cmpToP->_tv.tv_sec;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		mrb_raisef(mrb, E_TYPE_ERROR, "Expected Fixnum or Time, got %S",
 | 
			
		||||
		           mrb_str_new_cstr(mrb, mrb_class_name(mrb, mrb_class(mrb, cmpTo))));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TimeImpl *p = getPrivateData<TimeImpl>(mrb, self);
 | 
			
		||||
	mrb_int selfS = p->_tv.tv_sec;
 | 
			
		||||
 | 
			
		||||
	if (selfS < cmpToS)
 | 
			
		||||
		return mrb_fixnum_value(-1);
 | 
			
		||||
	else if (selfS == cmpToS)
 | 
			
		||||
		return mrb_fixnum_value(0);
 | 
			
		||||
	else
 | 
			
		||||
		return mrb_fixnum_value(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static mrb_value
 | 
			
		||||
timeStrftime(mrb_state *mrb, mrb_value self)
 | 
			
		||||
{
 | 
			
		||||
	const char *format;
 | 
			
		||||
	mrb_get_args(mrb, "z", &format);
 | 
			
		||||
 | 
			
		||||
	TimeImpl *p = getPrivateData<TimeImpl>(mrb, self);
 | 
			
		||||
 | 
			
		||||
	static char buffer[512];
 | 
			
		||||
	strftime(buffer, sizeof(buffer), format, &p->_tm);
 | 
			
		||||
 | 
			
		||||
	return mrb_str_new_cstr(mrb, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define TIME_ATTR(attr) \
 | 
			
		||||
	static mrb_value \
 | 
			
		||||
	timeGet_##attr(mrb_state *mrb, mrb_value self) \
 | 
			
		||||
	{ \
 | 
			
		||||
		TimeImpl *p = getPrivateData<TimeImpl>(mrb, self); \
 | 
			
		||||
		return mrb_fixnum_value(p->_tm.tm_##attr); \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
TIME_ATTR(sec)
 | 
			
		||||
TIME_ATTR(min)
 | 
			
		||||
TIME_ATTR(hour)
 | 
			
		||||
TIME_ATTR(mday)
 | 
			
		||||
TIME_ATTR(mon)
 | 
			
		||||
TIME_ATTR(year)
 | 
			
		||||
TIME_ATTR(wday)
 | 
			
		||||
 | 
			
		||||
#define TIME_BIND_ATTR(attr) \
 | 
			
		||||
	{ mrb_define_method(mrb, klass, #attr, timeGet_##attr, MRB_ARGS_NONE()); }
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
timeBindingInit(mrb_state *mrb)
 | 
			
		||||
{
 | 
			
		||||
	RClass *klass = mrb_define_class(mrb, "Time", 0);
 | 
			
		||||
	mrb_include_module(mrb, klass, mrb_class_get(mrb, "Comparable"));
 | 
			
		||||
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "now", timeNow, MRB_ARGS_NONE());
 | 
			
		||||
	mrb_define_class_method(mrb, klass, "at", timeAt, MRB_ARGS_REQ(1));
 | 
			
		||||
 | 
			
		||||
	mrb_define_method(mrb, klass, "+", timePlus, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_method(mrb, klass, "-", timeMinus, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_method(mrb, klass, "<=>", timeCompare, MRB_ARGS_REQ(1));
 | 
			
		||||
	mrb_define_method(mrb, klass, "strftime", timeStrftime, MRB_ARGS_REQ(1));
 | 
			
		||||
 | 
			
		||||
	TIME_BIND_ATTR(sec);
 | 
			
		||||
	TIME_BIND_ATTR(min);
 | 
			
		||||
	TIME_BIND_ATTR(hour);
 | 
			
		||||
	TIME_BIND_ATTR(mday);
 | 
			
		||||
	TIME_BIND_ATTR(mon);
 | 
			
		||||
	TIME_BIND_ATTR(year);
 | 
			
		||||
	TIME_BIND_ATTR(wday);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue