public
Description: A lean-and-mean Ruby/ObjC bridge
Homepage: http://rubyobjc.com
Clone URL: git://github.com/timburks/rubyobjc.git
rubyobjc / objc / objc_variable.m
100644 161 lines (143 sloc) 4.939 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
* objc_variable.m
*
* Defines a Ruby wrapper that allows Objective-C instance variables to be manipulated from Ruby.
*
* Copyright (c) 2007 Tim Burks, Neon Design Technology, Inc.
* For more information about this file, visit http://www.rubyobjc.com.
*/
 
/*
* Document-class: ObjC::Variable
*
* ObjC::Variable wraps Objective-C instance variables for manipulation from Ruby.
*
* The methods of this class allow the names, type encodings, and other properties of
* Objective-C instance variables to be accessed from Ruby.
* ObjC::Variable objects are returned by the ivars methods of ObjC::Class and ObjC::Object.
*/
#import "rubyobjc.h"
 
static VALUE __variable_class;
 
//////////////////////////////////////////////////////////////////
 
void variable_free(void *p)
{
    free(p);
}
 
VALUE variable_alloc(VALUE klass)
{
    ObjC_Variable *variable = (ObjC_Variable *) malloc (sizeof (ObjC_Variable));
    variable->v = 0;
    return Data_Wrap_Struct(klass, 0, variable_free, variable);
}
 
VALUE variable_create(Ivar v)
{
    ObjC_Variable *variable = (ObjC_Variable *) malloc (sizeof (ObjC_Variable));
    variable->v = v;
    return Data_Wrap_Struct(__variable_class, 0, variable_free, variable);
}
 
/*
* Get the name of the corresponding Objective-C instance variable.
*/
VALUE variable_name(VALUE self)
{
    ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Ivar v = variable->v;
    return v ? rb_str_new2(v->ivar_name) : Qnil;
}
 
/*
* Get the type encoding of the corresponding Objective-C instance variable.
*/
VALUE variable_type_encoding(VALUE self)
{
    ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Ivar v = variable->v;
    return v ? rb_str_new2(v->ivar_type) : Qnil;
}
 
/*
* Get the offset of the corresponding Objective-C instance variable.
*/
VALUE variable_offset(VALUE self)
{
    ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Ivar v = variable->v;
    return v ? INT2NUM(v->ivar_offset) : Qnil;
}
 
VALUE variable_get(VALUE self, VALUE object)
{
  ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Ivar v = variable->v;
 
    ObjC_Object *object_struct;
    Data_Get_Struct(object, ObjC_Object, object_struct);
    id o = object_struct->o;
  void *location = (void *)&(((char *)o)[v->ivar_offset]);
  VALUE result = get_ruby_value_from_objc_value(location, v->ivar_type, 0);
  return result;
}
 
VALUE variable_set(VALUE self, VALUE object, VALUE value)
{
  ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Ivar v = variable->v;
 
    ObjC_Object *object_struct;
    Data_Get_Struct(object, ObjC_Object, object_struct);
    id o = object_struct->o;
  void *location = (void *)&(((char *)o)[v->ivar_offset]);
  set_objc_value_from_ruby_value(location, value, v->ivar_type);
  return Qnil;
}
 
/*
* Compare the variable with another variable <i>p1</i>.
*/
VALUE variable_compare(VALUE self, VALUE other)
{
    ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    ObjC_Variable *other_variable;
    Data_Get_Struct(other, ObjC_Variable, other_variable);
    int r = strcmp(variable->v->ivar_name, other_variable->v->ivar_name);
    return INT2NUM(r);
}
 
/*
* Test variable for equality with another variable <i>p1</i>.
*/
VALUE variable_equal(VALUE self, VALUE other)
{
    if (TYPE(other) != T_DATA) return Qfalse;
    ObjC_Variable *variable, *other_variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Data_Get_Struct(other, ObjC_Variable, other_variable);
    return (variable->v == other_variable->v) ? Qtrue : Qfalse;
}
 
/*
* Get a hash value for a variable.
*/
VALUE variable_hash(VALUE self)
{
    ObjC_Variable *variable;
    Data_Get_Struct(self, ObjC_Variable, variable);
    Ivar v = variable->v;
    return INT2FIX((int) v);
}
 
//
// ObjC instance variables are mapped to instances of ObjC::Variable
//
void Init_ObjC_Variable(VALUE module)
{
                                                  // needed by RDoc
    if (!module) module = rb_define_module("ObjC");
    __variable_class = rb_define_class_under(module, "Variable", rb_cObject);
    rb_define_alloc_func(__variable_class, variable_alloc);
    rb_define_method(__variable_class, "name", variable_name, 0);
    rb_define_method(__variable_class, "type_encoding", variable_type_encoding, 0);
    rb_define_method(__variable_class, "offset", variable_offset, 0);
    rb_define_method(__variable_class, "_get", variable_get, 1);
  rb_define_method(__variable_class, "_set", variable_set, 2);
    rb_define_method(__variable_class, "to_s", variable_name, 0);
    rb_define_method(__variable_class, "<=>", variable_compare, 1);
    rb_define_method(__variable_class, "==", variable_equal, 1);
    rb_define_method(__variable_class, "eql?", variable_equal, 1);
    rb_define_method(__variable_class, "hash", variable_hash, 0);
}