Skip to content

Instantly share code, notes, and snippets.

@matthewd
Created May 21, 2010 18:20
Show Gist options
  • Select an option

  • Save matthewd/409207 to your computer and use it in GitHub Desktop.

Select an option

Save matthewd/409207 to your computer and use it in GitHub Desktop.
diff --git a/spec/capi/ext/symbol_spec.c b/spec/capi/ext/symbol_spec.c
new file mode 100644
index 0000000..79f0250
--- /dev/null
+++ b/spec/capi/ext/symbol_spec.c
@@ -0,0 +1,22 @@
+#include "ruby.h"
+
+VALUE symbol_spec_rb_is_const_id(VALUE self, VALUE sym) {
+ return rb_is_const_id(SYM2ID(sym));
+}
+
+VALUE symbol_spec_rb_is_instance_id(VALUE self, VALUE sym) {
+ return rb_is_instance_id(SYM2ID(sym));
+}
+
+VALUE symbol_spec_rb_is_class_id(VALUE self, VALUE sym) {
+ return rb_is_class_id(SYM2ID(sym));
+}
+
+void Init_symbol_spec() {
+ VALUE cls;
+ cls = rb_define_class("CApiSymbolSpecs", rb_cObject);
+
+ rb_define_method(cls, "rb_is_const_id", symbol_spec_rb_is_const_id, 1);
+ rb_define_method(cls, "rb_is_instance_id", symbol_spec_rb_is_instance_id, 1);
+ rb_define_method(cls, "rb_is_class_id", symbol_spec_rb_is_class_id, 1);
+}
diff --git a/spec/capi/symbol_spec.rb b/spec/capi/symbol_spec.rb
new file mode 100644
index 0000000..c94d274
--- /dev/null
+++ b/spec/capi/symbol_spec.rb
@@ -0,0 +1,63 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+load_extension('symbol')
+
+describe "C-API Symbol function" do
+ before :each do
+ @s = CApiSymbolSpecs.new
+ end
+
+ describe "rb_is_const_id" do
+ it "returns true given a const-like symbol" do
+ @s.rb_is_const_id(:Foo).should == true
+ end
+
+ it "returns false given an ivar-like symbol" do
+ @s.rb_is_const_id(:@foo).should == false
+ end
+
+ it "returns false given a cvar-like symbol" do
+ @s.rb_is_const_id(:@@foo).should == false
+ end
+
+ it "returns false given an undecorated symbol" do
+ @s.rb_is_const_id(:foo).should == false
+ end
+ end
+
+ describe "rb_is_instance_id" do
+ it "returns false given a const-like symbol" do
+ @s.rb_is_instance_id(:Foo).should == false
+ end
+
+ it "returns true given an ivar-like symbol" do
+ @s.rb_is_instance_id(:@foo).should == true
+ end
+
+ it "returns false given a cvar-like symbol" do
+ @s.rb_is_instance_id(:@@foo).should == false
+ end
+
+ it "returns false given an undecorated symbol" do
+ @s.rb_is_instance_id(:foo).should == false
+ end
+ end
+
+ describe "rb_is_class_id" do
+ it "returns false given a const-like symbol" do
+ @s.rb_is_class_id(:Foo).should == false
+ end
+
+ it "returns false given an ivar-like symbol" do
+ @s.rb_is_class_id(:@foo).should == false
+ end
+
+ it "returns true given a cvar-like symbol" do
+ @s.rb_is_class_id(:@@foo).should == true
+ end
+
+ it "returns false given an undecorated symbol" do
+ @s.rb_is_class_id(:foo).should == false
+ end
+ end
+end
diff --git a/vm/capi/ruby.h b/vm/capi/ruby.h
index e66dc54..588fa0e 100644
--- a/vm/capi/ruby.h
+++ b/vm/capi/ruby.h
@@ -736,6 +736,15 @@ VALUE rb_uint2big(unsigned long number);
/** Return Qtrue if obj is an immediate, Qfalse or Qnil. */
int rb_special_const_p(VALUE obj);
+ /** Return Qtrue if sym is suitable as a name of a constant. */
+ int rb_is_const_id(ID sym);
+
+ /** Return Qtrue if sym is suitable as a name of an instance variable. */
+ int rb_is_instance_id(ID sym);
+
+ /** Return Qtrue if sym is suitable as a name of a class variable. */
+ int rb_is_class_id(ID sym);
+
/** Return obj if it is an Array, or return wrapped (i.e. [obj]) */
VALUE rb_Array(VALUE obj_handle);
diff --git a/vm/capi/symbol.cpp b/vm/capi/symbol.cpp
new file mode 100644
index 0000000..ceff50f
--- /dev/null
+++ b/vm/capi/symbol.cpp
@@ -0,0 +1,33 @@
+#include "builtin/symbol.hpp"
+
+#include "capi/capi.hpp"
+#include "capi/ruby.h"
+
+using namespace rubinius;
+using namespace rubinius::capi;
+
+extern "C" {
+ const char *rb_id2name(ID sym) {
+ NativeMethodEnvironment* env = NativeMethodEnvironment::get();
+
+ return reinterpret_cast<Symbol*>(sym)->c_str(env->state());
+ }
+
+ int rb_is_const_id(ID sym) {
+ NativeMethodEnvironment* env = NativeMethodEnvironment::get();
+
+ return RBX_RTEST(reinterpret_cast<Symbol*>(sym)->is_constant_p(env->state())) ? Qtrue : Qfalse;
+ }
+
+ int rb_is_instance_id(ID sym) {
+ NativeMethodEnvironment* env = NativeMethodEnvironment::get();
+
+ return RBX_RTEST(reinterpret_cast<Symbol*>(sym)->is_ivar_p(env->state())) ? Qtrue : Qfalse;
+ }
+
+ int rb_is_class_id(ID sym) {
+ NativeMethodEnvironment* env = NativeMethodEnvironment::get();
+
+ return RBX_RTEST(reinterpret_cast<Symbol*>(sym)->is_cvar_p(env->state())) ? Qtrue : Qfalse;
+ }
+}
diff --git a/vm/capi/util.cpp b/vm/capi/util.cpp
index bc27a65..6fe4bef 100644
--- a/vm/capi/util.cpp
+++ b/vm/capi/util.cpp
@@ -5,12 +5,6 @@ using namespace rubinius;
using namespace rubinius::capi;
extern "C" {
- const char *rb_id2name(ID sym) {
- NativeMethodEnvironment* env = NativeMethodEnvironment::get();
-
- return reinterpret_cast<Symbol*>(sym)->c_str(env->state());
- }
-
int rb_scan_args(int argc, const VALUE* argv, const char* spec, ...) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment