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