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