virtualbox-com 0.9.9 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +339 -19
- data/examples/simple.rb +2 -0
- data/ext/virtualbox-com/4.1/extconf.rb +4 -0
- data/ext/virtualbox-com/4.1/generated.inc +17345 -0
- data/ext/virtualbox-com/4.1/vbox.c +858 -0
- data/ext/virtualbox-com/4.2/extconf.rb +4 -0
- data/ext/virtualbox-com/4.2/generated.inc +19751 -0
- data/ext/virtualbox-com/4.2/vbox.c +858 -0
- data/ext/virtualbox-com/helpers.h +62 -0
- data/ext/virtualbox-com/loader/extconf.rb +3 -0
- data/ext/virtualbox-com/loader/vbox-loader.c +187 -0
- data/ext/virtualbox-com/types.h +34 -0
- data/ext/virtualbox-com/vbox.c +858 -0
- data/lib/virtualbox/com.rb +4 -26
- data/lib/virtualbox/com/{abstract_enum.rb → abstracts.rb} +22 -18
- data/lib/virtualbox/com/exceptions.rb +29 -3
- data/lib/virtualbox/com/model/4.1-generated.rb +2141 -0
- data/lib/virtualbox/com/model/4.2-generated.rb +141 -432
- data/lib/virtualbox/com/model/4.2.rb +4 -4
- data/lib/virtualbox/com/util.rb +2 -1
- data/lib/virtualbox/com/version.rb +1 -1
- data/lib/virtualbox/com/xpcomc-ffi.rb +5 -19
- data/lib/virtualbox/com/xpcomc-ffi/abstracts.rb +103 -0
- data/lib/virtualbox/com/{iid.rb → xpcomc-ffi/iid.rb} +18 -0
- data/lib/virtualbox/com/xpcomc-ffi/lib.rb +6 -0
- data/lib/virtualbox/com/xpcomc-ffi/model-types.rb +1 -0
- data/lib/virtualbox/com/xpcomc-native.rb +8 -0
- data/scripts/abstracts.rb +84 -0
- data/scripts/sig.rb +201 -0
- data/scripts/spec.rb +56 -0
- data/scripts/to_c.rb +157 -0
- data/scripts/xidl-conv.rb +110 -50
- data/virtualbox-com.gemspec +18 -11
- metadata +49 -47
- data/.gitignore +0 -9
- data/README.md +0 -89
- data/Rakefile +0 -8
- data/lib/virtualbox/com/abstract_interface.rb +0 -144
- data/lib/virtualbox/com/abstract_model.rb +0 -14
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
#define SYM(str) ID2SYM(rb_intern(str))
|
3
|
+
|
4
|
+
|
5
|
+
#if 2 == SIZEOF_SHORT
|
6
|
+
# define NUM2INT16(val) NUM2SHORT(val)
|
7
|
+
# define NUM2UINT16(val) NUM2USHORT(val)
|
8
|
+
#elif 2 == SIZEOF_INT
|
9
|
+
# define NUM2INT16(val) NUM2INT(val)
|
10
|
+
# define NUM2UINT16(val) NUM2UINT(val)
|
11
|
+
#elif 2 == SIZEOF_LONG
|
12
|
+
# define NUM2INT16(val) NUM2LONG(val)
|
13
|
+
# define NUM2UINT16(val) NUM2ULONG(val)
|
14
|
+
#elif 2 == SIZEOF_LONG_LONG
|
15
|
+
# define NUM2INT16(val) NUM2LL(val)
|
16
|
+
# define NUM2UINT16(val) NUM2ULL(val)
|
17
|
+
#else
|
18
|
+
# error "unknown conversion"
|
19
|
+
#endif
|
20
|
+
|
21
|
+
#if 4 == SIZEOF_SHORT
|
22
|
+
# define NUM2INT32(val) NUM2SHORT(val)
|
23
|
+
# define NUM2UINT32(val) NUM2USHORT(val)
|
24
|
+
#elif 4 == SIZEOF_INT
|
25
|
+
# define NUM2INT32(val) NUM2INT(val)
|
26
|
+
# define NUM2UINT32(val) NUM2UINT(val)
|
27
|
+
#elif 4 == SIZEOF_LONG
|
28
|
+
# define NUM2INT32(val) NUM2LONG(val)
|
29
|
+
# define NUM2UINT32(val) NUM2ULONG(val)
|
30
|
+
#elif 4 == SIZEOF_LONG_LONG
|
31
|
+
# define NUM2INT32(val) NUM2LL(val)
|
32
|
+
# define NUM2UINT32(val) NUM2ULL(val)
|
33
|
+
#else
|
34
|
+
# error "unknown conversion"
|
35
|
+
#endif
|
36
|
+
|
37
|
+
#if 8 == SIZEOF_SHORT
|
38
|
+
# define NUM2INT64(val) NUM2SHORT(val)
|
39
|
+
# define NUM2UINT64(val) NUM2USHORT(val)
|
40
|
+
#elif 8 == SIZEOF_INT
|
41
|
+
# define NUM2INT64(val) NUM2INT(val)
|
42
|
+
# define NUM2UINT64(val) NUM2UINT(val)
|
43
|
+
#elif 8 == SIZEOF_LONG
|
44
|
+
# define NUM2INT64(val) NUM2LONG(val)
|
45
|
+
# define NUM2UINT64(val) NUM2ULONG(val)
|
46
|
+
#elif 8 == SIZEOF_LONG_LONG
|
47
|
+
# define NUM2INT64(val) NUM2LL(val)
|
48
|
+
# define NUM2UINT64(val) NUM2ULL(val)
|
49
|
+
#else
|
50
|
+
# error "unknown conversion"
|
51
|
+
#endif
|
52
|
+
|
53
|
+
|
54
|
+
#if SIZEOF_LONG == SIZEOF_VOIDP
|
55
|
+
# define NUM2PTR(val) NUM2ULONG(val)
|
56
|
+
# define PTR2NUM(ptr) ULONG2NUM(ptr)
|
57
|
+
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
|
58
|
+
# define NUM2PTR(val) NUM2ULL(val)
|
59
|
+
# define PTR2NUM(ptr) ULL2NUM(ptr)
|
60
|
+
#else
|
61
|
+
# error "unknown converion"
|
62
|
+
#endif
|
@@ -0,0 +1,187 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <stdarg.h>
|
5
|
+
#include <dlfcn.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
#include <ruby.h>
|
9
|
+
#include <ruby/encoding.h>
|
10
|
+
|
11
|
+
#include "../types.h"
|
12
|
+
|
13
|
+
#define VBOX_APP_HOME "VBOX_APP_HOME"
|
14
|
+
#define VBOX_XPCOMC_VERSION 0x00020000U
|
15
|
+
|
16
|
+
|
17
|
+
/*======================================================================
|
18
|
+
* Define basic structure and functions necessary to init XPCom
|
19
|
+
* Open dynamic library and retrieve XPCOM functions
|
20
|
+
*======================================================================*/
|
21
|
+
|
22
|
+
#if defined(__linux__) || defined(__linux_gnu__) || \
|
23
|
+
defined(__sun__) || defined(__FreeBSD__)
|
24
|
+
# define VBOX_DYNLIB_NAME "VBoxXPCOMC.so"
|
25
|
+
#elif defined(__APPLE__)
|
26
|
+
# define VBOX_DYNLIB_NAME "VBoxXPCOMC.dylib"
|
27
|
+
#elif defined(_MSC_VER) || defined(__OS2__)
|
28
|
+
# define VBOX_DYNLIB_NAME "VBoxXPCOMC.dll"
|
29
|
+
#else
|
30
|
+
# error "Need to be ported to this platform"
|
31
|
+
#endif
|
32
|
+
|
33
|
+
|
34
|
+
#if defined(__OS2__)
|
35
|
+
# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "_VBoxGetXPCOMCFunctions"
|
36
|
+
#else
|
37
|
+
# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "VBoxGetXPCOMCFunctions"
|
38
|
+
#endif
|
39
|
+
|
40
|
+
|
41
|
+
static char *VBoxHome[] = {
|
42
|
+
#if defined(__gnu__linux__) || defined(__linux__)
|
43
|
+
"/opt/VirtualBox",
|
44
|
+
"/usr/lib/virtualbox",
|
45
|
+
#elif defined(__sun__)
|
46
|
+
"/opt/VirtualBox/amd64",
|
47
|
+
"/opt/VirtualBox/i386",
|
48
|
+
#elif defined(__APPLE__)
|
49
|
+
"/Application/VirtualBox.app/Contents/MacOS",
|
50
|
+
#elif defined(__FreeBSD__)
|
51
|
+
"/usr/local/lib/virtualbox",
|
52
|
+
#endif
|
53
|
+
NULL
|
54
|
+
};
|
55
|
+
|
56
|
+
|
57
|
+
static VBOX_XPCOMC virtualbox_load(char *home, void **dl_ptr) {
|
58
|
+
char *path = NULL;
|
59
|
+
void *dl = NULL;
|
60
|
+
void *sym = NULL;
|
61
|
+
void *funcs = NULL;
|
62
|
+
|
63
|
+
/* Deal with environment variable */
|
64
|
+
if (home) { setenv(VBOX_APP_HOME, home, 1); }
|
65
|
+
else { unsetenv(VBOX_APP_HOME); }
|
66
|
+
|
67
|
+
/* Build library full path */
|
68
|
+
if (home) {
|
69
|
+
size_t len = strlen(home) + 1 + sizeof(VBOX_DYNLIB_NAME);
|
70
|
+
path = malloc(len+1);
|
71
|
+
snprintf(path, len+1, "%s/%s", home, VBOX_DYNLIB_NAME);
|
72
|
+
}
|
73
|
+
|
74
|
+
/* Open lib */
|
75
|
+
if (! (dl = dlopen(path, RTLD_NOW | RTLD_LOCAL)))
|
76
|
+
goto failed;
|
77
|
+
|
78
|
+
/* Retrieve symbole */
|
79
|
+
if (! (sym = dlsym(dl, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME))) {
|
80
|
+
rb_warn("dlsym(%s/%s): %s",
|
81
|
+
path, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, dlerror());
|
82
|
+
goto failed;
|
83
|
+
}
|
84
|
+
|
85
|
+
/* Retrieve vbox xpcomc functions */
|
86
|
+
if (! (funcs = ((VBOX_GET_XPCOMC_FUNCTIONS)sym)(VBOX_XPCOMC_VERSION))) {
|
87
|
+
rb_warn("%s: pfnGetFunctions(%#x) failed", path, VBOX_XPCOMC_VERSION);
|
88
|
+
goto failed;
|
89
|
+
}
|
90
|
+
|
91
|
+
/* Returns */
|
92
|
+
free(path);
|
93
|
+
if (*dl_ptr) *dl_ptr = dl;
|
94
|
+
return funcs;
|
95
|
+
|
96
|
+
failed:
|
97
|
+
if (dl ) dlclose(dl);
|
98
|
+
if (path) free(path);
|
99
|
+
return NULL;
|
100
|
+
}
|
101
|
+
|
102
|
+
static VBOX_XPCOMC virtualbox_init(void **dl_ptr) {
|
103
|
+
char *home = getenv(VBOX_APP_HOME);
|
104
|
+
char **hlist = VBoxHome;
|
105
|
+
|
106
|
+
if (home)
|
107
|
+
return virtualbox_load(home, dl_ptr);
|
108
|
+
|
109
|
+
while ((home = *hlist++)) {
|
110
|
+
VBOX_XPCOMC xpcom = virtualbox_load(home, dl_ptr);
|
111
|
+
if (xpcom) return xpcom;
|
112
|
+
}
|
113
|
+
|
114
|
+
return virtualbox_load(NULL, dl_ptr);
|
115
|
+
}
|
116
|
+
|
117
|
+
static void virtualbox_destroy(void *dl) {
|
118
|
+
if (dl) {
|
119
|
+
#if 0 /* VBoxRT.so doesn't like being reloaded. See @bugref{3725}. */
|
120
|
+
dlclose(dl);
|
121
|
+
#endif
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
/*======================================================================
|
127
|
+
* Load virtualbox library and ruby classes according to detected version
|
128
|
+
* Create necessary hooks
|
129
|
+
*======================================================================*/
|
130
|
+
|
131
|
+
/* export symbol for implementing classes */
|
132
|
+
VBOX_XPCOMC virtualbox_com_xpcom = NULL;
|
133
|
+
|
134
|
+
/* import symbol for class creation */
|
135
|
+
extern VALUE virtualbox_com_virtualbox(void *ptr);
|
136
|
+
extern VALUE virtualbox_com_session(void *ptr);
|
137
|
+
|
138
|
+
/* ruby calls this to load the extension */
|
139
|
+
void Init_vbox_loader(void) {
|
140
|
+
void * vlib = NULL;
|
141
|
+
VBOX_XPCOMC xpcom = NULL;
|
142
|
+
char * api = NULL;
|
143
|
+
char * xtra = NULL;
|
144
|
+
void *vbox, *session, *queue;
|
145
|
+
|
146
|
+
/* Virtualbox */
|
147
|
+
xpcom = virtualbox_com_xpcom = virtualbox_init(&vlib);
|
148
|
+
|
149
|
+
/* 4.1 */
|
150
|
+
api = "virtualbox/com/xpcomc-native/vbox_4_1";
|
151
|
+
xtra = "virtualbox/com/model/4.1";
|
152
|
+
xpcom->initialize("c28be65f-1a8f-43b4-81f1-eb60cb516e66", &vbox,
|
153
|
+
"12f4dcdb-12b2-4ec1-b7cd-ddd9f6c5bf4d", &session);
|
154
|
+
if (vbox && session) goto found;
|
155
|
+
|
156
|
+
/* 4.2 */
|
157
|
+
api = "virtualbox/com/xpcomc-native/vbox_4_2";
|
158
|
+
xtra = "virtualbox/com/model/4.2";
|
159
|
+
xpcom->initialize("3b2f08eb-b810-4715-bee0-bb06b9880ad2", &vbox,
|
160
|
+
"12f4dcdb-12b2-4ec1-b7cd-ddd9f6c5bf4d", &session);
|
161
|
+
if (vbox && session) goto found;
|
162
|
+
|
163
|
+
/* Not supported (exception is raised) */
|
164
|
+
rb_loaderror("Virtualbox version not supported");
|
165
|
+
/* NOT REACHED */
|
166
|
+
|
167
|
+
found:
|
168
|
+
rb_require(api);
|
169
|
+
rb_require(xtra);
|
170
|
+
|
171
|
+
VALUE mVirtualBox = rb_define_module("VirtualBox");
|
172
|
+
VALUE mCOM = rb_define_module_under(mVirtualBox, "COM");
|
173
|
+
VALUE mModel = rb_define_module_under(mCOM, "Model");
|
174
|
+
|
175
|
+
/* Instantiate VirtualBox and Session class */
|
176
|
+
rb_const_set(mCOM, rb_intern("VIRTUALBOX"),
|
177
|
+
virtualbox_com_virtualbox(vbox));
|
178
|
+
rb_const_set(mCOM, rb_intern("SESSION"),
|
179
|
+
virtualbox_com_session(vbox));
|
180
|
+
|
181
|
+
#if 0
|
182
|
+
/* Instantiate event queue */
|
183
|
+
xpcom->get_event_queue(&queue);
|
184
|
+
printf("Got the event queue: %p\n", (void *)queue);
|
185
|
+
#endif
|
186
|
+
|
187
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
typedef int bool_t;
|
2
|
+
typedef uint16_t *wstring_t;
|
3
|
+
|
4
|
+
typedef struct iid {
|
5
|
+
uint32_t m0;
|
6
|
+
uint16_t m1;
|
7
|
+
uint16_t m2;
|
8
|
+
uint8_t m3[8];
|
9
|
+
} iid_t;
|
10
|
+
|
11
|
+
struct obj {
|
12
|
+
void * vtbl;
|
13
|
+
};
|
14
|
+
|
15
|
+
|
16
|
+
typedef struct VBOX_XPCOMC {
|
17
|
+
unsigned cb;
|
18
|
+
unsigned uVersion;
|
19
|
+
unsigned int (*get_version )(void);
|
20
|
+
void (*initialize )(const char *virtualBoxIID,
|
21
|
+
void **virtualBox,
|
22
|
+
const char *sessionIID,
|
23
|
+
void **session);
|
24
|
+
void (*uninitialize )(void);
|
25
|
+
void (*unalloc_mem )(void *pv);
|
26
|
+
void (*utf16_free )(wstring_t u16);
|
27
|
+
void (*utf8_free )(char *u8);
|
28
|
+
int (*utf16_to_utf8 )(const wstring_t u16, char **u8);
|
29
|
+
int (*utf8_to_utf16 )(const char *u8, wstring_t *u16);
|
30
|
+
void (*get_event_queue)(void **eventQueue);
|
31
|
+
unsigned uEndVersion;
|
32
|
+
} * VBOX_XPCOMC;
|
33
|
+
typedef VBOX_XPCOMC (*VBOX_GET_XPCOMC_FUNCTIONS)(unsigned uVersion);
|
34
|
+
|
@@ -0,0 +1,858 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <stdarg.h>
|
5
|
+
#include <dlfcn.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
#include <ruby.h>
|
9
|
+
#include <ruby/encoding.h>
|
10
|
+
|
11
|
+
#include "../types.h"
|
12
|
+
#include "../helpers.h"
|
13
|
+
|
14
|
+
#define NS_CHECK(x) ns_check(x)
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
/*======================================================================
|
20
|
+
* Ruby shortcut
|
21
|
+
* - handle conversion to fixed size type (int, pointer)
|
22
|
+
*======================================================================*/
|
23
|
+
|
24
|
+
|
25
|
+
extern VBOX_XPCOMC virtualbox_com_xpcom;
|
26
|
+
|
27
|
+
|
28
|
+
static VBOX_XPCOMC xpcom = NULL;
|
29
|
+
|
30
|
+
static VALUE mVirtualBox = Qundef;
|
31
|
+
static VALUE mCOM = Qundef;
|
32
|
+
static VALUE mModel = Qundef;
|
33
|
+
|
34
|
+
static VALUE cBlob = Qundef;
|
35
|
+
static VALUE cWString = Qundef;
|
36
|
+
static VALUE cCArray = Qundef;
|
37
|
+
static VALUE cIID = Qundef;
|
38
|
+
static VALUE cAbstractModel = Qundef;
|
39
|
+
static VALUE cAbstractInterface = Qundef;
|
40
|
+
static VALUE cAbstractEnum = Qundef;
|
41
|
+
|
42
|
+
static VALUE oZero = Qundef;
|
43
|
+
static VALUE oMax_u16 = Qundef;
|
44
|
+
static VALUE oMax_u32 = Qundef;
|
45
|
+
static VALUE oMax_u64 = Qundef;
|
46
|
+
static VALUE oMax_s16 = Qundef;
|
47
|
+
static VALUE oMax_s32 = Qundef;
|
48
|
+
static VALUE oMax_s64 = Qundef;
|
49
|
+
static VALUE oMin_s16 = Qundef;
|
50
|
+
static VALUE oMin_s32 = Qundef;
|
51
|
+
static VALUE oMin_s64 = Qundef;
|
52
|
+
static VALUE oExceptionMap = Qundef;
|
53
|
+
|
54
|
+
static VALUE sYes = Qundef;
|
55
|
+
static VALUE sNo = Qundef;
|
56
|
+
static VALUE sTrue = Qundef;
|
57
|
+
static VALUE sFalse = Qundef;
|
58
|
+
static VALUE sOn = Qundef;
|
59
|
+
static VALUE sOff = Qundef;
|
60
|
+
static VALUE sEnabled = Qundef;
|
61
|
+
static VALUE sDisabled = Qundef;
|
62
|
+
static VALUE sIID = Qundef;
|
63
|
+
static VALUE sCode = Qundef;
|
64
|
+
static VALUE sFunction = Qundef;
|
65
|
+
|
66
|
+
static ID _IID;
|
67
|
+
static ID _map;
|
68
|
+
static ID _brackets;
|
69
|
+
static ID _bracketseq;
|
70
|
+
static ID _pow;
|
71
|
+
static ID _minus;
|
72
|
+
static ID _neg;
|
73
|
+
static ID _ge;
|
74
|
+
static ID _le;
|
75
|
+
static ID _is_a;
|
76
|
+
static ID _dup;
|
77
|
+
static ID _symbol;
|
78
|
+
static ID _value;
|
79
|
+
static ID _const_get;
|
80
|
+
static ID _new;
|
81
|
+
|
82
|
+
static rb_encoding * _UTF8;
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
static void no_instantiation(VALUE klass) {
|
88
|
+
rb_undef_method(rb_singleton_class(klass), "new");
|
89
|
+
rb_undef_alloc_func(klass);
|
90
|
+
}
|
91
|
+
|
92
|
+
|
93
|
+
static void ns_check(uint32_t rcode) {
|
94
|
+
if (rcode & 0x80000000) {
|
95
|
+
VALUE c = ULL2NUM(rcode);
|
96
|
+
VALUE k = rb_funcall(oExceptionMap, _brackets, 1, c);
|
97
|
+
VALUE h = rb_hash_new();
|
98
|
+
rb_funcall(h, _bracketseq, 2, sCode, c);
|
99
|
+
rb_exc_raise(rb_funcall(k, _new, 1, h));
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
/* Forward definition */
|
104
|
+
static void nsISupports_free(struct obj *ptr);
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
/*======================================================================*
|
110
|
+
* Internal classes
|
111
|
+
* They are an intermediate to
|
112
|
+
* - manage data conversion
|
113
|
+
* - perform garbage collection
|
114
|
+
*======================================================================*/
|
115
|
+
|
116
|
+
/* Class: IID
|
117
|
+
*/
|
118
|
+
#define IID_STR_MAX 36 /* 8+1+4+1+4+1+4+1+12 */
|
119
|
+
static VALUE iid__new(iid_t *iid) {
|
120
|
+
iid_t *a_iid = ALLOC(iid_t);
|
121
|
+
*a_iid = *iid;
|
122
|
+
return Data_Wrap_Struct(cIID, 0, free, a_iid);
|
123
|
+
}
|
124
|
+
static VALUE iid__to_s(VALUE self) {
|
125
|
+
iid_t *iid = DATA_PTR(self);
|
126
|
+
char str[IID_STR_MAX+1];
|
127
|
+
snprintf(str, IID_STR_MAX+1,
|
128
|
+
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
129
|
+
iid->m0, iid->m1, iid->m2,
|
130
|
+
iid->m3[0], iid->m3[1], iid->m3[2], iid->m3[3],
|
131
|
+
iid->m3[4], iid->m3[5], iid->m3[6], iid->m3[7]);
|
132
|
+
return rb_str_new(str, IID_STR_MAX);
|
133
|
+
}
|
134
|
+
static void iid_init(VALUE under) {
|
135
|
+
cIID = rb_define_class_under(under, "IID", rb_cObject);
|
136
|
+
no_instantiation(cIID);
|
137
|
+
rb_define_method(cIID, "to_s", iid__to_s, 0);
|
138
|
+
}
|
139
|
+
|
140
|
+
|
141
|
+
/* Class: Blob
|
142
|
+
*/
|
143
|
+
struct blob_info {
|
144
|
+
uint32_t size;
|
145
|
+
uint8_t *data;
|
146
|
+
};
|
147
|
+
static void blob_free(struct blob_info *bi) {
|
148
|
+
xpcom->unalloc_mem(bi->data);
|
149
|
+
free(bi);
|
150
|
+
}
|
151
|
+
static VALUE blob_new(uint32_t size, uint8_t *data) {
|
152
|
+
struct blob_info *bi = ALLOC(struct blob_info);
|
153
|
+
bi->size = size;
|
154
|
+
bi->data = data;
|
155
|
+
return Data_Wrap_Struct(cBlob, 0, blob_free, bi);
|
156
|
+
}
|
157
|
+
static VALUE blob__new(VALUE self, VALUE data) {
|
158
|
+
data = StringValue(data);
|
159
|
+
return blob_new(RSTRING_LEN(data), (uint8_t*)RSTRING_PTR(data));
|
160
|
+
}
|
161
|
+
|
162
|
+
static VALUE blob__to_s(VALUE self) {
|
163
|
+
struct blob_info * bi = ((struct blob_info *)DATA_PTR(self));
|
164
|
+
return rb_str_new((char *)bi->data, bi->size);
|
165
|
+
}
|
166
|
+
static void blob_init(VALUE under) {
|
167
|
+
cBlob = rb_define_class_under(under, "Blob", rb_cObject);
|
168
|
+
no_instantiation(cBlob);
|
169
|
+
rb_define_singleton_method(cBlob, "new", blob__new, 1);
|
170
|
+
rb_define_method(cBlob, "to_s", blob__to_s, 0);
|
171
|
+
}
|
172
|
+
|
173
|
+
|
174
|
+
/* Class: WString
|
175
|
+
*/
|
176
|
+
static VALUE wstring_new(wstring_t wstr) {
|
177
|
+
return Data_Wrap_Struct(cWString, 0, xpcom->utf16_free, wstr);
|
178
|
+
}
|
179
|
+
static VALUE wstring__new(VALUE self, VALUE str) {
|
180
|
+
wstring_t u16;
|
181
|
+
char *u8;
|
182
|
+
str = StringValue(str);
|
183
|
+
str = rb_str_export_to_enc(str, _UTF8);
|
184
|
+
u8 = StringValueCStr(str);
|
185
|
+
xpcom->utf8_to_utf16(u8, &u16);
|
186
|
+
return wstring_new(u16);
|
187
|
+
}
|
188
|
+
static VALUE wstring__to_s(VALUE self) {
|
189
|
+
wstring_t u16 = DATA_PTR(self);
|
190
|
+
char *u8;
|
191
|
+
VALUE str;
|
192
|
+
xpcom->utf16_to_utf8(u16, &u8);
|
193
|
+
str = rb_str_new_cstr(u8);
|
194
|
+
rb_enc_associate(str, _UTF8);
|
195
|
+
xpcom->utf8_free(u8);
|
196
|
+
return str;
|
197
|
+
}
|
198
|
+
static void wstring_init(VALUE under) {
|
199
|
+
cWString = rb_define_class_under(under, "WString", rb_cObject);
|
200
|
+
no_instantiation(cWString);
|
201
|
+
rb_define_singleton_method(cWString, "new", wstring__new, 1);
|
202
|
+
rb_define_method(cWString, "to_s", wstring__to_s, 0);
|
203
|
+
}
|
204
|
+
|
205
|
+
|
206
|
+
/* Class: CArray
|
207
|
+
*/
|
208
|
+
struct carray_info {
|
209
|
+
uint32_t size;
|
210
|
+
void *data;
|
211
|
+
VALUE ary;
|
212
|
+
};
|
213
|
+
static void carray_free(struct carray_info *ci) {
|
214
|
+
free(ci->data);
|
215
|
+
free(ci);
|
216
|
+
}
|
217
|
+
static void carray_mark(struct carray_info *ci) {
|
218
|
+
rb_gc_mark(ci->ary);
|
219
|
+
}
|
220
|
+
static VALUE carray_new(uint32_t size, void *data, VALUE ary) {
|
221
|
+
struct carray_info *ci = ALLOC(struct carray_info);
|
222
|
+
ci->size = size;
|
223
|
+
ci->data = data;
|
224
|
+
ci->ary = ary;
|
225
|
+
return Data_Wrap_Struct(cCArray, carray_mark, carray_free, ci);
|
226
|
+
}
|
227
|
+
static inline uint32_t carray_get_size(VALUE val) {
|
228
|
+
return ((struct carray_info *)DATA_PTR(val))->size;
|
229
|
+
}
|
230
|
+
static inline void *carray_get_data(VALUE val) {
|
231
|
+
return ((struct carray_info *)DATA_PTR(val))->data;
|
232
|
+
}
|
233
|
+
static void carray_init(VALUE under) {
|
234
|
+
cCArray = rb_define_class_under(under, "CArray", rb_cObject);
|
235
|
+
no_instantiation(cCArray);
|
236
|
+
}
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
/*======================================================================*
|
242
|
+
* Data preparation:
|
243
|
+
* Will check type and perform basic conversion.
|
244
|
+
* All exceptions should be raised here
|
245
|
+
*======================================================================*/
|
246
|
+
|
247
|
+
static VALUE prepare_int16(VALUE val) {
|
248
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
249
|
+
rb_raise(rb_eArgError, "expecting Integer");
|
250
|
+
if (rb_funcall(val, _ge, 1, oMin_s16) == Qfalse ||
|
251
|
+
rb_funcall(val, _le, 1, oMax_s16) == Qfalse)
|
252
|
+
rb_raise(rb_eArgError, "expecting array of Integer [-2^15..2^15-1]");
|
253
|
+
return val;
|
254
|
+
}
|
255
|
+
static VALUE prepare_int32(VALUE val) {
|
256
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
257
|
+
rb_raise(rb_eArgError, "expecting Integer");
|
258
|
+
if (rb_funcall(val, _ge, 1, oMin_s32) == Qfalse ||
|
259
|
+
rb_funcall(val, _le, 1, oMax_s32) == Qfalse)
|
260
|
+
rb_raise(rb_eArgError, "expecting array of Integer [-2^32..2^31-1]");
|
261
|
+
return val;
|
262
|
+
}
|
263
|
+
static VALUE prepare_int64(VALUE val) {
|
264
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
265
|
+
rb_raise(rb_eArgError, "expecting Integer");
|
266
|
+
if (rb_funcall(val, _ge, 1, oMin_s64) == Qfalse ||
|
267
|
+
rb_funcall(val, _le, 1, oMax_s64) == Qfalse)
|
268
|
+
rb_raise(rb_eArgError, "expecting array of Integer [-2^63..2^63-1]");
|
269
|
+
return val;
|
270
|
+
}
|
271
|
+
static VALUE prepare_uint16(VALUE val) {
|
272
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
273
|
+
rb_raise(rb_eArgError, "expecting Integer");
|
274
|
+
if (rb_funcall(val, _ge, 1, oZero ) == Qfalse ||
|
275
|
+
rb_funcall(val, _le, 1, oMax_u16) == Qfalse)
|
276
|
+
rb_raise(rb_eArgError, "expecting Integer [0..2^16-1]");
|
277
|
+
return val;
|
278
|
+
}
|
279
|
+
static VALUE prepare_uint32(VALUE val) {
|
280
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
281
|
+
rb_raise(rb_eArgError, "expecting Integer");
|
282
|
+
if (rb_funcall(val, _ge, 1, oZero ) == Qfalse ||
|
283
|
+
rb_funcall(val, _le, 1, oMax_u32) == Qfalse)
|
284
|
+
rb_raise(rb_eArgError, "expecting Integer [0..2^32-1]");
|
285
|
+
return val;
|
286
|
+
}
|
287
|
+
static VALUE prepare_uint64(VALUE val) {
|
288
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
289
|
+
rb_raise(rb_eArgError, "expecting Integer");
|
290
|
+
if (rb_funcall(val, _ge, 1, oZero ) == Qfalse ||
|
291
|
+
rb_funcall(val, _le, 1, oMax_u64) == Qfalse)
|
292
|
+
rb_raise(rb_eArgError, "expecting Integer [0..2^64-1]");
|
293
|
+
return val;
|
294
|
+
}
|
295
|
+
|
296
|
+
static VALUE prepare_bool(VALUE val) {
|
297
|
+
switch(rb_type(val)) {
|
298
|
+
case T_TRUE :
|
299
|
+
return Qtrue;
|
300
|
+
|
301
|
+
case T_FALSE: case T_NIL:
|
302
|
+
return Qfalse;
|
303
|
+
|
304
|
+
case T_BIGNUM: case T_FIXNUM:
|
305
|
+
return rb_equal(val, INT2FIX(0));
|
306
|
+
|
307
|
+
case T_SYMBOL:
|
308
|
+
if (val == sYes || val == sTrue || val == sOn || val == sEnabled )
|
309
|
+
return Qtrue;
|
310
|
+
if (val == sNo || val == sFalse || val == sOff || val == sDisabled)
|
311
|
+
return Qfalse;
|
312
|
+
break;
|
313
|
+
}
|
314
|
+
rb_raise(rb_eArgError, "boolean-like value expected");
|
315
|
+
}
|
316
|
+
|
317
|
+
static VALUE prepare_ptr(VALUE val) {
|
318
|
+
rb_raise(rb_eArgError, "passing pointer is not allowed");
|
319
|
+
}
|
320
|
+
|
321
|
+
static inline VALUE prepare_blob(VALUE val) {
|
322
|
+
return blob__new(cBlob, val);
|
323
|
+
}
|
324
|
+
|
325
|
+
static inline VALUE prepare_wstring(VALUE val) {
|
326
|
+
return wstring__new(cWString, val);
|
327
|
+
}
|
328
|
+
|
329
|
+
static VALUE prepare_enum(VALUE val, VALUE klass) {
|
330
|
+
switch(rb_type(val)) {
|
331
|
+
case T_FIXNUM:
|
332
|
+
case T_BIGNUM: {
|
333
|
+
if (NIL_P(rb_funcall(klass, _symbol, 1, val)))
|
334
|
+
goto arg_error;
|
335
|
+
break;
|
336
|
+
}
|
337
|
+
case T_SYMBOL: {
|
338
|
+
VALUE v = rb_funcall(klass, _value, 1, val);
|
339
|
+
if (NIL_P(v)) goto arg_error;
|
340
|
+
val = v;
|
341
|
+
break;
|
342
|
+
}
|
343
|
+
default: arg_error:
|
344
|
+
rb_raise(rb_eArgError, "can't interpret '%s' as part of %s",
|
345
|
+
StringValueCStr(val), rb_class2name(klass));
|
346
|
+
}
|
347
|
+
return val;
|
348
|
+
}
|
349
|
+
|
350
|
+
static VALUE prepare_interface(VALUE val, VALUE klass) {
|
351
|
+
if (0 && rb_funcall(val, _is_a, 1, klass) == Qfalse) {
|
352
|
+
rb_raise(rb_eArgError, "expecting %s", rb_class2name(klass));
|
353
|
+
}
|
354
|
+
return val;
|
355
|
+
}
|
356
|
+
|
357
|
+
|
358
|
+
static VALUE prepare_array_uint16(VALUE ary) {
|
359
|
+
VALUE res = Qundef;
|
360
|
+
uint16_t *data = NULL;
|
361
|
+
long len, i;
|
362
|
+
|
363
|
+
ary = rb_check_array_type(ary);
|
364
|
+
len = RARRAY_LEN(ary);
|
365
|
+
data = ALLOC_N(uint16_t, len);
|
366
|
+
res = carray_new(len, data, Qnil);
|
367
|
+
|
368
|
+
for (i = 0 ; i < len ; i++) {
|
369
|
+
VALUE val = rb_ary_entry(ary, i);
|
370
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
371
|
+
rb_raise(rb_eArgError, "expecting array of Integer");
|
372
|
+
if (rb_funcall(val, _ge, 1, oZero ) == Qfalse ||
|
373
|
+
rb_funcall(val, _le, 1, oMax_u16) == Qfalse)
|
374
|
+
rb_raise(rb_eArgError, "expecting array of Integer [0..2^16-1]");
|
375
|
+
data[i] = NUM2UINT16(val);
|
376
|
+
}
|
377
|
+
return res;
|
378
|
+
}
|
379
|
+
|
380
|
+
static VALUE prepare_array_int16(VALUE ary) {
|
381
|
+
VALUE res = Qundef;
|
382
|
+
int16_t * data = NULL;
|
383
|
+
long len, i;
|
384
|
+
|
385
|
+
ary = rb_check_array_type(ary);
|
386
|
+
len = RARRAY_LEN(ary);
|
387
|
+
data = ALLOC_N(int16_t, len);
|
388
|
+
res = carray_new(len, data, Qnil);
|
389
|
+
|
390
|
+
for (i = 0 ; i < len ; i++) {
|
391
|
+
VALUE val = rb_ary_entry(ary, i);
|
392
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
393
|
+
rb_raise(rb_eArgError, "expecting array of Integer");
|
394
|
+
if (rb_funcall(val, _ge, 1, oMin_s16) == Qfalse ||
|
395
|
+
rb_funcall(val, _le, 1, oMax_s16) == Qfalse)
|
396
|
+
rb_raise(rb_eArgError, "expecting array of Integer [-2^15..2^15-1]");
|
397
|
+
data[i] = NUM2INT16(val);
|
398
|
+
}
|
399
|
+
return res;
|
400
|
+
}
|
401
|
+
|
402
|
+
static VALUE prepare_array_uint32(VALUE ary) {
|
403
|
+
VALUE res = Qundef;
|
404
|
+
uint32_t *data = NULL;
|
405
|
+
long len, i;
|
406
|
+
|
407
|
+
ary = rb_check_array_type(ary);
|
408
|
+
len = RARRAY_LEN(ary);
|
409
|
+
data = ALLOC_N(uint32_t, len);
|
410
|
+
res = carray_new(len, data, Qnil);
|
411
|
+
|
412
|
+
for (i = 0 ; i < len ; i++) {
|
413
|
+
VALUE val = rb_ary_entry(ary, i);
|
414
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
415
|
+
rb_raise(rb_eArgError, "expecting array of Integer");
|
416
|
+
if (rb_funcall(val, _ge, 1, oZero ) == Qfalse ||
|
417
|
+
rb_funcall(val, _le, 1, oMax_u32) == Qfalse)
|
418
|
+
rb_raise(rb_eArgError, "expecting array of Integer [0..2^32-1]");
|
419
|
+
data[i] = NUM2UINT32(val);
|
420
|
+
}
|
421
|
+
return res;
|
422
|
+
}
|
423
|
+
|
424
|
+
static VALUE prepare_array_int32(VALUE ary) {
|
425
|
+
VALUE res = Qundef;
|
426
|
+
int32_t * data = NULL;
|
427
|
+
long len, i;
|
428
|
+
|
429
|
+
ary = rb_check_array_type(ary);
|
430
|
+
len = RARRAY_LEN(ary);
|
431
|
+
data = ALLOC_N(int32_t, len);
|
432
|
+
res = carray_new(len, data, Qnil);
|
433
|
+
|
434
|
+
for (i = 0 ; i < len ; i++) {
|
435
|
+
VALUE val = rb_ary_entry(ary, i);
|
436
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
437
|
+
rb_raise(rb_eArgError, "expecting array of Integer");
|
438
|
+
if (rb_funcall(val, _ge, 1, oMin_s32) == Qfalse ||
|
439
|
+
rb_funcall(val, _le, 1, oMax_s32) == Qfalse)
|
440
|
+
rb_raise(rb_eArgError, "expecting array of Integer [-2^31..2^31-1]");
|
441
|
+
data[i] = NUM2INT32(val);
|
442
|
+
}
|
443
|
+
return res;
|
444
|
+
}
|
445
|
+
|
446
|
+
static VALUE prepare_array_uint64(VALUE ary) {
|
447
|
+
VALUE res = Qundef;
|
448
|
+
uint64_t *data = NULL;
|
449
|
+
long len, i;
|
450
|
+
|
451
|
+
ary = rb_check_array_type(ary);
|
452
|
+
len = RARRAY_LEN(ary);
|
453
|
+
data = ALLOC_N(uint64_t, len);
|
454
|
+
res = carray_new(len, data, Qnil);
|
455
|
+
|
456
|
+
for (i = 0 ; i < len ; i++) {
|
457
|
+
VALUE val = rb_ary_entry(ary, i);
|
458
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
459
|
+
rb_raise(rb_eArgError, "expecting array of Integer");
|
460
|
+
if (rb_funcall(val, _ge, 1, oZero ) == Qfalse ||
|
461
|
+
rb_funcall(val, _le, 1, oMax_u64) == Qfalse)
|
462
|
+
rb_raise(rb_eArgError, "expecting array of Integer [0..2^64-1]");
|
463
|
+
data[i] = NUM2UINT64(val);
|
464
|
+
}
|
465
|
+
return res;
|
466
|
+
}
|
467
|
+
|
468
|
+
static VALUE prepare_array_int64(VALUE ary) {
|
469
|
+
VALUE res = Qundef;
|
470
|
+
int64_t * data = NULL;
|
471
|
+
long len, i;
|
472
|
+
|
473
|
+
ary = rb_check_array_type(ary);
|
474
|
+
len = RARRAY_LEN(ary);
|
475
|
+
data = ALLOC_N(int64_t, len);
|
476
|
+
res = carray_new(len, data, Qnil);
|
477
|
+
|
478
|
+
for (i = 0 ; i < len ; i++) {
|
479
|
+
VALUE val = rb_ary_entry(ary, i);
|
480
|
+
if (rb_funcall(val, _is_a, 1, rb_cInteger) == Qfalse)
|
481
|
+
rb_raise(rb_eArgError, "expecting array of Integer");
|
482
|
+
if (rb_funcall(val, _ge, 1, oMin_s64) == Qfalse ||
|
483
|
+
rb_funcall(val, _le, 1, oMax_s64) == Qfalse)
|
484
|
+
rb_raise(rb_eArgError, "expecting array of Integer [-2^63..2^63-1]");
|
485
|
+
data[i] = NUM2INT64(val);
|
486
|
+
}
|
487
|
+
return res;
|
488
|
+
}
|
489
|
+
|
490
|
+
static VALUE prepare_array_bool(VALUE ary) {
|
491
|
+
VALUE res = Qundef;
|
492
|
+
bool_t *data = NULL;
|
493
|
+
long len, i;
|
494
|
+
|
495
|
+
ary = rb_check_array_type(ary);
|
496
|
+
len = RARRAY_LEN(ary);
|
497
|
+
data = ALLOC_N(bool_t, len);
|
498
|
+
res = carray_new(len, data, Qnil);
|
499
|
+
|
500
|
+
for (i = 0 ; i < len ; i++) {
|
501
|
+
VALUE val = prepare_bool(rb_ary_entry(ary, i));
|
502
|
+
data[i] = val == Qtrue ? ~0 : 0;
|
503
|
+
}
|
504
|
+
return res;
|
505
|
+
}
|
506
|
+
|
507
|
+
static VALUE prepare_array_wstring(VALUE ary) {
|
508
|
+
VALUE res = Qundef;
|
509
|
+
wstring_t *data = NULL;
|
510
|
+
long len, i;
|
511
|
+
|
512
|
+
ary = rb_ary_dup(rb_check_array_type(ary));
|
513
|
+
len = RARRAY_LEN(ary);
|
514
|
+
data = ALLOC_N(wstring_t, len);
|
515
|
+
res = carray_new(len, data, ary);
|
516
|
+
|
517
|
+
for (i = 0 ; i < len ; i++) {
|
518
|
+
VALUE val = prepare_wstring(rb_ary_entry(ary, i));
|
519
|
+
rb_ary_store(ary, i, val);
|
520
|
+
data[i] = (wstring_t)DATA_PTR(val);
|
521
|
+
}
|
522
|
+
OBJ_FREEZE(ary);
|
523
|
+
return res;
|
524
|
+
}
|
525
|
+
|
526
|
+
static VALUE prepare_array_enum(VALUE ary, VALUE klass) {
|
527
|
+
VALUE res = Qundef;
|
528
|
+
uint32_t *data = NULL;
|
529
|
+
long len, i;
|
530
|
+
|
531
|
+
ary = rb_check_array_type(ary);
|
532
|
+
len = RARRAY_LEN(ary);
|
533
|
+
data = ALLOC_N(uint32_t, len);
|
534
|
+
res = carray_new(len, data, Qnil);
|
535
|
+
|
536
|
+
for (i = 0 ; i < len ; i++) {
|
537
|
+
VALUE val = prepare_enum(rb_ary_entry(ary, i), klass);
|
538
|
+
data[i] = NUM2UINT32(val);
|
539
|
+
}
|
540
|
+
return res;
|
541
|
+
}
|
542
|
+
|
543
|
+
static VALUE prepare_array_interface(VALUE ary, VALUE klass) {
|
544
|
+
VALUE res = Qundef;
|
545
|
+
void * *data = NULL;
|
546
|
+
long len, i;
|
547
|
+
|
548
|
+
ary = rb_ary_dup(rb_check_array_type(ary));
|
549
|
+
len = RARRAY_LEN(ary);
|
550
|
+
data = (void*)ALLOC_N(uint32_t, len);
|
551
|
+
res = carray_new(len, data, ary);
|
552
|
+
|
553
|
+
for (i = 0 ; i < len ; i++) {
|
554
|
+
VALUE val = rb_ary_entry(ary, i);
|
555
|
+
if (rb_funcall(val, _is_a, 1, klass) == Qfalse)
|
556
|
+
rb_raise(rb_eArgError, "expecting array of %s",
|
557
|
+
rb_class2name(klass));
|
558
|
+
data[i] = DATA_PTR(val);
|
559
|
+
}
|
560
|
+
OBJ_FREEZE(ary);
|
561
|
+
return res;
|
562
|
+
}
|
563
|
+
|
564
|
+
|
565
|
+
|
566
|
+
|
567
|
+
/*======================================================================*
|
568
|
+
* Extract C value from Ruby object (object has been previously prepared)
|
569
|
+
* - it's not necessary to perform checking
|
570
|
+
* - C value can be directly used
|
571
|
+
*======================================================================*/
|
572
|
+
|
573
|
+
#define extract_int16(val, data) *(data) = NUM2INT16(val)
|
574
|
+
#define extract_int32(val, data) *(data) = NUM2INT32(val)
|
575
|
+
#define extract_int64(val, data) *(data) = NUM2INT64(val)
|
576
|
+
#define extract_uint16(val, data) *(data) = NUM2UINT16(val)
|
577
|
+
#define extract_uint32(val, data) *(data) = NUM2UINT32(val)
|
578
|
+
#define extract_uint64(val, data) *(data) = NUM2UINT64(val)
|
579
|
+
#define extract_bool(val, data) *(data) = (val) == Qtrue ? ~0 : 0
|
580
|
+
#define extract_ptr(val, data) *(data) = NUM2PTR(val)
|
581
|
+
#define extract_wstring(val, data) *(data) = DATA_PTR(val)
|
582
|
+
#define extract_enum(val, data, klass) *(data) = NUM2UINT32(val)
|
583
|
+
#define extract_interface(val, data, klass) *(data) = DATA_PTR(val)
|
584
|
+
|
585
|
+
static inline void extract_blob(VALUE val, uint32_t *size, void **data) {
|
586
|
+
struct blob_info * bi = ((struct blob_info *)DATA_PTR(val));
|
587
|
+
*size = bi->size;
|
588
|
+
*data = bi->data;
|
589
|
+
}
|
590
|
+
|
591
|
+
static inline void extract_carray(VALUE val, uint32_t *size, void **data) {
|
592
|
+
struct carray_info * ci = ((struct carray_info *)DATA_PTR(val));
|
593
|
+
*size = ci->size;
|
594
|
+
*data = ci->data;
|
595
|
+
}
|
596
|
+
|
597
|
+
|
598
|
+
|
599
|
+
|
600
|
+
/*======================================================================*
|
601
|
+
* Convert information from response
|
602
|
+
* - don't raise exception as this could lead to memory leak
|
603
|
+
*
|
604
|
+
*======================================================================*/
|
605
|
+
|
606
|
+
#define convert_int16(v) LL2NUM(v)
|
607
|
+
#define convert_int32(v) LL2NUM(v)
|
608
|
+
#define convert_int64(v) LL2NUM(v)
|
609
|
+
#define convert_uint16(v) ULL2NUM(v)
|
610
|
+
#define convert_uint32(v) ULL2NUM(v)
|
611
|
+
#define convert_uint64(v) ULL2NUM(v)
|
612
|
+
#define convert_ptr(v) PTR2NUM(v)
|
613
|
+
#define convert_bool(v) ((v) ? Qtrue : Qfalse)
|
614
|
+
#define convert_blob(s,d) ((d) ? blob_new(s,d) : Qnil)
|
615
|
+
#define convert_wstring(v) ((v) ? wstring_new(v) : Qnil)
|
616
|
+
|
617
|
+
static inline VALUE convert_enum(uint32_t v, VALUE klass) {
|
618
|
+
VALUE val = ULL2NUM(v);
|
619
|
+
VALUE sym = rb_funcall(klass, _symbol, 1, val);
|
620
|
+
if (NIL_P(sym)) {
|
621
|
+
rb_warn("unable to convert value %d to enumeration symbol", v);
|
622
|
+
return val;
|
623
|
+
}
|
624
|
+
return sym;
|
625
|
+
}
|
626
|
+
|
627
|
+
static inline VALUE convert_interface(void *iptr, VALUE klass) {
|
628
|
+
return iptr ? Data_Wrap_Struct(klass, 0, nsISupports_free, iptr)
|
629
|
+
: Qnil;
|
630
|
+
}
|
631
|
+
|
632
|
+
|
633
|
+
static inline VALUE convert_array_int32(uint32_t size, int32_t *array) {
|
634
|
+
if (array) {
|
635
|
+
VALUE res = rb_ary_new();
|
636
|
+
uint32_t i;
|
637
|
+
for (i = 0 ; i < size ; i++)
|
638
|
+
rb_ary_store(res, i, convert_int32(array[i]));
|
639
|
+
xpcom->unalloc_mem(array);
|
640
|
+
return res;
|
641
|
+
} else {
|
642
|
+
return Qnil;
|
643
|
+
}
|
644
|
+
}
|
645
|
+
static inline VALUE convert_array_int64(uint32_t size, int64_t *array) {
|
646
|
+
if (array) {
|
647
|
+
VALUE res = rb_ary_new2(size);
|
648
|
+
uint32_t i;
|
649
|
+
for (i = 0 ; i < size ; i++)
|
650
|
+
rb_ary_store(res, i, convert_int64(array[i]));
|
651
|
+
xpcom->unalloc_mem(array);
|
652
|
+
return res;
|
653
|
+
} else {
|
654
|
+
return Qnil;
|
655
|
+
}
|
656
|
+
}
|
657
|
+
static inline VALUE convert_array_uint32(uint32_t size, uint32_t *array) {
|
658
|
+
if (array) {
|
659
|
+
VALUE res = rb_ary_new2(size);
|
660
|
+
uint32_t i;
|
661
|
+
for (i = 0 ; i < size ; i++)
|
662
|
+
rb_ary_store(res, i, convert_uint32(array[i]));
|
663
|
+
xpcom->unalloc_mem(array);
|
664
|
+
return res;
|
665
|
+
} else {
|
666
|
+
return Qnil;
|
667
|
+
}
|
668
|
+
}
|
669
|
+
static inline VALUE convert_array_enum(uint32_t size, uint32_t *array, VALUE klass) {
|
670
|
+
if (array) {
|
671
|
+
VALUE res = rb_ary_new2(size);
|
672
|
+
uint32_t i;
|
673
|
+
for (i = 0 ; i < size ; i++)
|
674
|
+
rb_ary_store(res, i, convert_enum(array[i], klass));
|
675
|
+
xpcom->unalloc_mem(array);
|
676
|
+
return res;
|
677
|
+
} else {
|
678
|
+
return Qnil;
|
679
|
+
}
|
680
|
+
}
|
681
|
+
static inline VALUE convert_array_interface(uint32_t size, void **array, VALUE klass) {
|
682
|
+
if (array) {
|
683
|
+
VALUE res = rb_ary_new2(size);
|
684
|
+
uint32_t i;
|
685
|
+
for (i = 0 ; i < size ; i++)
|
686
|
+
rb_ary_push(res, convert_interface(array[i], klass));
|
687
|
+
xpcom->unalloc_mem(array);
|
688
|
+
return res;
|
689
|
+
} else {
|
690
|
+
return Qnil;
|
691
|
+
}
|
692
|
+
}
|
693
|
+
|
694
|
+
static inline VALUE convert_array_wstring(uint32_t size, void **array) {
|
695
|
+
if (array) {
|
696
|
+
VALUE res = rb_ary_new2(size);
|
697
|
+
uint32_t i;
|
698
|
+
for (i = 0 ; i < size ; i++)
|
699
|
+
rb_ary_push(res, convert_wstring(array[i]));
|
700
|
+
xpcom->unalloc_mem(array);
|
701
|
+
return res;
|
702
|
+
} else {
|
703
|
+
return Qnil;
|
704
|
+
}
|
705
|
+
}
|
706
|
+
|
707
|
+
|
708
|
+
|
709
|
+
/*======================================================================*
|
710
|
+
*
|
711
|
+
*
|
712
|
+
*
|
713
|
+
*======================================================================*/
|
714
|
+
|
715
|
+
#include "generated.inc"
|
716
|
+
|
717
|
+
|
718
|
+
static void nsISupports_free(struct obj *ptr) {
|
719
|
+
((struct NSISupports *)ptr->vtbl)->Release(ptr);
|
720
|
+
}
|
721
|
+
|
722
|
+
static VALUE NSISupports__dup(VALUE self) {
|
723
|
+
VALUE klass = rb_class_of(self);
|
724
|
+
struct obj *obj = DATA_PTR(self);
|
725
|
+
struct NSISupports *vtbl = obj->vtbl;
|
726
|
+
vtbl->AddRef(obj);
|
727
|
+
return Data_Wrap_Struct(klass, 0, nsISupports_free, obj);
|
728
|
+
}
|
729
|
+
|
730
|
+
static VALUE NSISupports__clone(VALUE self) {
|
731
|
+
VALUE res = NSISupports__dup(self);
|
732
|
+
if (OBJ_TAINTED (self)) OBJ_TAINT(res);
|
733
|
+
if (OBJ_FROZEN (self)) OBJ_FREEZE(res);
|
734
|
+
if (OBJ_UNTRUSTED(self)) OBJ_UNTRUST(res);
|
735
|
+
return res;
|
736
|
+
}
|
737
|
+
|
738
|
+
static VALUE NSISupports__cast(VALUE self, VALUE model_name) {
|
739
|
+
VALUE res = Qundef;
|
740
|
+
VALUE model = rb_funcall(mModel,_const_get, 2, model_name, Qfalse);
|
741
|
+
VALUE iid = rb_funcall(model, _const_get, 2, sIID, Qfalse);
|
742
|
+
struct obj *obj = DATA_PTR(self);
|
743
|
+
struct NSISupports *vtbl = obj->vtbl;
|
744
|
+
void *nobj = NULL;
|
745
|
+
|
746
|
+
if (rb_funcall(model, _le, 1, cAbstractInterface) == Qfalse ||
|
747
|
+
rb_funcall(iid, _is_a, 1, cIID ) == Qfalse) {
|
748
|
+
rb_raise(rb_eArgError, "provided object is not a COM Model");
|
749
|
+
}
|
750
|
+
|
751
|
+
NS_CHECK(vtbl->QueryInterface(obj, DATA_PTR(iid), &nobj));
|
752
|
+
return convert_interface(nobj, model);
|
753
|
+
}
|
754
|
+
|
755
|
+
|
756
|
+
|
757
|
+
|
758
|
+
|
759
|
+
/*======================================================================*
|
760
|
+
* Initialisation of ruby extension
|
761
|
+
*======================================================================*/
|
762
|
+
|
763
|
+
/* ruby calls this to load the extension */
|
764
|
+
void RUBY_VBOX_INIT(void) {
|
765
|
+
VALUE oOne = INT2FIX(1);
|
766
|
+
VALUE oTwo = INT2FIX(2);
|
767
|
+
VALUE p15, p16, p31, p32, p63, p64;
|
768
|
+
|
769
|
+
xpcom = virtualbox_com_xpcom;
|
770
|
+
|
771
|
+
/* Basic ruby helper objects */
|
772
|
+
_IID = rb_intern("IID");
|
773
|
+
_map = rb_intern("map");
|
774
|
+
_brackets = rb_intern("[]");
|
775
|
+
_bracketseq = rb_intern("[]=");
|
776
|
+
_pow = rb_intern("**");
|
777
|
+
_minus = rb_intern("-" );
|
778
|
+
_neg = rb_intern("-@");
|
779
|
+
_ge = rb_intern(">=");
|
780
|
+
_le = rb_intern("<=");
|
781
|
+
_is_a = rb_intern("is_a?");
|
782
|
+
_dup = rb_intern("dup");
|
783
|
+
_symbol = rb_intern("symbol");
|
784
|
+
_value = rb_intern("value");
|
785
|
+
_const_get = rb_intern("const_get");
|
786
|
+
_new = rb_intern("new");
|
787
|
+
|
788
|
+
p15 = rb_funcall(oTwo, _pow, 1, INT2FIX(15));
|
789
|
+
p16 = rb_funcall(oTwo, _pow, 1, INT2FIX(16));
|
790
|
+
p31 = rb_funcall(oTwo, _pow, 1, INT2FIX(31));
|
791
|
+
p32 = rb_funcall(oTwo, _pow, 1, INT2FIX(32));
|
792
|
+
p63 = rb_funcall(oTwo, _pow, 1, INT2FIX(63));
|
793
|
+
p64 = rb_funcall(oTwo, _pow, 1, INT2FIX(64));
|
794
|
+
oZero = INT2FIX(0);
|
795
|
+
oMax_u16 = rb_funcall(p16, _minus, 1, oOne);
|
796
|
+
oMax_u32 = rb_funcall(p32, _minus, 1, oOne);
|
797
|
+
oMax_u64 = rb_funcall(p64, _minus, 1, oOne);
|
798
|
+
oMax_s16 = rb_funcall(p15, _minus, 1, oOne);
|
799
|
+
oMax_s32 = rb_funcall(p31, _minus, 1, oOne);
|
800
|
+
oMax_s64 = rb_funcall(p63, _minus, 1, oOne);
|
801
|
+
oMin_s16 = rb_funcall(p15, _neg, 0);
|
802
|
+
oMin_s32 = rb_funcall(p31, _neg, 0);
|
803
|
+
oMin_s64 = rb_funcall(p63, _neg, 0);
|
804
|
+
|
805
|
+
sYes = SYM("yes" );
|
806
|
+
sNo = SYM("no" );
|
807
|
+
sTrue = SYM("true" );
|
808
|
+
sFalse = SYM("false" );
|
809
|
+
sOn = SYM("on" );
|
810
|
+
sOff = SYM("off" );
|
811
|
+
sEnabled = SYM("enabled" );
|
812
|
+
sDisabled = SYM("disabled");
|
813
|
+
sIID = SYM("IID" );
|
814
|
+
sCode = SYM("code" );
|
815
|
+
sFunction = SYM("function");
|
816
|
+
|
817
|
+
_UTF8 = rb_enc_find("UTF-8");
|
818
|
+
if (_UTF8 == NULL)
|
819
|
+
rb_fatal("can't find UTF-8 encoding");
|
820
|
+
|
821
|
+
/* Define modules */
|
822
|
+
mVirtualBox = rb_define_module("VirtualBox");
|
823
|
+
mCOM = rb_define_module_under(mVirtualBox, "COM");
|
824
|
+
mModel = rb_define_module_under(mCOM, "Model");
|
825
|
+
|
826
|
+
/* Define abstract enumerations / interfaces */
|
827
|
+
cAbstractModel
|
828
|
+
= rb_define_class_under(mCOM, "AbstractModel", rb_cObject);
|
829
|
+
cAbstractEnum
|
830
|
+
= rb_define_class_under(mCOM, "AbstractEnum", cAbstractModel);
|
831
|
+
cAbstractInterface
|
832
|
+
= rb_define_class_under(mCOM, "AbstractInterface", cAbstractModel);
|
833
|
+
|
834
|
+
/* Retrieve exception map */
|
835
|
+
oExceptionMap
|
836
|
+
= rb_funcall(mCOM, _const_get, 2, SYM("EXCEPTION_MAP"), Qfalse);
|
837
|
+
|
838
|
+
/* Init internal classes */
|
839
|
+
iid_init(mCOM);
|
840
|
+
blob_init(mCOM);
|
841
|
+
wstring_init(mCOM);
|
842
|
+
carray_init(mCOM);
|
843
|
+
|
844
|
+
/* Init of generated xpcom classes */
|
845
|
+
comclass_init(mModel);
|
846
|
+
|
847
|
+
rb_define_method(cNSISupports, "cast", NSISupports__cast, 1);
|
848
|
+
rb_define_method(cNSISupports, "dup", NSISupports__dup, 0);
|
849
|
+
rb_define_method(cNSISupports, "clone", NSISupports__clone, 0);
|
850
|
+
}
|
851
|
+
|
852
|
+
VALUE virtualbox_com_virtualbox(void *ptr) {
|
853
|
+
return convert_interface(ptr, cVirtualBox);
|
854
|
+
}
|
855
|
+
|
856
|
+
VALUE virtualbox_com_session(void *ptr) {
|
857
|
+
return convert_interface(ptr, cSession);
|
858
|
+
}
|