about summary refs log tree commit homepage
path: root/ext/sleepy_penguin/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sleepy_penguin/util.c')
-rw-r--r--ext/sleepy_penguin/util.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/ext/sleepy_penguin/util.c b/ext/sleepy_penguin/util.c
new file mode 100644
index 0000000..d8b27d4
--- /dev/null
+++ b/ext/sleepy_penguin/util.c
@@ -0,0 +1,122 @@
+#include "sleepy_penguin.h"
+
+static VALUE klass_for(VALUE klass)
+{
+        return (TYPE(klass) == T_CLASS) ? klass : CLASS_OF(klass);
+}
+
+int rb_sp_get_flags(VALUE klass, VALUE flags)
+{
+        switch (TYPE(flags)) {
+        case T_NIL: return 0;
+        case T_FIXNUM: return FIX2INT(flags);
+        case T_BIGNUM: return NUM2INT(flags);
+        case T_SYMBOL:
+                return NUM2INT(rb_const_get(klass_for(klass), SYM2ID(flags)));
+        case T_ARRAY: {
+                VALUE *ptr = RARRAY_PTR(flags);
+                long len = RARRAY_LEN(flags);
+                int rv = 0;
+
+                klass = klass_for(klass);
+                while (--len >= 0) {
+                        VALUE tmp = *ptr++;
+
+                        Check_Type(tmp, T_SYMBOL);
+                        tmp = rb_const_get(klass, SYM2ID(tmp));
+                        rv |= NUM2INT(tmp);
+                }
+                return rv;
+                }
+        }
+        rb_raise(rb_eTypeError, "invalid flags");
+        return 0;
+}
+
+unsigned rb_sp_get_uflags(VALUE klass, VALUE flags)
+{
+        switch (TYPE(flags)) {
+        case T_NIL: return 0;
+        case T_FIXNUM: return FIX2UINT(flags);
+        case T_BIGNUM: return NUM2UINT(flags);
+        case T_SYMBOL:
+                return NUM2UINT(rb_const_get(klass_for(klass), SYM2ID(flags)));
+        case T_ARRAY: {
+                VALUE *ptr = RARRAY_PTR(flags);
+                long len = RARRAY_LEN(flags);
+                unsigned rv = 0;
+
+                klass = klass_for(klass);
+                while (--len >= 0) {
+                        VALUE tmp = *ptr++;
+
+                        Check_Type(tmp, T_SYMBOL);
+                        tmp = rb_const_get(klass, SYM2ID(tmp));
+                        rv |= NUM2UINT(tmp);
+                }
+                return rv;
+                }
+        }
+        rb_raise(rb_eTypeError, "invalid flags");
+        return 0;
+}
+
+#if ! HAVE_RB_IO_T
+#  define rb_io_t OpenFile
+#endif
+
+#ifdef GetReadFile
+#  define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
+#else
+#  if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
+#    define FPTR_TO_FD(fptr) fileno(fptr->f)
+#  else
+#    define FPTR_TO_FD(fptr) fptr->fd
+#  endif
+#endif
+
+static int fixint_closed_p(VALUE io)
+{
+        return (fcntl(FIX2INT(io), F_GETFD) == -1 && errno == EBADF);
+}
+
+#if defined(RFILE) && defined(HAVE_ST_FD)
+static int my_rb_io_closed(VALUE io)
+{
+        return RFILE(io)->fptr->fd < 0;
+}
+#else
+static int my_rb_io_closed(VALUE io)
+{
+        return rb_funcall(io, rb_intern("closed?"), 0) == Qtrue;
+}
+#endif
+
+int rb_sp_io_closed(VALUE io)
+{
+        switch (TYPE(io)) {
+        case T_FIXNUM:
+                return fixint_closed_p(io);
+        case T_FILE:
+                break;
+        default:
+                io = rb_convert_type(io, T_FILE, "IO", "to_io");
+        }
+
+        return my_rb_io_closed(io);
+}
+
+int rb_sp_fileno(VALUE io)
+{
+        rb_io_t *fptr;
+
+        switch (TYPE(io)) {
+        case T_FIXNUM: return FIX2INT(io);
+        case T_FILE:
+                GetOpenFile(io, fptr);
+                return FPTR_TO_FD(fptr);
+        }
+        io = rb_convert_type(io, T_FILE, "IO", "to_io");
+        GetOpenFile(io, fptr);
+        return FPTR_TO_FD(fptr);
+}