~ubuntu-branches/ubuntu/quantal/hawtjni/quantal

« back to all changes in this revision

Viewing changes to hawtjni-generator/src/main/java/org/fusesource/hawtjni/generator/StructsGenerator.java

  • Committer: Bazaar Package Importer
  • Author(s): Miguel Landaeta
  • Date: 2010-08-05 19:40:25 UTC
  • Revision ID: james.westby@ubuntu.com-20100805194025-3004hn889accwu2i
Tags: upstream-1.0~+git0c502e20c4
ImportĀ upstreamĀ versionĀ 1.0~+git0c502e20c4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2009 Progress Software, Inc.
 
3
 * Copyright (c) 2004, 2007 IBM Corporation and others.
 
4
 *
 
5
 * All rights reserved. This program and the accompanying materials
 
6
 * are made available under the terms of the Eclipse Public License v1.0
 
7
 * which accompanies this distribution, and is available at
 
8
 * http://www.eclipse.org/legal/epl-v10.html
 
9
 *
 
10
 *******************************************************************************/
 
11
package org.fusesource.hawtjni.generator;
 
12
 
 
13
import java.lang.reflect.Modifier;
 
14
import java.util.ArrayList;
 
15
import java.util.List;
 
16
 
 
17
import org.fusesource.hawtjni.generator.model.JNIClass;
 
18
import org.fusesource.hawtjni.generator.model.JNIField;
 
19
import org.fusesource.hawtjni.generator.model.JNIType;
 
20
import org.fusesource.hawtjni.runtime.ClassFlag;
 
21
 
 
22
/**
 
23
 * 
 
24
 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
 
25
 */
 
26
public class StructsGenerator extends JNIGenerator {
 
27
 
 
28
    boolean header;
 
29
 
 
30
    static final boolean GLOBAL_REF = false;
 
31
 
 
32
    public StructsGenerator(boolean header) {
 
33
        this.header = header;
 
34
    }
 
35
 
 
36
    public void generateCopyright() {
 
37
        outputln(fixDelimiter(getCopyright()));
 
38
    }
 
39
 
 
40
    public void generateIncludes() {
 
41
        if (header) {
 
42
            outputln("#include \""+getOutputName()+".h\"");
 
43
        } else {
 
44
            outputln("#include \""+getOutputName()+".h\"");
 
45
            outputln("#include \"hawtjni.h\"");
 
46
            outputln("#include \""+getOutputName()+"_structs.h\"");
 
47
        }
 
48
        outputln();
 
49
    }
 
50
 
 
51
    public void generate(JNIClass clazz) {
 
52
        ArrayList<JNIField> fields = getStructFields(clazz);
 
53
        if (fields.isEmpty())
 
54
            return;
 
55
        if (header) {
 
56
            generateHeaderFile(clazz);
 
57
        } else {
 
58
            generateSourceFile(clazz);
 
59
        }
 
60
    }
 
61
 
 
62
    private ArrayList<JNIField> getStructFields(JNIClass clazz) {
 
63
        ArrayList<JNIField> rc = new ArrayList<JNIField>();
 
64
        List<JNIField> fields = clazz.getDeclaredFields();
 
65
        for (JNIField field : fields) {
 
66
            int mods = field.getModifiers();
 
67
            if ( (mods & Modifier.STATIC) == 0 && (mods & Modifier.TRANSIENT) == 0) {
 
68
                rc.add(field);
 
69
            }
 
70
        }
 
71
        return rc;
 
72
    }
 
73
 
 
74
    void generateHeaderFile(JNIClass clazz) {
 
75
        generateSourceStart(clazz);
 
76
        generatePrototypes(clazz);
 
77
        generateBlankMacros(clazz);
 
78
        generateSourceEnd(clazz);
 
79
        outputln();
 
80
    }
 
81
 
 
82
    void generateSourceFile(JNIClass clazz) {
 
83
        generateSourceStart(clazz);
 
84
        generateFIDsStructure(clazz);
 
85
        outputln();
 
86
        generateGlobalVar(clazz);
 
87
        outputln();
 
88
        generateFunctions(clazz);
 
89
        generateSourceEnd(clazz);
 
90
        outputln();
 
91
    }
 
92
 
 
93
    void generateSourceStart(JNIClass clazz) {
 
94
        String conditional = clazz.getConditional();
 
95
        if (conditional!=null) {
 
96
            outputln("#if "+conditional);
 
97
        }
 
98
    }
 
99
 
 
100
    void generateSourceEnd(JNIClass clazz) {
 
101
        if (clazz.getConditional()!=null) {
 
102
            outputln("#endif");
 
103
        }
 
104
    }
 
105
 
 
106
    void generateGlobalVar(JNIClass clazz) {
 
107
        String clazzName = clazz.getSimpleName();
 
108
        output(clazzName);
 
109
        output("_FID_CACHE ");
 
110
        output(clazzName);
 
111
        outputln("Fc;");
 
112
    }
 
113
 
 
114
    void generateBlankMacros(JNIClass clazz) {
 
115
        
 
116
        if (clazz.getConditional()==null) {
 
117
            return;
 
118
        }
 
119
        
 
120
        String clazzName = clazz.getSimpleName();
 
121
        outputln("#else");
 
122
        output("#define cache");
 
123
        output(clazzName);
 
124
        outputln("Fields(a,b)");
 
125
        output("#define get");
 
126
        output(clazzName);
 
127
        outputln("Fields(a,b,c) NULL");
 
128
        output("#define set");
 
129
        output(clazzName);
 
130
        outputln("Fields(a,b,c)");
 
131
    }
 
132
 
 
133
    void generatePrototypes(JNIClass clazz) {
 
134
        String clazzName = clazz.getSimpleName();
 
135
        output("void cache");
 
136
        output(clazzName);
 
137
        outputln("Fields(JNIEnv *env, jobject lpObject);");
 
138
        if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
 
139
            output("struct ");
 
140
        }
 
141
        output(clazzName);
 
142
        output(" *get");
 
143
        output(clazzName);
 
144
        output("Fields(JNIEnv *env, jobject lpObject, ");
 
145
        if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
 
146
            output("struct ");
 
147
        }
 
148
        output(clazzName);
 
149
        outputln(" *lpStruct);");
 
150
        output("void set");
 
151
        output(clazzName);
 
152
        output("Fields(JNIEnv *env, jobject lpObject, ");
 
153
        if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
 
154
            output("struct ");
 
155
        }
 
156
        output(clazzName);
 
157
        outputln(" *lpStruct);");
 
158
    }
 
159
 
 
160
    void generateFIDsStructure(JNIClass clazz) {
 
161
        String clazzName = clazz.getSimpleName();
 
162
        output("typedef struct ");
 
163
        output(clazzName);
 
164
        outputln("_FID_CACHE {");
 
165
        outputln("\tint cached;");
 
166
        outputln("\tjclass clazz;");
 
167
        output("\tjfieldID ");
 
168
        List<JNIField> fields = clazz.getDeclaredFields();
 
169
        boolean first = true;
 
170
        for (JNIField field : fields) {
 
171
            if (ignoreField(field))
 
172
                continue;
 
173
            if (!first)
 
174
                output(", ");
 
175
            output(field.getName());
 
176
            first = false;
 
177
        }
 
178
        outputln(";");
 
179
        output("} ");
 
180
        output(clazzName);
 
181
        outputln("_FID_CACHE;");
 
182
    }
 
183
 
 
184
    void generateCacheFunction(JNIClass clazz) {
 
185
        String clazzName = clazz.getSimpleName();
 
186
        output("void cache");
 
187
        output(clazzName);
 
188
        outputln("Fields(JNIEnv *env, jobject lpObject)");
 
189
        outputln("{");
 
190
        output("\tif (");
 
191
        output(clazzName);
 
192
        outputln("Fc.cached) return;");
 
193
        JNIClass superclazz = clazz.getSuperclass();
 
194
        if (!superclazz.getName().equals("java.lang.Object")) {
 
195
            String superName = superclazz.getSimpleName();
 
196
            output("\tcache");
 
197
            output(superName);
 
198
            outputln("Fields(env, lpObject);");
 
199
        }
 
200
        output("\t");
 
201
        output(clazzName);
 
202
        if (isCPP) {
 
203
            if (GLOBAL_REF) {
 
204
                output("Fc.clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(lpObject));");
 
205
            } else {
 
206
                output("Fc.clazz = env->GetObjectClass(lpObject);");
 
207
            }
 
208
        } else {
 
209
            if (GLOBAL_REF) {
 
210
                output("Fc.clazz = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, lpObject));");
 
211
            } else {
 
212
                output("Fc.clazz = (*env)->GetObjectClass(env, lpObject);");
 
213
            }
 
214
        }
 
215
        outputln();
 
216
        List<JNIField> fields = clazz.getDeclaredFields();
 
217
        for (JNIField field : fields) {
 
218
            if (ignoreField(field))
 
219
                continue;
 
220
            output("\t");
 
221
            output(clazzName);
 
222
            output("Fc.");
 
223
            output(field.getName());
 
224
            if (isCPP) {
 
225
                output(" = env->GetFieldID(");
 
226
            } else {
 
227
                output(" = (*env)->GetFieldID(env, ");
 
228
            }
 
229
            output(clazzName);
 
230
            output("Fc.clazz, \"");
 
231
            output(field.getName());
 
232
            JNIType type = field.getType(), type64 = field.getType64();
 
233
            output("\", ");
 
234
            if (type.equals(type64))
 
235
                output("\"");
 
236
            output(type.getTypeSignature(!type.equals(type64)));
 
237
            if (type.equals(type64))
 
238
                output("\"");
 
239
            outputln(");");
 
240
        }
 
241
        output("\t");
 
242
        output(clazzName);
 
243
        outputln("Fc.cached = 1;");
 
244
        outputln("}");
 
245
    }
 
246
 
 
247
    void generateGetFields(JNIClass clazz) {
 
248
        JNIClass superclazz = clazz.getSuperclass();
 
249
        String clazzName = clazz.getSimpleName();
 
250
        String superName = superclazz.getSimpleName();
 
251
        if (!superclazz.getName().equals("java.lang.Object")) {
 
252
            /*
 
253
             * Windows exception - cannot call get/set function of super class
 
254
             * in this case
 
255
             */
 
256
            if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) {
 
257
                output("\tget");
 
258
                output(superName);
 
259
                output("Fields(env, lpObject, (");
 
260
                output(superName);
 
261
                outputln(" *)lpStruct);");
 
262
            } else {
 
263
                generateGetFields(superclazz);
 
264
            }
 
265
        }
 
266
        List<JNIField> fields = clazz.getDeclaredFields();
 
267
        for (JNIField field : fields) {
 
268
            if (ignoreField(field))
 
269
                continue;
 
270
            String conditional = field.getConditional();
 
271
            if (conditional!=null) {
 
272
                outputln("#if "+conditional);
 
273
            }
 
274
            JNIType type = field.getType(), type64 = field.getType64();
 
275
            String typeName = type.getSimpleName();
 
276
            String accessor = field.getAccessor();
 
277
            if (accessor == null || accessor.length() == 0)
 
278
                accessor = field.getName();
 
279
            if (type.isPrimitive()) {
 
280
                output("\tlpStruct->");
 
281
                output(accessor);
 
282
                output(" = ");
 
283
                output(field.getCast());
 
284
                if( field.isPointer() ) {
 
285
                    output("(intptr_t)");
 
286
                }
 
287
                if (isCPP) {
 
288
                    output("env->Get");
 
289
                } else {
 
290
                    output("(*env)->Get");
 
291
                }
 
292
                output(type.getTypeSignature1(!type.equals(type64)));
 
293
                if (isCPP) {
 
294
                    output("Field(lpObject, ");
 
295
                } else {
 
296
                    output("Field(env, lpObject, ");
 
297
                }
 
298
                output(field.getDeclaringClass().getSimpleName());
 
299
                output("Fc.");
 
300
                output(field.getName());
 
301
                output(");");
 
302
            } else if (type.isArray()) {
 
303
                JNIType componentType = type.getComponentType(), componentType64 = type64.getComponentType();
 
304
                if (componentType.isPrimitive()) {
 
305
                    outputln("\t{");
 
306
                    output("\t");
 
307
                    output(type.getTypeSignature2(!type.equals(type64)));
 
308
                    output(" lpObject1 = (");
 
309
                    output(type.getTypeSignature2(!type.equals(type64)));
 
310
                    if (isCPP) {
 
311
                        output(")env->GetObjectField(lpObject, ");
 
312
                    } else {
 
313
                        output(")(*env)->GetObjectField(env, lpObject, ");
 
314
                    }
 
315
                    output(field.getDeclaringClass().getSimpleName());
 
316
                    output("Fc.");
 
317
                    output(field.getName());
 
318
                    outputln(");");
 
319
                    if (isCPP) {
 
320
                        output("\tenv->Get");
 
321
                    } else {
 
322
                        output("\t(*env)->Get");
 
323
                    }
 
324
                    output(componentType.getTypeSignature1(!componentType.equals(componentType64)));
 
325
                    if (isCPP) {
 
326
                        output("ArrayRegion(lpObject1, 0, sizeof(lpStruct->");
 
327
                    } else {
 
328
                        output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->");
 
329
                    }
 
330
                    output(accessor);
 
331
                    output(")");
 
332
                    if (!componentType.isType("byte")) {
 
333
                        output(" / sizeof(");
 
334
                        output(componentType.getTypeSignature2(!componentType.equals(componentType64)));
 
335
                        output(")");
 
336
                    }
 
337
                    output(", (");
 
338
                    output(type.getTypeSignature4(!type.equals(type64), false));
 
339
                    output(")lpStruct->");
 
340
                    output(accessor);
 
341
                    outputln(");");
 
342
                    output("\t}");
 
343
                } else {
 
344
                    throw new Error("not done");
 
345
                }
 
346
            } else {
 
347
                outputln("\t{");
 
348
                if (isCPP) {
 
349
                    output("\tjobject lpObject1 = env->GetObjectField(lpObject, ");
 
350
                } else {
 
351
                    output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, ");
 
352
                }
 
353
                output(field.getDeclaringClass().getSimpleName());
 
354
                output("Fc.");
 
355
                output(field.getName());
 
356
                outputln(");");
 
357
                output("\tif (lpObject1 != NULL) get");
 
358
                output(typeName);
 
359
                output("Fields(env, lpObject1, &lpStruct->");
 
360
                output(accessor);
 
361
                outputln(");");
 
362
                output("\t}");
 
363
            }
 
364
            outputln();
 
365
            if (conditional!=null) {
 
366
                outputln("#endif");
 
367
            }
 
368
        }
 
369
    }
 
370
 
 
371
    void generateGetFunction(JNIClass clazz) {
 
372
        String clazzName = clazz.getSimpleName();
 
373
        if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
 
374
            output("struct ");
 
375
        }
 
376
        output(clazzName);
 
377
        output(" *get");
 
378
        output(clazzName);
 
379
        output("Fields(JNIEnv *env, jobject lpObject, ");
 
380
        if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
 
381
            output("struct ");
 
382
        }
 
383
        output(clazzName);
 
384
        outputln(" *lpStruct)");
 
385
        outputln("{");
 
386
        output("\tif (!");
 
387
        output(clazzName);
 
388
        output("Fc.cached) cache");
 
389
        output(clazzName);
 
390
        outputln("Fields(env, lpObject);");
 
391
        if( clazz.getFlag(ClassFlag.ZERO_OUT) ) {
 
392
            outputln("memset(lpStruct, 0, sizeof(struct "+clazzName+"));");
 
393
        }
 
394
        generateGetFields(clazz);
 
395
        outputln("\treturn lpStruct;");
 
396
        outputln("}");
 
397
    }
 
398
 
 
399
    void generateSetFields(JNIClass clazz) {
 
400
        JNIClass superclazz = clazz.getSuperclass();
 
401
        String clazzName = clazz.getSimpleName();
 
402
        String superName = superclazz.getSimpleName();
 
403
        if (!superclazz.getName().equals("java.lang.Object")) {
 
404
            /*
 
405
             * Windows exception - cannot call get/set function of super class
 
406
             * in this case
 
407
             */
 
408
            if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) {
 
409
                output("\tset");
 
410
                output(superName);
 
411
                output("Fields(env, lpObject, (");
 
412
                output(superName);
 
413
                outputln(" *)lpStruct);");
 
414
            } else {
 
415
                generateSetFields(superclazz);
 
416
            }
 
417
        }
 
418
        List<JNIField> fields = clazz.getDeclaredFields();
 
419
        for (JNIField field : fields) {
 
420
            if (ignoreField(field))
 
421
                continue;
 
422
            String conditional = field.getConditional();
 
423
            if (conditional!=null) {
 
424
                outputln("#if "+conditional);
 
425
            }
 
426
            JNIType type = field.getType(), type64 = field.getType64();
 
427
            boolean allowConversion = !type.equals(type64);
 
428
            
 
429
            String typeName = type.getSimpleName();
 
430
            String accessor = field.getAccessor();
 
431
            if (accessor == null || accessor.length() == 0)
 
432
                accessor = field.getName();
 
433
            if (type.isPrimitive()) {
 
434
                if (isCPP) {
 
435
                    output("\tenv->Set");
 
436
                } else {
 
437
                    output("\t(*env)->Set");
 
438
                }
 
439
                output(type.getTypeSignature1(allowConversion));
 
440
                if (isCPP) {
 
441
                    output("Field(lpObject, ");
 
442
                } else {
 
443
                    output("Field(env, lpObject, ");
 
444
                }
 
445
                output(field.getDeclaringClass().getSimpleName());
 
446
                output("Fc.");
 
447
                output(field.getName());
 
448
                output(", ");
 
449
                output("("+type.getTypeSignature2(allowConversion)+")");
 
450
                if( field.isPointer() ) {
 
451
                    output("(intptr_t)");
 
452
                }
 
453
                output("lpStruct->"+accessor);
 
454
                output(");");
 
455
            } else if (type.isArray()) {
 
456
                JNIType componentType = type.getComponentType(), componentType64 = type64.getComponentType();
 
457
                if (componentType.isPrimitive()) {
 
458
                    outputln("\t{");
 
459
                    output("\t");
 
460
                    output(type.getTypeSignature2(allowConversion));
 
461
                    output(" lpObject1 = (");
 
462
                    output(type.getTypeSignature2(allowConversion));
 
463
                    if (isCPP) {
 
464
                        output(")env->GetObjectField(lpObject, ");
 
465
                    } else {
 
466
                        output(")(*env)->GetObjectField(env, lpObject, ");
 
467
                    }
 
468
                    output(field.getDeclaringClass().getSimpleName());
 
469
                    output("Fc.");
 
470
                    output(field.getName());
 
471
                    outputln(");");
 
472
                    if (isCPP) {
 
473
                        output("\tenv->Set");
 
474
                    } else {
 
475
                        output("\t(*env)->Set");
 
476
                    }
 
477
                    output(componentType.getTypeSignature1(!componentType.equals(componentType64)));
 
478
                    if (isCPP) {
 
479
                        output("ArrayRegion(lpObject1, 0, sizeof(lpStruct->");
 
480
                    } else {
 
481
                        output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->");
 
482
                    }
 
483
                    output(accessor);
 
484
                    output(")");
 
485
                    if (!componentType.isType("byte")) {
 
486
                        output(" / sizeof(");
 
487
                        output(componentType.getTypeSignature2(!componentType.equals(componentType64)));
 
488
                        output(")");
 
489
                    }
 
490
                    output(", (");
 
491
                    output(type.getTypeSignature4(allowConversion, false));
 
492
                    output(")lpStruct->");
 
493
                    output(accessor);
 
494
                    outputln(");");
 
495
                    output("\t}");
 
496
                } else {
 
497
                    throw new Error("not done");
 
498
                }
 
499
            } else {
 
500
                outputln("\t{");
 
501
                output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, ");
 
502
                output(field.getDeclaringClass().getSimpleName());
 
503
                output("Fc.");
 
504
                output(field.getName());
 
505
                outputln(");");
 
506
                output("\tif (lpObject1 != NULL) set");
 
507
                output(typeName);
 
508
                output("Fields(env, lpObject1, &lpStruct->");
 
509
                output(accessor);
 
510
                outputln(");");
 
511
                output("\t}");
 
512
            }
 
513
            outputln();
 
514
            if (conditional!=null) {
 
515
                outputln("#endif");
 
516
            }
 
517
        }
 
518
    }
 
519
 
 
520
    void generateSetFunction(JNIClass clazz) {
 
521
        String clazzName = clazz.getSimpleName();
 
522
        output("void set");
 
523
        output(clazzName);
 
524
        output("Fields(JNIEnv *env, jobject lpObject, ");
 
525
        if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
 
526
            output("struct ");
 
527
        }
 
528
        output(clazzName);
 
529
        outputln(" *lpStruct)");
 
530
        outputln("{");
 
531
        output("\tif (!");
 
532
        output(clazzName);
 
533
        output("Fc.cached) cache");
 
534
        output(clazzName);
 
535
        outputln("Fields(env, lpObject);");
 
536
        generateSetFields(clazz);
 
537
        outputln("}");
 
538
    }
 
539
 
 
540
    void generateFunctions(JNIClass clazz) {
 
541
        generateCacheFunction(clazz);
 
542
        outputln();
 
543
        generateGetFunction(clazz);
 
544
        outputln();
 
545
        generateSetFunction(clazz);
 
546
    }
 
547
 
 
548
    boolean ignoreField(JNIField field) {
 
549
        int mods = field.getModifiers();
 
550
        return ((mods & Modifier.PUBLIC) == 0) || ((mods & Modifier.FINAL) != 0) || ((mods & Modifier.STATIC) != 0);
 
551
    }
 
552
 
 
553
}