slang_rs_reflection.cpp revision c20992e629a0edb507be763851edaf073cb5b18a
1#include "slang_rs_context.hpp"
2#include "slang_rs_export_var.hpp"
3#include "slang_rs_reflection.hpp"
4#include "slang_rs_export_func.hpp"
5
6#include <ctype.h>
7
8#include <utility>
9#include <cstdarg>
10
11using std::make_pair;
12using std::endl;
13
14
15#define RS_SCRIPT_CLASS_NAME_PREFIX         "ScriptC_"
16#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME    "ScriptC"
17
18#define RS_TYPE_CLASS_NAME_PREFIX           "ScriptField_"
19#define RS_TYPE_CLASS_SUPER_CLASS_NAME      "android.renderscript.Script.FieldBase"
20
21#define RS_TYPE_ITEM_CLASS_NAME             "Item"
22
23#define RS_TYPE_ITEM_BUFFER_NAME            "mItemArray"
24#define RS_TYPE_ITEM_BUFFER_PACKER_NAME     "mIOBuffer"
25
26#define RS_EXPORT_VAR_INDEX_PREFIX          "mExportVarIdx_"
27#define RS_EXPORT_VAR_PREFIX                "mExportVar_"
28
29#define RS_EXPORT_FUNC_INDEX_PREFIX         "mExportFuncIdx_"
30
31#define RS_EXPORT_VAR_ALLOCATION_PREFIX     "mAlloction_"
32#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX   "mData_"
33
34namespace slang {
35
36/* Some utility function using internal in RSReflection */
37static bool GetFileNameWithoutExtension(const std::string& FileName, std::string& OutFileName) {
38    OutFileName.clear();
39
40    if(FileName.empty() || (FileName == "-"))
41        return true;
42
43    /* find last component in given path */
44    size_t SlashPos = FileName.find_last_of("/\\");
45
46    if((SlashPos != std::string::npos) && ((SlashPos + 1) < FileName.length()))
47        OutFileName = FileName.substr(SlashPos + 1);
48    else
49        OutFileName = FileName;
50
51    size_t DotPos = OutFileName.find_first_of('.');
52    if(DotPos != std::string::npos)
53        OutFileName.erase(DotPos);
54
55    return true;
56}
57
58static const char* GetPrimitiveTypeName(const RSExportPrimitiveType* EPT) {
59    static const char* PrimitiveTypeJavaNameMap[] = {
60        "",
61        "",
62        "float",    /* RSExportPrimitiveType::DataTypeFloat32 */
63        "double",   /* RSExportPrimitiveType::DataTypeFloat64 */
64        "byte",     /* RSExportPrimitiveType::DataTypeSigned8 */
65        "short",    /* RSExportPrimitiveType::DataTypeSigned16 */
66        "int",      /* RSExportPrimitiveType::DataTypeSigned32 */
67        "long",     /* RSExportPrimitiveType::DataTypeSigned64 */
68        "short",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
69        "int",      /* RSExportPrimitiveType::DataTypeUnsigned16 */
70        "long",     /* RSExportPrimitiveType::DataTypeUnsigned32 */
71        "long",     /* RSExportPrimitiveType::DataTypeUnsigned64 */
72
73        "int",      /* RSExportPrimitiveType::DataTypeUnsigned565 */
74        "int",      /* RSExportPrimitiveType::DataTypeUnsigned5551 */
75        "int",      /* RSExportPrimitiveType::DataTypeUnsigned4444 */
76
77        "Element",  /* RSExportPrimitiveType::DataTypeRSElement */
78        "Type",     /* RSExportPrimitiveType::DataTypeRSType */
79        "Allocation",   /* RSExportPrimitiveType::DataTypeRSAllocation */
80        "Sampler",  /* RSExportPrimitiveType::DataTypeRSSampler */
81        "Script",   /* RSExportPrimitiveType::DataTypeRSScript */
82        "SimpleMesh",       /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
83        "ProgramFragment",  /* RSExportPrimitiveType::DataTypeRSProgramFragment */
84        "ProgramVertex",    /* RSExportPrimitiveType::DataTypeRSProgramVertex */
85        "ProgramRaster",    /* RSExportPrimitiveType::DataTypeRSProgramRaster */
86        "ProgramStore",     /* RSExportPrimitiveType::DataTypeRSProgramStore */
87    };
88
89    if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveTypeJavaNameMap) / sizeof(const char*))))
90        return PrimitiveTypeJavaNameMap[ EPT->getType() ];
91
92    assert(false && "GetPrimitiveTypeName : Unknown primitive data type");
93    return NULL;
94}
95
96static const char* GetVectorTypeName(const RSExportVectorType* EVT) {
97    static const char* VectorTypeJavaNameMap[][3] = {
98        /* 0 */ { "Byte2",  "Byte3",    "Byte4" },
99        /* 1 */ { "Short2", "Short3",   "Short4" },
100        /* 2 */ { "Int2",   "Int3",     "Int4" },
101        /* 3 */ { "Long2",  "Long3",    "Long4" },
102        /* 4 */ { "Float2", "Float3",   "Float4" },
103    };
104
105    const char** BaseElement;
106
107    switch(EVT->getType()) {
108        case RSExportPrimitiveType::DataTypeSigned8:
109            BaseElement = VectorTypeJavaNameMap[0];
110        break;
111
112        case RSExportPrimitiveType::DataTypeSigned16:
113        case RSExportPrimitiveType::DataTypeUnsigned8:
114            BaseElement = VectorTypeJavaNameMap[1];
115        break;
116
117        case RSExportPrimitiveType::DataTypeSigned32:
118        case RSExportPrimitiveType::DataTypeUnsigned16:
119            BaseElement = VectorTypeJavaNameMap[2];
120        break;
121
122        case RSExportPrimitiveType::DataTypeUnsigned32:
123            BaseElement = VectorTypeJavaNameMap[3];
124        break;
125
126        case RSExportPrimitiveType::DataTypeFloat32:
127            BaseElement = VectorTypeJavaNameMap[4];
128        break;
129
130        default:
131            assert(false && "RSReflection::genElementTypeName : Unsupported vector element data type");
132        break;
133    }
134
135    assert((EVT->getNumElement() > 1) && (EVT->getNumElement() <= 4) && "Number of element in vector type is invalid");
136
137    return BaseElement[EVT->getNumElement() - 2];
138}
139
140static const char* GetPackerAPIName(const RSExportPrimitiveType* EPT) {
141    static const char* PrimitiveTypePackerAPINameMap[] = {
142        "",
143        "",
144        "addF32",   /* RSExportPrimitiveType::DataTypeFloat32 */
145        "addF64",   /* RSExportPrimitiveType::DataTypeFloat64 */
146        "addI8",    /* RSExportPrimitiveType::DataTypeSigned8 */
147        "addI16",   /* RSExportPrimitiveType::DataTypeSigned16 */
148        "addI32",   /* RSExportPrimitiveType::DataTypeSigned32 */
149        "addI64",   /* RSExportPrimitiveType::DataTypeSigned64 */
150        "addU8",    /* RSExportPrimitiveType::DataTypeUnsigned8 */
151        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned16 */
152        "addU32",   /* RSExportPrimitiveType::DataTypeUnsigned32 */
153        "addU64",   /* RSExportPrimitiveType::DataTypeUnsigned64 */
154
155        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
156        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
157        "addU16",   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
158
159        "addObj",   /* RSExportPrimitiveType::DataTypeRSElement */
160        "addObj",   /* RSExportPrimitiveType::DataTypeRSType */
161        "addObj",   /* RSExportPrimitiveType::DataTypeRSAllocation */
162        "addObj",   /* RSExportPrimitiveType::DataTypeRSSampler */
163        "addObj",   /* RSExportPrimitiveType::DataTypeRSScript */
164        "addObj",   /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
165        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramFragment */
166        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
167        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
168        "addObj",   /* RSExportPrimitiveType::DataTypeRSProgramStore */
169    };
170
171    if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*))))
172        return PrimitiveTypePackerAPINameMap[ EPT->getType() ];
173
174    assert(false && "GetPackerAPIName : Unknown primitive data type");
175    return NULL;
176}
177
178static std::string GetTypeName(const RSExportType* ET) {
179    switch(ET->getClass()) {
180        case RSExportType::ExportClassPrimitive:
181            return GetPrimitiveTypeName(static_cast<const RSExportPrimitiveType*>(ET));
182        break;
183
184        case RSExportType::ExportClassPointer:
185        {
186            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
187
188            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
189                return "Allocation";
190            else
191                return RS_TYPE_CLASS_NAME_PREFIX + PointeeType->getName();
192        }
193        break;
194
195        case RSExportType::ExportClassVector:
196            return GetVectorTypeName(static_cast<const RSExportVectorType*>(ET));
197        break;
198
199        case RSExportType::ExportClassRecord:
200            return RS_TYPE_CLASS_NAME_PREFIX + ET->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
201        break;
202
203        default:
204            assert(false && "Unknown class of type");
205        break;
206    }
207
208    return "";
209}
210
211static const char* GetBuiltinElementConstruct(const RSExportType* ET) {
212    if(ET->getClass() == RSExportType::ExportClassPrimitive) {
213        const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
214        if(EPT->getKind() == RSExportPrimitiveType::DataKindUser) {
215            static const char* PrimitiveBuiltinElementConstructMap[] = {
216                NULL,
217                NULL,
218                "USER_F32", /* RSExportPrimitiveType::DataTypeFloat32 */
219                NULL,       /* RSExportPrimitiveType::DataTypeFloat64 */
220                "USER_I8",  /* RSExportPrimitiveType::DataTypeSigned8 */
221                NULL,       /* RSExportPrimitiveType::DataTypeSigned16 */
222                "USER_I32", /* RSExportPrimitiveType::DataTypeSigned32 */
223                NULL,       /* RSExportPrimitiveType::DataTypeSigned64 */
224                "USER_U8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
225                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned16 */
226                "USER_U32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
227                NULL,       /* RSExportPrimitiveType::DataTypeUnsigned64 */
228
229                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned565 */
230                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned5551 */
231                NULL,   /* RSExportPrimitiveType::DataTypeUnsigned4444 */
232
233                "USER_ELEMENT", /* RSExportPrimitiveType::DataTypeRSElement */
234                "USER_TYPE",    /* RSExportPrimitiveType::DataTypeRSType */
235                "USER_ALLOCATION",  /* RSExportPrimitiveType::DataTypeRSAllocation */
236                "USER_SAMPLER",     /* RSExportPrimitiveType::DataTypeRSSampler */
237                "USER_SCRIPT",      /* RSExportPrimitiveType::DataTypeRSScript */
238                "USER_MESH",        /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
239                "USER_PROGRAM_FRAGMENT",    /* RSExportPrimitiveType::DataTypeRSProgramFragment */
240                "USER_PROGRAM_VERTEX",      /* RSExportPrimitiveType::DataTypeRSProgramVertex */
241                "USER_PROGRAM_RASTER",      /* RSExportPrimitiveType::DataTypeRSProgramRaster */
242                "USER_PROGRAM_STORE",       /* RSExportPrimitiveType::DataTypeRSProgramStore */
243            };
244
245            if((EPT->getType() >= 0) && (EPT->getType() < (sizeof(PrimitiveBuiltinElementConstructMap) / sizeof(const char*))))
246                return PrimitiveBuiltinElementConstructMap[ EPT->getType() ];
247        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelA) {
248            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
249                return "A_8";
250        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGB) {
251            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned565)
252                return "RGB_565";
253            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
254                return "RGB_888";
255        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGBA) {
256            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned5551)
257                return "RGB_5551";
258            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned4444)
259                return "RGB_4444";
260            else if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
261                return "RGB_8888";
262        } else if(EPT->getKind() == RSExportPrimitiveType::DataKindIndex) {
263            if(EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned16)
264                return "INDEX_16";
265        }
266    } else if(ET->getClass() == RSExportType::ExportClassVector) {
267        const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(ET);
268        if(EVT->getKind() == RSExportPrimitiveType::DataKindPosition) {
269            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
270                if(EVT->getNumElement() == 2)
271                    return "ATTRIB_POSITION_2";
272                else if(EVT->getNumElement() == 3)
273                    return "ATTRIB_POSITION_3";
274            }
275        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindTexture) {
276            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
277                if(EVT->getNumElement() == 2)
278                    return "ATTRIB_TEXTURE_2";
279            }
280        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindNormal) {
281            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
282                if(EVT->getNumElement() == 3)
283                    return "ATTRIB_NORMAL_3";
284            }
285        } else if(EVT->getKind() == RSExportPrimitiveType::DataKindColor) {
286            if(EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
287                if(EVT->getNumElement() == 4)
288                    return "ATTRIB_COLOR_F32_4";
289            } else if(EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
290                if(EVT->getNumElement() == 4)
291                    return "ATTRIB_COLOR_U8_4";
292            }
293        }
294    } else if(ET->getClass() == RSExportType::ExportClassPointer) {
295        return "USER_I32";  /* tread pointer type variable as unsigned int (TODO: this is target dependent) */
296    }
297
298    return NULL;
299}
300
301static const char* GetElementDataKindName(RSExportPrimitiveType::DataKind DK) {
302    static const char* ElementDataKindNameMap[] = {
303        "Element.DataKind.USER",        /* RSExportPrimitiveType::DataKindUser */
304        "Element.DataKind.COLOR",       /* RSExportPrimitiveType::DataKindColor */
305        "Element.DataKind.POSITION",    /* RSExportPrimitiveType::DataKindPosition */
306        "Element.DataKind.TEXTURE",     /* RSExportPrimitiveType::DataKindTexture */
307        "Element.DataKind.NORMAL",      /* RSExportPrimitiveType::DataKindNormal */
308        "Element.DataKind.INDEX",       /* RSExportPrimitiveType::DataKindIndex */
309        "Element.DataKind.POINT_SIZE",  /* RSExportPrimitiveType::DataKindPointSize */
310        "Element.DataKind.PIXEL_L",     /* RSExportPrimitiveType::DataKindPixelL */
311        "Element.DataKind.PIXEL_A",     /* RSExportPrimitiveType::DataKindPixelA */
312        "Element.DataKind.PIXEL_LA",    /* RSExportPrimitiveType::DataKindPixelLA */
313        "Element.DataKind.PIXEL_RGB",   /* RSExportPrimitiveType::DataKindPixelRGB */
314        "Element.DataKind.PIXEL_RGBA",  /* RSExportPrimitiveType::DataKindPixelRGBA */
315    };
316
317    if((DK >= 0) && (DK < (sizeof(ElementDataKindNameMap) / sizeof(const char*))))
318        return ElementDataKindNameMap[ DK ];
319    else
320        return NULL;
321}
322
323static const char* GetElementDataTypeName(RSExportPrimitiveType::DataType DT) {
324    static const char* ElementDataTypeNameMap[] = {
325        NULL,
326        NULL,
327        "Element.DataType.FLOAT_32",    /* RSExportPrimitiveType::DataTypeFloat32 */
328        NULL,                           /* RSExportPrimitiveType::DataTypeFloat64 */
329        "Element.DataType.SIGNED_8",    /* RSExportPrimitiveType::DataTypeSigned8 */
330        "Element.DataType.SIGNED_16",   /* RSExportPrimitiveType::DataTypeSigned16 */
331        "Element.DataType.SIGNED_32",   /* RSExportPrimitiveType::DataTypeSigned32 */
332        NULL,                           /* RSExportPrimitiveType::DataTypeSigned64 */
333        "Element.DataType.UNSIGNED_8",  /* RSExportPrimitiveType::DataTypeUnsigned8 */
334        "Element.DataType.UNSIGNED_16", /* RSExportPrimitiveType::DataTypeUnsigned16 */
335        "Element.DataType.UNSIGNED_32", /* RSExportPrimitiveType::DataTypeUnsigned32 */
336        NULL,                           /* RSExportPrimitiveType::DataTypeUnsigned64 */
337
338        "Element.DataType.UNSIGNED_5_6_5",   /* RSExportPrimitiveType::DataTypeUnsigned565 */
339        "Element.DataType.UNSIGNED_5_5_5_1", /* RSExportPrimitiveType::DataTypeUnsigned5551 */
340        "Element.DataType.UNSIGNED_4_4_4_4", /* RSExportPrimitiveType::DataTypeUnsigned4444 */
341
342        "Element.DataType.RS_ELEMENT",  /* RSExportPrimitiveType::DataTypeRSElement */
343        "Element.DataType.RS_TYPE",     /* RSExportPrimitiveType::DataTypeRSType */
344        "Element.DataType.RS_ALLOCATION",   /* RSExportPrimitiveType::DataTypeRSAllocation */
345        "Element.DataType.RS_SAMPLER",      /* RSExportPrimitiveType::DataTypeRSSampler */
346        "Element.DataType.RS_SCRIPT",       /* RSExportPrimitiveType::DataTypeRSScript */
347        "Element.DataType.RS_MESH",         /* RSExportPrimitiveType::DataTypeRSSimpleMesh */
348        "Element.DataType.RS_PROGRAM_FRAGMENT", /* RSExportPrimitiveType::DataTypeRSProgramFragment */
349        "Element.DataType.RS_PROGRAM_VERTEX",   /* RSExportPrimitiveType::DataTypeRSProgramVertex */
350        "Element.DataType.RS_PROGRAM_RASTER",   /* RSExportPrimitiveType::DataTypeRSProgramRaster */
351        "Element.DataType.RS_PROGRAM_STORE",    /* RSExportPrimitiveType::DataTypeRSProgramStore */
352    };
353
354    if((DT >= 0) && (DT < (sizeof(ElementDataTypeNameMap) / sizeof(const char*))))
355        return ElementDataTypeNameMap[ DT ];
356    else
357        return NULL;
358}
359
360/****************************** Methods to generate script class ******************************/
361bool RSReflection::genScriptClass(Context& C, const std::string& ClassName, std::string& ErrorMsg) {
362    if(!C.startClass(Context::AM_Public, false, ClassName, RS_SCRIPT_CLASS_SUPER_CLASS_NAME, ErrorMsg))
363        return false;
364
365    genScriptClassConstructor(C);
366
367    /* Reflect export variable */
368    for(RSContext::const_export_var_iterator I = mRSContext->export_vars_begin();
369        I != mRSContext->export_vars_end();
370        I++)
371        genExportVariable(C, *I);
372
373    /* Reflect export function */
374    for(RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin();
375        I != mRSContext->export_funcs_end();
376        I++)
377        genExportFunction(C, *I);
378
379    C.endClass();
380
381    return true;
382}
383
384void RSReflection::genScriptClassConstructor(Context& C) {
385    C.indent() << "// Constructor" << endl;
386    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 3, "RenderScript", "rs",
387                                                                          "Resources", "resources",
388                                                                          "boolean", "isRoot");
389    /* Call constructor of super class */
390    C.indent() << "super(rs, resources, R.raw." << C.getResourceId() << ", isRoot);" << endl;
391    C.endFunction();
392    return;
393}
394
395void RSReflection::genExportVariable(Context& C, const RSExportVar* EV) {
396    const RSExportType* ET = EV->getType();
397
398    C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << " = " << C.getNextExportVarSlot() << ";" << endl;
399
400    switch(ET->getClass()) {
401        case RSExportType::ExportClassPrimitive:
402            genPrimitiveTypeExportVariable(C, EV);
403        break;
404
405        case RSExportType::ExportClassPointer:
406            genPointerTypeExportVariable(C, EV);
407        break;
408
409        case RSExportType::ExportClassVector:
410            genVectorTypeExportVariable(C, EV);
411        break;
412
413        case RSExportType::ExportClassRecord:
414            genRecordTypeExportVariable(C, EV);
415        break;
416
417        default:
418            assert(false && "Unknown class of type");
419        break;
420    }
421
422    return;
423}
424
425void RSReflection::genExportFunction(Context& C, const RSExportFunc* EF) {
426    C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << " = " << C.getNextExportFuncSlot() << ";" << endl;
427
428    /* invoke_*() */
429    Context::ArgTy Args;
430
431    for(RSExportFunc::const_param_iterator I = EF->params_begin();
432        I != EF->params_end();
433        I++)
434    {
435        const RSExportFunc::Parameter* P = *I;
436        Args.push_back( make_pair(GetTypeName(P->getType()), P->getName()) );
437    }
438
439    C.startFunction(Context::AM_Public, false, "void", "invoke_" + EF->getName(), Args);
440
441    if(!EF->hasParam()) {
442        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", null);" << endl;
443    } else {
444        const RSExportRecordType* ERT = EF->getParamPacketType();
445        std::string FieldPackerName = EF->getName() + "_fp";
446
447        if(genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
448            genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
449
450        C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", " << FieldPackerName << ");" << endl;
451    }
452
453    C.endFunction();
454    return;
455}
456
457void RSReflection::genPrimitiveTypeExportVariable(Context& C, const RSExportVar* EV) {
458    assert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive) && "Variable should be type of primitive here");
459
460    const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(EV->getType());
461    const char* TypeName = GetPrimitiveTypeName(EPT);
462
463    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
464
465    /* set_*() */
466    C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
467    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
468
469    if(EPT->isRSObjectType())
470        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", v.getID());" << endl;
471    else
472        C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", v);" << endl;
473
474    C.endFunction();
475
476    genGetExportVariable(C, TypeName, EV->getName());
477
478    return;
479}
480
481void RSReflection::genPointerTypeExportVariable(Context& C, const RSExportVar* EV) {
482    const RSExportType* ET = EV->getType();
483    const RSExportType* PointeeType;
484    std::string TypeName;
485
486    assert((ET->getClass() == RSExportType::ExportClassPointer) && "Variable should be type of pointer here");
487
488    PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
489    TypeName = GetTypeName(ET);
490
491    /* bind_*() */
492    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
493
494    C.startFunction(Context::AM_Public, false, "void", "bind_" + EV->getName(), 1, TypeName.c_str(), "v");
495
496    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
497    C.indent() << "if(v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
498
499    if(PointeeType->getClass() == RSExportType::ExportClassRecord)
500        C.indent() << "else bindAllocation(v.getAllocation(), "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
501    else
502        C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");" << endl;
503
504    C.endFunction();
505
506    genGetExportVariable(C, TypeName, EV->getName());
507
508    return;
509}
510
511void RSReflection::genVectorTypeExportVariable(Context& C, const RSExportVar* EV) {
512    assert((EV->getType()->getClass() == RSExportType::ExportClassVector) && "Variable should be type of vector here");
513
514    const RSExportVectorType* EVT = static_cast<const RSExportVectorType*>(EV->getType());
515    const char* TypeName = GetVectorTypeName(EVT);
516    const char* FieldPackerName = "fp";
517
518    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
519
520    /* set_*() */
521    C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName, "v");
522    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
523
524    if(genCreateFieldPacker(C, EVT, FieldPackerName))
525        genPackVarOfType(C, EVT, "v", FieldPackerName);
526    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
527
528    C.endFunction();
529
530    genGetExportVariable(C, TypeName, EV->getName());
531    return;
532}
533
534void RSReflection::genRecordTypeExportVariable(Context& C, const RSExportVar* EV) {
535    assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) && "Variable should be type of struct here");
536
537    const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(EV->getType());
538    std::string TypeName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
539    const char* FieldPackerName = "fp";
540
541    C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX << EV->getName() << ";" << endl;
542
543    /* set_*() */
544    C.startFunction(Context::AM_Public, false, "void", "set_" + EV->getName(), 1, TypeName.c_str(), "v");
545    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << endl;
546
547    if(genCreateFieldPacker(C, ERT, FieldPackerName))
548        genPackVarOfType(C, ERT, "v", FieldPackerName);
549    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", " << FieldPackerName << ");" << endl;
550
551    C.endFunction();
552
553    genGetExportVariable(C, TypeName.c_str(), EV->getName());
554    return;
555}
556
557void RSReflection::genGetExportVariable(Context& C, const std::string& TypeName, const std::string& VarName) {
558    C.startFunction(Context::AM_Public, false, TypeName.c_str(), "get_" + VarName, 0);
559
560    C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << endl;
561
562    C.endFunction();
563    return;
564}
565
566/****************************** Methods to generate script class /end ******************************/
567
568bool RSReflection::genCreateFieldPacker(Context& C, const RSExportType* ET, const char* FieldPackerName) {
569    size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
570    if(AllocSize > 0)
571        C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker(" << AllocSize << ");" << endl;
572    else
573        return false;
574    return true;
575}
576
577void RSReflection::genPackVarOfType(Context& C, const RSExportType* ET, const char* VarName, const char* FieldPackerName) {
578    switch(ET->getClass()) {
579        case RSExportType::ExportClassPrimitive:
580        case RSExportType::ExportClassVector:
581            C.indent() << FieldPackerName << "." << GetPackerAPIName(static_cast<const RSExportPrimitiveType*>(ET)) << "(" << VarName << ");" << endl;
582        break;
583
584        case RSExportType::ExportClassPointer:
585        {
586            /* Must reflect as type Allocation in Java */
587            const RSExportType* PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
588
589            if(PointeeType->getClass() != RSExportType::ExportClassRecord)
590                C.indent() << FieldPackerName << ".addI32(" << VarName << ".getPtr());" << endl;
591            else
592                C.indent() << FieldPackerName << ".addI32(" << VarName << ".getAllocation().getPtr());" << endl;
593        }
594        break;
595
596        case RSExportType::ExportClassRecord:
597        {
598            const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
599            int Pos = 0;    /* relative pos from now on in field packer */
600
601            for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
602                I != ERT->fields_end();
603                I++)
604            {
605                const RSExportRecordType::Field* F = *I;
606                std::string FieldName;
607                size_t FieldOffset = F->getOffsetInParent();
608                size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
609                size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
610
611                if(VarName != NULL)
612                    FieldName = VarName + ("." + F->getName());
613                else
614                    FieldName = F->getName();
615
616                if(FieldOffset > Pos)
617                    C.indent() << FieldPackerName << ".skip(" << (FieldOffset - Pos) << ");" << endl;
618
619                genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
620
621                if(FieldAllocSize > FieldStoreSize)  /* there's padding in the field type */
622                    C.indent() << FieldPackerName << ".skip(" << (FieldAllocSize - FieldStoreSize) << ");" << endl;
623
624                Pos = FieldOffset + FieldAllocSize;
625            }
626
627            /* There maybe some padding after the struct */
628            size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
629            if(Padding > 0)
630                C.indent() << FieldPackerName << ".skip(" << Padding << ");" << endl;
631        }
632        break;
633
634        default:
635            assert(false && "Unknown class of type");
636        break;
637    }
638
639    return;
640}
641
642/****************************** Methods to generate type class  ******************************/
643bool RSReflection::genTypeClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
644    std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
645
646    if(!C.startClass(Context::AM_Public, false, ClassName, RS_TYPE_CLASS_SUPER_CLASS_NAME, ErrorMsg))
647        return false;
648
649    if(!genTypeItemClass(C, ERT, ErrorMsg))
650        return false;
651
652    /* Declare item buffer and item buffer packer */
653    C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[];" << endl;
654    C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";" << endl;
655
656    genTypeClassConstructor(C, ERT);
657    genTypeClassCopyToArray(C, ERT);
658    genTypeClasSet(C, ERT);
659    genTypeClasCopyAll(C, ERT);
660
661    C.endClass();
662
663    return true;
664}
665
666bool RSReflection::genTypeItemClass(Context& C, const RSExportRecordType* ERT, std::string& ErrorMsg) {
667    C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
668    C.startBlock();
669
670    C.indent() << "public static final int sizeof = " << RSExportType::GetTypeAllocSize(ERT) << ";" << endl;
671
672    /* Member elements */
673    C.out() << endl;
674    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
675        FI != ERT->fields_end();
676        FI++)
677        C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName() << ";" << endl;
678
679    /* Constructor */
680    C.out() << endl;
681    C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
682    C.startBlock();
683
684    for(RSExportRecordType::const_field_iterator FI = ERT->fields_begin();
685        FI != ERT->fields_end();
686        FI++)
687    {
688        const RSExportRecordType::Field* F = *FI;
689        if((F->getType()->getClass() == RSExportType::ExportClassVector) || (F->getType()->getClass() == RSExportType::ExportClassRecord))
690        C.indent() << F->getName() << " = new " << GetTypeName(F->getType()) << "();" << endl;
691    }
692
693    C.endBlock();   /* end Constructor */
694
695    C.endBlock();   /* end Item class */
696
697
698    return true;
699}
700
701void RSReflection::genTypeClassConstructor(Context& C, const RSExportRecordType* ERT) {
702    const char* RenderScriptVar = "rs";
703
704    C.startFunction(Context::AM_Public, false, NULL, C.getClassName(), 2, "RenderScript", RenderScriptVar,
705                                                                          "int", "count");
706
707    C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << endl;
708    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << endl;
709
710    genBuildElement(C, ERT, "mElement", RenderScriptVar);
711    /* Call init() in super class */
712    C.indent() << "init(" << RenderScriptVar << ", count);" << endl;
713    C.endFunction();
714
715    return;
716}
717
718void RSReflection::genTypeClassCopyToArray(Context& C, const RSExportRecordType* ERT) {
719    C.startFunction(Context::AM_Private, false, "void", "copyToArray", 2, RS_TYPE_ITEM_CLASS_NAME, "i",
720                                                                          "int", "index");
721
722    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_PACKER_NAME" == null) "RS_TYPE_ITEM_BUFFER_PACKER_NAME" = new FieldPacker("RS_TYPE_ITEM_CLASS_NAME".sizeof * mType.getX() /* count */);" << endl;
723    C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);" << endl;
724
725    genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
726
727    C.endFunction();
728    return;
729}
730
731void RSReflection::genTypeClasSet(Context& C, const RSExportRecordType* ERT) {
732    C.startFunction(Context::AM_Public, false, "void", "set", 3, RS_TYPE_ITEM_CLASS_NAME, "i",
733                                                                 "int", "index",
734                                                                 "boolean", "copyNow");
735    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "RS_TYPE_ITEM_BUFFER_NAME" = new "RS_TYPE_ITEM_CLASS_NAME"[mType.getX() /* count */];" << endl;
736    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << endl;
737
738    C.indent() << "if (copyNow) ";
739    C.startBlock();
740
741    C.indent() << "copyToArray(i, index);" << endl;
742    C.indent() << "mAllocation.subData1D(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof, "RS_TYPE_ITEM_CLASS_NAME".sizeof, "RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
743
744    C.endBlock();   /* end if (copyNow) */
745
746    C.endFunction();
747    return;
748}
749
750void RSReflection::genTypeClasCopyAll(Context& C, const RSExportRecordType* ERT) {
751    C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
752
753    C.indent() << "for (int ct=0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++) copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);" << endl;
754    C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << endl;
755
756    C.endFunction();
757    return;
758}
759
760/****************************** Methods to generate type class /end ******************************/
761
762/******************** Methods to create Element in Java of given record type ********************/
763void RSReflection::genBuildElement(Context& C, const RSExportRecordType* ERT, const char* ElementName, const char* RenderScriptVar) {
764    const char* ElementBuilderName = "eb";
765
766    /* Create element builder */
767    C.startBlock(true);
768
769    C.indent() << "Element.Builder " << ElementBuilderName << " = new Element.Builder(" << RenderScriptVar << ");" << endl;
770
771    /* eb.add(...) */
772    genAddElementToElementBuilder(C, ERT, "", ElementBuilderName, RenderScriptVar);
773
774    C.indent() << ElementName << " = " << ElementBuilderName << ".create();" << endl;
775
776    C.endBlock();
777    return;
778}
779
780#define EB_ADD(x, ...)  \
781        C.indent() << ElementBuilderName << ".add(Element." << x ##__VA_ARGS__ ", \"" << VarName << "\");" << endl
782void RSReflection::genAddElementToElementBuilder(Context& C, const RSExportType* ET, const std::string& VarName, const char* ElementBuilderName, const char* RenderScriptVar) {
783        const char* ElementConstruct = GetBuiltinElementConstruct(ET);
784        if(ElementConstruct != NULL) {
785            EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
786        } else {
787            if((ET->getClass() == RSExportType::ExportClassPrimitive) || (ET->getClass() == RSExportType::ExportClassVector)) {
788                const RSExportPrimitiveType* EPT = static_cast<const RSExportPrimitiveType*>(ET);
789                const char* DataKindName = GetElementDataKindName(EPT->getKind());
790                const char* DataTypeName = GetElementDataTypeName(EPT->getType());
791                int Size = (ET->getClass() == RSExportType::ExportClassVector) ? static_cast<const RSExportVectorType*>(ET)->getNumElement() : 1;
792
793                switch(EPT->getKind()) {
794                    case RSExportPrimitiveType::DataKindColor:
795                    case RSExportPrimitiveType::DataKindPosition:
796                    case RSExportPrimitiveType::DataKindTexture:
797                    case RSExportPrimitiveType::DataKindNormal:
798                    case RSExportPrimitiveType::DataKindPointSize:
799                        /* Element.createAttrib() */
800                        EB_ADD("createAttrib(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ", " << Size << ")");
801                    break;
802
803                    case RSExportPrimitiveType::DataKindIndex:
804                        /* Element.createIndex() */
805                        EB_ADD("createAttrib(" << RenderScriptVar << ")");
806                    break;
807
808                    case RSExportPrimitiveType::DataKindPixelL:
809                    case RSExportPrimitiveType::DataKindPixelA:
810                    case RSExportPrimitiveType::DataKindPixelLA:
811                    case RSExportPrimitiveType::DataKindPixelRGB:
812                    case RSExportPrimitiveType::DataKindPixelRGBA:
813                        /* Element.createPixel() */
814                        EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << DataKindName << ")");
815                    break;
816
817                    case RSExportPrimitiveType::DataKindUser:
818                    default:
819                        if(EPT->getClass() == RSExportType::ExportClassPrimitive)
820                            /* Element.createUser() */
821                            EB_ADD("createUser(" << RenderScriptVar << ", " << DataTypeName << ")");
822                        else /* (ET->getClass() == RSExportType::ExportClassVector) must hold here */
823                            /* Element.createVector() */
824                            EB_ADD("createVector(" << RenderScriptVar << ", " << DataTypeName << ", " << Size << ")");
825                    break;
826                }
827            } else if(ET->getClass() == RSExportType::ExportClassPointer) {
828                /* Pointer type variable should be resolved in GetBuiltinElementConstruct()  */
829                assert(false && "??");
830            } else if(ET->getClass() == RSExportType::ExportClassRecord) {
831                /*
832                 * Simalar to genPackVarOfType.
833                 *
834                 * TODO: Generalize these two function such that there's no duplicated codes.
835                 */
836                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
837                int Pos = 0;    /* relative pos from now on */
838
839                for(RSExportRecordType::const_field_iterator I = ERT->fields_begin();
840                    I != ERT->fields_end();
841                    I++)
842                {
843                    const RSExportRecordType::Field* F = *I;
844                    std::string FieldName;
845                    size_t FieldOffset = F->getOffsetInParent();
846                    size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
847                    size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
848
849                    if(!VarName.empty())
850                        FieldName = VarName + "." + F->getName();
851                    else
852                        FieldName = F->getName();
853
854                    /* alignment */
855                    genAddPaddingToElementBuiler(C, (FieldOffset - Pos), ElementBuilderName, RenderScriptVar);
856
857                    /* eb.add(...) */
858                    genAddElementToElementBuilder(C, (*I)->getType(), FieldName, ElementBuilderName, RenderScriptVar);
859
860                    /* there's padding within the field type */
861                    genAddPaddingToElementBuiler(C, (FieldAllocSize - FieldStoreSize), ElementBuilderName, RenderScriptVar);
862
863                    Pos = FieldOffset + FieldAllocSize;
864                }
865
866                /* There maybe some padding after the struct */
867                genAddPaddingToElementBuiler(C, (RSExportType::GetTypeAllocSize(ERT) - Pos), ElementBuilderName, RenderScriptVar);
868            } else {
869                assert(false && "Unknown class of type");
870            }
871        }
872}
873
874void RSReflection::genAddPaddingToElementBuiler(Context& C, size_t PaddingSize, const char* ElementBuilderName, const char* RenderScriptVar) {
875    while(PaddingSize > 0) {
876        const std::string& VarName = C.createPaddingField();
877        if(PaddingSize >= 4) {
878            EB_ADD("USER_U32(" << RenderScriptVar << ")");
879            PaddingSize -= 4;
880        } else if(PaddingSize >= 2) {
881            EB_ADD("USER_U16(" << RenderScriptVar << ")");
882            PaddingSize -= 2;
883        } else if(PaddingSize >= 1) {
884            EB_ADD("USER_U8(" << RenderScriptVar << ")");
885            PaddingSize -= 1;
886        }
887    }
888    return;
889}
890
891#undef EB_ADD
892/******************** Methods to create Element in Java of given record type /end ********************/
893
894bool RSReflection::reflect(const char* OutputPackageName, const std::string& InputFileName, const std::string& OutputBCFileName) {
895    Context *C = NULL;
896    std::string ResourceId = "";
897
898    if(!GetFileNameWithoutExtension(OutputBCFileName, ResourceId))
899        return false;
900
901    if(ResourceId.empty())
902        ResourceId = "<Resource ID>";
903
904    if((OutputPackageName == NULL) || (*OutputPackageName == '\0') || strcmp(OutputPackageName, "-") == 0)
905        C = new Context("<Package Name>", ResourceId, true);
906    else
907        C = new Context(OutputPackageName, ResourceId, false);
908
909    if(C != NULL) {
910        std::string ErrorMsg, ScriptClassName;
911        /* class ScriptC_<ScriptName> */
912        if(!GetFileNameWithoutExtension(InputFileName, ScriptClassName))
913            return false;
914
915        if(ScriptClassName.empty())
916            ScriptClassName = "<Input Script Name>";
917
918        ScriptClassName.at(0) = toupper(ScriptClassName.at(0));
919        ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
920
921        if(!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
922            std::cerr << "Failed to generate class " << ScriptClassName << " (" << ErrorMsg << ")" << endl;
923            return false;
924        }
925
926        /* class ScriptField_<TypeName> */
927        for(RSContext::const_export_type_iterator TI = mRSContext->export_types_begin();
928            TI != mRSContext->export_types_end();
929            TI++)
930        {
931            const RSExportType* ET = TI->getValue();
932
933            if(ET->getClass() == RSExportType::ExportClassRecord) {
934                const RSExportRecordType* ERT = static_cast<const RSExportRecordType*>(ET);
935
936                if(!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
937                    std::cerr << "Failed to generate type class for struct '" << ERT->getName() << "' (" << ErrorMsg << ")" << endl;
938                    return false;
939                }
940            }
941        }
942    }
943
944    return true;
945}
946
947/****************************** RSReflection::Context ******************************/
948const char* const RSReflection::Context::LicenseNote =
949    "/*\n"
950	" * Copyright (C) 2010 The Android Open Source Project\n"
951	" *\n"
952	" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
953	" * you may not use this file except in compliance with the License.\n"
954	" * You may obtain a copy of the License at\n"
955	" *\n"
956	" *      http://www.apache.org/licenses/LICENSE-2.0\n"
957	" *\n"
958	" * Unless required by applicable law or agreed to in writing, software\n"
959	" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
960	" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
961	" * See the License for the specific language governing permissions and\n"
962	" * limitations under the License.\n"
963	" */\n";
964
965const char* const RSReflection::Context::Import[] = {
966    /* RenderScript java class */
967    "android.renderscript.*",
968    /* Import R */
969    "android.content.res.Resources",
970    /* Import for debugging */
971    "android.util.Log",
972};
973
974const char* RSReflection::Context::AccessModifierStr(AccessModifier AM) {
975    switch(AM) {
976        case AM_Public: return "public"; break;
977        case AM_Protected: return "protected"; break;
978        case AM_Private: return "private"; break;
979        default: return ""; break;
980    }
981}
982
983bool RSReflection::Context::startClass(AccessModifier AM, bool IsStatic, const std::string& ClassName, const char* SuperClassName, std::string& ErrorMsg) {
984    if(mVerbose)
985        std::cout << "Generating " << ClassName << ".java ..." << endl;
986
987    /* Open the file */
988    if(!mUseStdout) {
989        mOF.clear();
990        mOF.open((ClassName + ".java").c_str());
991        if(!mOF.good()) {
992            ErrorMsg = "failed to open file '" + ClassName + ".java' for write";
993            return false;
994        }
995    }
996
997    /* License */
998    out() << LicenseNote << endl;
999
1000    /* Package */
1001    if(!mPackageName.empty())
1002        out() << "package " << mPackageName << ";" << endl;
1003    out() << endl;
1004
1005    /* Imports */
1006    for(int i=0;i<(sizeof(Import)/sizeof(const char*));i++)
1007        out() << "import " << Import[i] << ";" << endl;
1008    out() << endl;
1009
1010    out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class " << ClassName;
1011    if(SuperClassName != NULL)
1012        out() << " extends " << SuperClassName;
1013
1014    startBlock();
1015
1016    mClassName = ClassName;
1017
1018    return true;
1019}
1020
1021void RSReflection::Context::endClass() {
1022    endBlock();
1023    if(!mUseStdout)
1024        mOF.close();
1025    clear();
1026    return;
1027}
1028
1029void RSReflection::Context::startBlock(bool ShouldIndent) {
1030    if(ShouldIndent)
1031        indent() << "{" << endl;
1032    else
1033        out() << " {" << endl;
1034    incIndentLevel();
1035    return;
1036}
1037
1038void RSReflection::Context::endBlock() {
1039    decIndentLevel();
1040    indent() << "}" << endl << endl;
1041    return;
1042}
1043
1044void RSReflection::Context::startTypeClass(const std::string& ClassName) {
1045    indent() << "public static class " << ClassName;
1046    startBlock();
1047    return;
1048}
1049
1050void RSReflection::Context::endTypeClass() {
1051    endBlock();
1052    return;
1053}
1054
1055void RSReflection::Context::startFunction(AccessModifier AM, bool IsStatic, const char* ReturnType, const std::string& FunctionName, int Argc, ...) {
1056    ArgTy Args;
1057    va_list vl;
1058    va_start(vl, Argc);
1059
1060    for(int i=0;i<Argc;i++) {
1061        const char* ArgType = va_arg(vl, const char*);
1062        const char* ArgName = va_arg(vl, const char*);
1063
1064        Args.push_back( make_pair(ArgType, ArgName) );
1065    }
1066    va_end(vl);
1067
1068    startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
1069
1070    return;
1071}
1072
1073void RSReflection::Context::startFunction(AccessModifier AM,
1074                                          bool IsStatic,
1075                                          const char* ReturnType,
1076                                          const std::string& FunctionName,
1077                                          const ArgTy& Args)
1078{
1079    indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ") << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
1080
1081    bool FirstArg = true;
1082    for(ArgTy::const_iterator I = Args.begin();
1083        I != Args.end();
1084        I++)
1085    {
1086        if(!FirstArg)
1087            out() << ", ";
1088        else
1089            FirstArg = false;
1090
1091        out() << I->first << " " << I->second;
1092    }
1093
1094    out() << ")";
1095    startBlock();
1096
1097    return;
1098}
1099
1100void RSReflection::Context::endFunction() {
1101    endBlock();
1102    return;
1103}
1104
1105}   /* namespace slang */
1106