Snippet Preview
Snippet HTML Code
1
2
package org.jruby.ext.ffi;
3
4
import java.nio.ByteOrder;
5
import org.jruby.Ruby;
6
import org.jruby.RubyClass;
7
import org.jruby.runtime.Block;
8
import org.jruby.runtime.ThreadContext;
9
import org.jruby.runtime.builtin.IRubyObject;
13
14
abstract class MemoryOp {
15
public static final MemoryOp BOOL = new BooleanOp();
16
public static final MemoryOp INT8 = new Signed8();
17
public static final MemoryOp UINT8 = new Unsigned8();
18
public static final MemoryOp INT16 = new Signed16();
19
public static final MemoryOp UINT16 = new Unsigned16();
20
public static final MemoryOp INT32 = new Signed32();
21
public static final MemoryOp UINT32 = new Unsigned32();
22
public static final MemoryOp INT64 = new Signed64();
23
public static final MemoryOp UINT64 = new Unsigned64();
24
public static final MemoryOp FLOAT32 = new Float32();
25
public static final MemoryOp FLOAT64 = new Float64();
26
public static final MemoryOp INT16SWAP = new Signed16Swapped();
27
public static final MemoryOp UINT16SWAP = new Unsigned16Swapped();
28
public static final MemoryOp INT32SWAP = new Signed32Swapped();
29
public static final MemoryOp UINT32SWAP = new Unsigned32Swapped();
30
public static final MemoryOp INT64SWAP = new Signed64Swapped();
31
public static final MemoryOp UINT64SWAP = new Unsigned64Swapped();
32
public static final MemoryOp POINTER = new PointerOp();
33
34
public static MemoryOp getMemoryOp(NativeType type) {
35
return getMemoryOp(type, ByteOrder.nativeOrder());
36
}
37
38
public static MemoryOp getMemoryOp(NativeType type, ByteOrder order) {
39
switch (type) {
40
case BOOL:
41
return BOOL;
42
case CHAR:
43
return INT8;
44
case UCHAR:
45
return UINT8;
46
case SHORT:
47
return order.equals(ByteOrder.nativeOrder()) ? INT16 : INT16SWAP;
48
case USHORT:
49
return order.equals(ByteOrder.nativeOrder()) ? UINT16 : UINT16SWAP;
50
case INT:
51
return order.equals(ByteOrder.nativeOrder()) ? INT32 : INT32SWAP;
52
case UINT:
53
return order.equals(ByteOrder.nativeOrder()) ? UINT32 : UINT32SWAP;
54
case LONG_LONG:
55
return order.equals(ByteOrder.nativeOrder()) ? INT64 : INT64SWAP;
56
case ULONG_LONG:
57
return order.equals(ByteOrder.nativeOrder()) ? UINT64 : UINT64SWAP;
58
case FLOAT:
59
return FLOAT32;
60
case DOUBLE:
61
return FLOAT64;
62
case LONG:
63
return Platform.getPlatform().longSize() == 32
64
? getMemoryOp(NativeType.INT, order) : getMemoryOp(NativeType.LONG_LONG, order);
65
case ULONG:
66
67
? getMemoryOp(NativeType.UINT, order) : getMemoryOp(NativeType.ULONG_LONG, order);
68
case POINTER:
69
return POINTER;
70
default:
71
return null;
72
73
74
75
public static MemoryOp getMemoryOp(Type type) {
76
77
78
79
public static MemoryOp getMemoryOp(Type type, ByteOrder order) {
80
if (type instanceof Type.Builtin) {
81
return getMemoryOp(type.getNativeType(), order);
82
83
} else if (type instanceof StructByValue) {
84
StructByValue sbv = (StructByValue) type;
85
return new StructOp(sbv.getStructClass());
86
87
} else if (type instanceof MappedType) {
88
return new Mapped(getMemoryOp(((MappedType) type).getRealType(), order), (MappedType) type);
89
90
91
92
93
94
abstract IRubyObject get(ThreadContext context, MemoryIO io, long offset);
95
abstract void put(ThreadContext context, MemoryIO io, long offset, IRubyObject value);
96
97
IRubyObject get(ThreadContext context, AbstractMemory ptr, long offset) {
98
return get(context, ptr.getMemoryIO(), offset);
99
100
101
void put(ThreadContext context, AbstractMemory ptr, long offset, IRubyObject value) {
102
put(context, ptr.getMemoryIO(), offset, value);
103
104
105
static abstract class PrimitiveOp extends MemoryOp {
106
abstract IRubyObject get(Ruby runtime, MemoryIO io, long offset);
107
abstract void put(Ruby runtime, MemoryIO io, long offset, IRubyObject value);
108
109
IRubyObject get(ThreadContext context, MemoryIO io, long offset) {
110
return get(context.runtime, io, offset);
111
112
void put(ThreadContext context, MemoryIO io, long offset, IRubyObject value) {
113
put(context.runtime, io, offset, value);
114
115
116
static final class BooleanOp extends PrimitiveOp {
117
public final void put(Ruby runtime, MemoryIO io, long offset, IRubyObject value) {
118
io.putByte(offset, (byte) (value.isTrue() ? 1 : 0));
119
120
121
public final IRubyObject get(Ruby runtime, MemoryIO io, long offset) {
122
return runtime.newBoolean(io.getByte(offset) != 0);
123
124
125
126
static final class Signed8 extends PrimitiveOp {
127
128
io.putByte(offset, Util.int8Value(value));
129
130
131
132
return Util.newSigned8(runtime, io.getByte(offset));
133
134
135
136
static final class Unsigned8 extends PrimitiveOp {
137
138
io.putByte(offset, (byte) Util.uint8Value(value));
139
140
141
142
return Util.newUnsigned8(runtime, io.getByte(offset));
143
144
145
146
static final class Signed16 extends PrimitiveOp {
147
148
io.putShort(offset, Util.int16Value(value));
149
150
151
152
return Util.newSigned16(runtime, io.getShort(offset));
153
154
155
156
static final class Signed16Swapped extends PrimitiveOp {
157
158
io.putShort(offset, Short.reverseBytes(Util.int16Value(value)));
159
160
161
162
return Util.newSigned16(runtime, Short.reverseBytes(io.getShort(offset)));
163
164
165
166
static final class Unsigned16 extends PrimitiveOp {
167
168
io.putShort(offset, (short) Util.uint16Value(value));
169
170
171
172
return Util.newUnsigned16(runtime, io.getShort(offset));
173
174
175
176
static final class Unsigned16Swapped extends PrimitiveOp {
177
178
io.putShort(offset, Short.reverseBytes((short) Util.uint16Value(value)));
179
180
181
182
return Util.newUnsigned16(runtime, Short.reverseBytes(io.getShort(offset)));
183
184
185
186
static final class Signed32 extends PrimitiveOp {
187
188
io.putInt(offset, Util.int32Value(value));
189
190
191
192
return Util.newSigned32(runtime, io.getInt(offset));
193
194
195
196
static final class Signed32Swapped extends PrimitiveOp {
197
198
io.putInt(offset, Integer.reverseBytes(Util.int32Value(value)));
199
200
201
202
return Util.newSigned32(runtime, Integer.reverseBytes(io.getInt(offset)));
203
204
205
206
static final class Unsigned32 extends PrimitiveOp {
207
208
io.putInt(offset, (int) Util.uint32Value(value));
209
210
211
212
return Util.newUnsigned32(runtime, io.getInt(offset));
213
214
215
216
static final class Unsigned32Swapped extends PrimitiveOp {
217
218
io.putInt(offset, Integer.reverseBytes((int) Util.uint32Value(value)));
219
220
221
222
return Util.newUnsigned32(runtime, Integer.reverseBytes(io.getInt(offset)));
223
224
225
226
static final class Signed64 extends PrimitiveOp {
227
228
io.putLong(offset, Util.int64Value(value));
229
230
231
232
return Util.newSigned64(runtime, io.getLong(offset));
233
234
235
236
static final class Signed64Swapped extends PrimitiveOp {
237
238
io.putLong(offset, Long.reverseBytes(Util.int64Value(value)));
239
240
241
242
return Util.newSigned64(runtime, Long.reverseBytes(io.getLong(offset)));
243
244
245
246
static final class Unsigned64 extends PrimitiveOp {
247
248
io.putLong(offset, Util.uint64Value(value));
249
250
251
252
return Util.newUnsigned64(runtime, io.getLong(offset));
253
254
255
256
static final class Unsigned64Swapped extends PrimitiveOp {
257
258
io.putLong(offset, Long.reverseBytes(Util.uint64Value(value)));
259
260
261
262
return Util.newUnsigned64(runtime, Long.reverseBytes(io.getLong(offset)));
263
264
265
266
static final class Float32 extends PrimitiveOp {
267
268
io.putFloat(offset, Util.floatValue(value));
269
270
271
272
return runtime.newFloat(io.getFloat(offset));
273
274
275
276
static final class Float64 extends PrimitiveOp {
277
278
io.putDouble(offset, Util.doubleValue(value));
279
280
281
282
return runtime.newFloat(io.getDouble(offset));
283
284
285
286
static final class PointerOp extends PrimitiveOp {
287
288
io.putMemoryIO(offset, ((AbstractMemory) value).getMemoryIO());
289
290
291
292
return new Pointer(runtime, io.getMemoryIO(offset));
293
294
295
296
297
static final class StructOp extends MemoryOp {
298
private final RubyClass structClass;
299
300
public StructOp(RubyClass structClass) {
301
this.structClass = structClass;
302
303
304
@Override
305
306
throw new UnsupportedOperationException("Not supported yet.");
307
308
309
310
311
312
313
314
315
316
return structClass.newInstance(context,
317
new IRubyObject[] { ptr.slice(context.runtime, offset) },
318
Block.NULL_BLOCK);
319
320
321
322
323
if (!(value instanceof Struct)) {
324
throw context.runtime.newTypeError("expected a struct");
325
326
Struct s = (Struct) value;
327
byte[] tmp = new byte[Struct.getStructSize(context.runtime, s)];
328
s.getMemoryIO().get(0, tmp, 0, tmp.length);
329
ptr.getMemoryIO().put(offset, tmp, 0, tmp.length);
330
331
332
333
static final class Mapped extends MemoryOp {
334
private final MemoryOp nativeOp;
335
private final MappedType mappedType;
336
337
public Mapped(MemoryOp nativeOp, MappedType mappedType) {
338
this.nativeOp = nativeOp;
339
this.mappedType = mappedType;
340
341
342
343
344
return mappedType.fromNative(context, nativeOp.get(context, ptr, offset));
345
346
347
348
349
nativeOp.put(context, ptr, offset, mappedType.toNative(context, value));
350
351
352
353
354
return mappedType.fromNative(context, nativeOp.get(context, io, offset));
355
356
357
358
359
nativeOp.put(context, io, offset, mappedType.toNative(context, value));
360
361
362