slang_rs_reflection.cpp revision 8a224b81e0e87af300080123568667988fbc1f05
1#include "slang_rs_reflection.h"
2
3#include <utility>
4#include <cstdarg>
5#include <cctype>
6#include <sys/stat.h>
7
8#include "llvm/ADT/APFloat.h"
9
10#include "slang_rs_context.h"
11#include "slang_rs_export_var.h"
12#include "slang_rs_export_func.h"
13#include "slang_rs_reflect_utils.h"
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
34using namespace slang;
35
36// Some utility function using internal in RSReflection
37static bool GetClassNameFromFileName(const std::string &FileName,
38                                     std::string &ClassName) {
39  ClassName.clear();
40
41  if (FileName.empty() || (FileName == "-"))
42    return true;
43
44  ClassName =
45      RSSlangReflectUtils::JavaClassNameFromRSFileName(FileName.c_str());
46
47  return true;
48}
49
50static const char *GetPrimitiveTypeName(const RSExportPrimitiveType *EPT) {
51  static const char *PrimitiveTypeJavaNameMap[] = {
52    "",         // RSExportPrimitiveType::DataTypeFloat16
53    "float",    // RSExportPrimitiveType::DataTypeFloat32
54    "double",   // RSExportPrimitiveType::DataTypeFloat64
55    "byte",     // RSExportPrimitiveType::DataTypeSigned8
56    "short",    // RSExportPrimitiveType::DataTypeSigned16
57    "int",      // RSExportPrimitiveType::DataTypeSigned32
58    "long",     // RSExportPrimitiveType::DataTypeSigned64
59    "short",    // RSExportPrimitiveType::DataTypeUnsigned8
60    "int",      // RSExportPrimitiveType::DataTypeUnsigned16
61    "long",     // RSExportPrimitiveType::DataTypeUnsigned32
62    "long",     // RSExportPrimitiveType::DataTypeUnsigned64
63    "boolean",  // RSExportPrimitiveType::DataTypeBoolean
64
65    "int",      // RSExportPrimitiveType::DataTypeUnsigned565
66    "int",      // RSExportPrimitiveType::DataTypeUnsigned5551
67    "int",      // RSExportPrimitiveType::DataTypeUnsigned4444
68
69    "",     // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix2x2
70    "",     // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix3x3
71    "",     // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix4x4
72
73    "Element",      // RSExportPrimitiveType::DataTypeRSElement
74    "Type",         // RSExportPrimitiveType::DataTypeRSType
75    "Allocation",   // RSExportPrimitiveType::DataTypeRSAllocation
76    "Sampler",      // RSExportPrimitiveType::DataTypeRSSampler
77    "Script",       // RSExportPrimitiveType::DataTypeRSScript
78    "Mesh",         // RSExportPrimitiveType::DataTypeRSMesh
79    "ProgramFragment",  // RSExportPrimitiveType::DataTypeRSProgramFragment
80    "ProgramVertex",    // RSExportPrimitiveType::DataTypeRSProgramVertex
81    "ProgramRaster",    // RSExportPrimitiveType::DataTypeRSProgramRaster
82    "ProgramStore",     // RSExportPrimitiveType::DataTypeRSProgramStore
83    "Font",     // RSExportPrimitiveType::DataTypeRSFont
84  };
85  unsigned TypeId = EPT->getType();
86
87  if (TypeId < (sizeof(PrimitiveTypeJavaNameMap) / sizeof(const char*))) {
88    return PrimitiveTypeJavaNameMap[ EPT->getType() ];
89  }
90
91  assert(false && "GetPrimitiveTypeName : Unknown primitive data type");
92  return NULL;
93}
94
95static const char *GetVectorTypeName(const RSExportVectorType *EVT) {
96  static const char *VectorTypeJavaNameMap[][3] = {
97    /* 0 */ { "Byte2",  "Byte3",    "Byte4" },
98    /* 1 */ { "Short2", "Short3",   "Short4" },
99    /* 2 */ { "Int2",   "Int3",     "Int4" },
100    /* 3 */ { "Long2",  "Long3",    "Long4" },
101    /* 4 */ { "Float2", "Float3",   "Float4" },
102  };
103
104  const char **BaseElement = NULL;
105
106  switch (EVT->getType()) {
107    case RSExportPrimitiveType::DataTypeSigned8:
108    case RSExportPrimitiveType::DataTypeBoolean: {
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::DataTypeSigned64:
123    case RSExportPrimitiveType::DataTypeUnsigned32: {
124      BaseElement = VectorTypeJavaNameMap[3];
125      break;
126    }
127    case RSExportPrimitiveType::DataTypeFloat32: {
128      BaseElement = VectorTypeJavaNameMap[4];
129      break;
130    }
131    default: {
132      assert(false && "RSReflection::genElementTypeName : Unsupported vector "
133                      "element data type");
134      break;
135    }
136  }
137
138  assert((EVT->getNumElement() > 1) &&
139         (EVT->getNumElement() <= 4) &&
140         "Number of element in vector type is invalid");
141
142  return BaseElement[EVT->getNumElement() - 2];
143}
144
145static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
146  static const char *MatrixTypeJavaNameMap[] = {
147    /* 2x2 */ "Matrix2f",
148    /* 3x3 */ "Matrix3f",
149    /* 4x4 */ "Matrix4f",
150  };
151  unsigned Dim = EMT->getDim();
152
153  if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char*)))
154    return MatrixTypeJavaNameMap[ EMT->getDim() - 2 ];
155
156  assert(false && "GetMatrixTypeName : Unsupported matrix dimension");
157  return NULL;
158}
159
160static const char *GetVectorAccessor(int Index) {
161  static const char *VectorAccessorMap[] = {
162    /* 0 */ "x",
163    /* 1 */ "y",
164    /* 2 */ "z",
165    /* 3 */ "w",
166  };
167
168  assert((Index >= 0) &&
169         (Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) &&
170         "Out-of-bound index to access vector member");
171
172  return VectorAccessorMap[Index];
173}
174
175static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) {
176  static const char *PrimitiveTypePackerAPINameMap[] = {
177    "",         // RSExportPrimitiveType::DataTypeFloat16
178    "addF32",   // RSExportPrimitiveType::DataTypeFloat32
179    "addF64",   // RSExportPrimitiveType::DataTypeFloat64
180    "addI8",    // RSExportPrimitiveType::DataTypeSigned8
181    "addI16",   // RSExportPrimitiveType::DataTypeSigned16
182    "addI32",   // RSExportPrimitiveType::DataTypeSigned32
183    "addI64",   // RSExportPrimitiveType::DataTypeSigned64
184    "addU8",    // RSExportPrimitiveType::DataTypeUnsigned8
185    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned16
186    "addU32",   // RSExportPrimitiveType::DataTypeUnsigned32
187    "addU64",   // RSExportPrimitiveType::DataTypeUnsigned64
188    "addBoolean",  // RSExportPrimitiveType::DataTypeBoolean
189
190    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned565
191    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned5551
192    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned4444
193
194    "addObj",   // RSExportPrimitiveType::DataTypeRSMatrix2x2
195    "addObj",   // RSExportPrimitiveType::DataTypeRSMatrix3x3
196    "addObj",   // RSExportPrimitiveType::DataTypeRSMatrix4x4
197
198    "addObj",   // RSExportPrimitiveType::DataTypeRSElement
199    "addObj",   // RSExportPrimitiveType::DataTypeRSType
200    "addObj",   // RSExportPrimitiveType::DataTypeRSAllocation
201    "addObj",   // RSExportPrimitiveType::DataTypeRSSampler
202    "addObj",   // RSExportPrimitiveType::DataTypeRSScript
203    "addObj",   // RSExportPrimitiveType::DataTypeRSMesh
204    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramFragment
205    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramVertex
206    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramRaster
207    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramStore
208    "addObj",   // RSExportPrimitiveType::DataTypeRSFont
209  };
210  unsigned TypeId = EPT->getType();
211
212  if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*)))
213    return PrimitiveTypePackerAPINameMap[ EPT->getType() ];
214
215  assert(false && "GetPackerAPIName : Unknown primitive data type");
216  return NULL;
217}
218
219static std::string GetTypeName(const RSExportType *ET) {
220  switch (ET->getClass()) {
221    case RSExportType::ExportClassPrimitive: {
222      return GetPrimitiveTypeName(
223                static_cast<const RSExportPrimitiveType*>(ET));
224    }
225    case RSExportType::ExportClassPointer: {
226      const RSExportType *PointeeType =
227          static_cast<const RSExportPointerType*>(ET)->getPointeeType();
228
229      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
230        return "Allocation";
231      else
232        return RS_TYPE_CLASS_NAME_PREFIX + PointeeType->getName();
233    }
234    case RSExportType::ExportClassVector: {
235      return GetVectorTypeName(static_cast<const RSExportVectorType*>(ET));
236    }
237    case RSExportType::ExportClassMatrix: {
238      return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET));
239    }
240    case RSExportType::ExportClassConstantArray: {
241      const RSExportConstantArrayType* CAT =
242          static_cast<const RSExportConstantArrayType*>(ET);
243      std::string ElementTypeName = GetTypeName(CAT->getElementType());
244      ElementTypeName.append("[]");
245      return ElementTypeName;
246    }
247    case RSExportType::ExportClassRecord: {
248      return RS_TYPE_CLASS_NAME_PREFIX + ET->getName() +
249                 "."RS_TYPE_ITEM_CLASS_NAME;
250    }
251    default: {
252      assert(false && "Unknown class of type");
253    }
254  }
255
256  return "";
257}
258
259static const char *GetBuiltinElementConstruct(const RSExportType *ET) {
260  if (ET->getClass() == RSExportType::ExportClassPrimitive) {
261    const RSExportPrimitiveType *EPT =
262        static_cast<const RSExportPrimitiveType*>(ET);
263    if (EPT->getKind() == RSExportPrimitiveType::DataKindUser) {
264      static const char *PrimitiveBuiltinElementConstructMap[] = {
265        NULL,   // RSExportPrimitiveType::DataTypeFloat16
266        "F32",  // RSExportPrimitiveType::DataTypeFloat32
267        "F64",  // RSExportPrimitiveType::DataTypeFloat64
268        "I8",   // RSExportPrimitiveType::DataTypeSigned8
269        NULL,   // RSExportPrimitiveType::DataTypeSigned16
270        "I32",  // RSExportPrimitiveType::DataTypeSigned32
271        "I64",  // RSExportPrimitiveType::DataTypeSigned64
272        "U8",   // RSExportPrimitiveType::DataTypeUnsigned8
273        NULL,   // RSExportPrimitiveType::DataTypeUnsigned16
274        "U32",  // RSExportPrimitiveType::DataTypeUnsigned32
275        NULL,   // RSExportPrimitiveType::DataTypeUnsigned64
276        "BOOLEAN",  // RSExportPrimitiveType::DataTypeBoolean
277
278        NULL,   // RSExportPrimitiveType::DataTypeUnsigned565
279        NULL,   // RSExportPrimitiveType::DataTypeUnsigned5551
280        NULL,   // RSExportPrimitiveType::DataTypeUnsigned4444
281
282        NULL,   // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix2x2
283        NULL,   // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix3x3
284        NULL,   // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix4x4
285
286        "ELEMENT",      // RSExportPrimitiveType::DataTypeRSElement
287        "TYPE",         // RSExportPrimitiveType::DataTypeRSType
288        "ALLOCATION",   // RSExportPrimitiveType::DataTypeRSAllocation
289        "SAMPLER",      // RSExportPrimitiveType::DataTypeRSSampler
290        "SCRIPT",       // RSExportPrimitiveType::DataTypeRSScript
291        "MESH",         // RSExportPrimitiveType::DataTypeRSMesh
292        "PROGRAM_FRAGMENT",  // RSExportPrimitiveType::DataTypeRSProgramFragment
293        "PROGRAM_VERTEX",    // RSExportPrimitiveType::DataTypeRSProgramVertex
294        "PROGRAM_RASTER",    // RSExportPrimitiveType::DataTypeRSProgramRaster
295        "PROGRAM_STORE",     // RSExportPrimitiveType::DataTypeRSProgramStore
296        "FONT",       // RSExportPrimitiveType::DataTypeRSFont
297      };
298      unsigned TypeId = EPT->getType();
299
300      if (TypeId <
301          (sizeof(PrimitiveBuiltinElementConstructMap) / sizeof(const char*)))
302        return PrimitiveBuiltinElementConstructMap[ EPT->getType() ];
303    } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelA) {
304      if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
305        return "A_8";
306    } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGB) {
307      if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned565)
308        return "RGB_565";
309      else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
310        return "RGB_888";
311    } else if (EPT->getKind() == RSExportPrimitiveType::DataKindPixelRGBA) {
312      if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned5551)
313        return "RGBA_5551";
314      else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned4444)
315        return "RGBA_4444";
316      else if (EPT->getType() == RSExportPrimitiveType::DataTypeUnsigned8)
317        return "RGBA_8888";
318    }
319  } else if (ET->getClass() == RSExportType::ExportClassVector) {
320    const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(ET);
321    if (EVT->getKind() == RSExportPrimitiveType::DataKindUser) {
322      if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
323        if (EVT->getNumElement() == 2)
324          return "F32_2";
325        else if (EVT->getNumElement() == 3)
326          return "F32_3";
327        else if (EVT->getNumElement() == 4)
328          return "F32_4";
329      } else if (EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
330        if (EVT->getNumElement() == 4)
331          return "U8_4";
332      }
333    }
334  } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
335    const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType *>(ET);
336    switch (EMT->getDim()) {
337      case 2: {
338        return "MATRIX_2X2";
339        break;
340      }
341      case 3: {
342        return "MATRIX_3X3";
343        break;
344      }
345      case 4: {
346        return "MATRIX_4X4";
347        break;
348      }
349      default: {
350        assert(false && "Unsupported dimension of matrix");
351      }
352    }
353  } else if (ET->getClass() == RSExportType::ExportClassPointer) {
354    // Treat pointer type variable as unsigned int
355    // TODO(zonr): this is target dependent
356    return "USER_I32";
357  }
358
359  return NULL;
360}
361
362static const char *GetElementDataKindName(RSExportPrimitiveType::DataKind DK) {
363  static const char *ElementDataKindNameMap[] = {
364    "Element.DataKind.USER",        // RSExportPrimitiveType::DataKindUser
365    "Element.DataKind.PIXEL_L",     // RSExportPrimitiveType::DataKindPixelL
366    "Element.DataKind.PIXEL_A",     // RSExportPrimitiveType::DataKindPixelA
367    "Element.DataKind.PIXEL_LA",    // RSExportPrimitiveType::DataKindPixelLA
368    "Element.DataKind.PIXEL_RGB",   // RSExportPrimitiveType::DataKindPixelRGB
369    "Element.DataKind.PIXEL_RGBA",  // RSExportPrimitiveType::DataKindPixelRGBA
370  };
371
372  if (static_cast<unsigned>(DK) <
373      (sizeof(ElementDataKindNameMap) / sizeof(const char*)))
374    return ElementDataKindNameMap[ DK ];
375  else
376    return NULL;
377}
378
379static const char *GetElementDataTypeName(RSExportPrimitiveType::DataType DT) {
380  static const char *ElementDataTypeNameMap[] = {
381    NULL,                           // RSExportPrimitiveType::DataTypeFloat16
382    "Element.DataType.FLOAT_32",    // RSExportPrimitiveType::DataTypeFloat32
383    "Element.DataType.FLOAT_64",    // RSExportPrimitiveType::DataTypeFloat64
384    "Element.DataType.SIGNED_8",    // RSExportPrimitiveType::DataTypeSigned8
385    "Element.DataType.SIGNED_16",   // RSExportPrimitiveType::DataTypeSigned16
386    "Element.DataType.SIGNED_32",   // RSExportPrimitiveType::DataTypeSigned32
387    "Element.DataType.SIGNED_64",   // RSExportPrimitiveType::DataTypeSigned64
388    "Element.DataType.UNSIGNED_8",  // RSExportPrimitiveType::DataTypeUnsigned8
389    "Element.DataType.UNSIGNED_16", // RSExportPrimitiveType::DataTypeUnsigned16
390    "Element.DataType.UNSIGNED_32", // RSExportPrimitiveType::DataTypeUnsigned32
391    NULL,                           // RSExportPrimitiveType::DataTypeUnsigned64
392    "Element.DataType.BOOLEAN",     // RSExportPrimitiveType::DataTypeBoolean
393
394    // RSExportPrimitiveType::DataTypeUnsigned565
395    "Element.DataType.UNSIGNED_5_6_5",
396    // RSExportPrimitiveType::DataTypeUnsigned5551
397    "Element.DataType.UNSIGNED_5_5_5_1",
398    // RSExportPrimitiveType::DataTypeUnsigned4444
399    "Element.DataType.UNSIGNED_4_4_4_4",
400
401    // DataTypeRSMatrix* must have been resolved in GetBuiltinElementConstruct()
402    NULL, // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix2x2
403    NULL, // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix3x3
404    NULL, // (Dummy) RSExportPrimitiveType::DataTypeRSMatrix4x4
405
406    "Element.DataType.RS_ELEMENT",  // RSExportPrimitiveType::DataTypeRSElement
407    "Element.DataType.RS_TYPE",     // RSExportPrimitiveType::DataTypeRSType
408      // RSExportPrimitiveType::DataTypeRSAllocation
409    "Element.DataType.RS_ALLOCATION",
410      // RSExportPrimitiveType::DataTypeRSSampler
411    "Element.DataType.RS_SAMPLER",
412      // RSExportPrimitiveType::DataTypeRSScript
413    "Element.DataType.RS_SCRIPT",
414      // RSExportPrimitiveType::DataTypeRSMesh
415    "Element.DataType.RS_MESH",
416      // RSExportPrimitiveType::DataTypeRSProgramFragment
417    "Element.DataType.RS_PROGRAM_FRAGMENT",
418      // RSExportPrimitiveType::DataTypeRSProgramVertex
419    "Element.DataType.RS_PROGRAM_VERTEX",
420      // RSExportPrimitiveType::DataTypeRSProgramRaster
421    "Element.DataType.RS_PROGRAM_RASTER",
422      // RSExportPrimitiveType::DataTypeRSProgramStore
423    "Element.DataType.RS_PROGRAM_STORE",
424      // RSExportPrimitiveType::DataTypeRSFont
425    "Element.DataType.RS_FONT",
426  };
427
428  if (static_cast<unsigned>(DT) <
429      (sizeof(ElementDataTypeNameMap) / sizeof(const char*)))
430    return ElementDataTypeNameMap[ DT ];
431  else
432    return NULL;
433}
434
435bool RSReflection::openScriptFile(Context &C,
436                                  const std::string &ClassName,
437                                  std::string &ErrorMsg) {
438  if (!C.mUseStdout) {
439    C.mOF.clear();
440    std::string _path = RSSlangReflectUtils::ComputePackagedPath(
441        mRSContext->getReflectJavaPathName().c_str(),
442        C.getPackageName().c_str());
443
444    RSSlangReflectUtils::mkdir_p(_path.c_str());
445    C.mOF.open((_path + "/" + ClassName + ".java").c_str());
446    if (!C.mOF.good()) {
447      ErrorMsg = "failed to open file '" + _path + "/" + ClassName
448          + ".java' for write";
449
450      return false;
451    }
452  }
453  return true;
454}
455
456/********************** Methods to generate script class **********************/
457bool RSReflection::genScriptClass(Context &C,
458                                  const std::string &ClassName,
459                                  std::string &ErrorMsg) {
460  // Open the file
461  if (!openScriptFile(C, ClassName, ErrorMsg)) {
462    return false;
463  }
464
465  if (!C.startClass(Context::AM_Public,
466                    false,
467                    ClassName,
468                    RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
469                    ErrorMsg))
470    return false;
471
472  genScriptClassConstructor(C);
473
474  // Reflect export variable
475  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
476           E = mRSContext->export_vars_end();
477       I != E;
478       I++)
479    genExportVariable(C, *I);
480
481  // Reflect export function
482  for (RSContext::const_export_func_iterator
483           I = mRSContext->export_funcs_begin(),
484           E = mRSContext->export_funcs_end();
485       I != E; I++)
486    genExportFunction(C, *I);
487
488  C.endClass();
489
490  return true;
491}
492
493void RSReflection::genScriptClassConstructor(Context &C) {
494  C.indent() << "// Constructor" << std::endl;
495  C.startFunction(Context::AM_Public,
496                  false,
497                  NULL,
498                  C.getClassName(),
499                  4,
500                  "RenderScript",
501                  "rs",
502                  "Resources",
503                  "resources",
504                  "int",
505                  "id",
506                  "boolean",
507                  "isRoot");
508  // Call constructor of super class
509  C.indent() << "super(rs, resources, id, isRoot);" << std::endl;
510
511  // If an exported variable has initial value, reflect it
512
513  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
514           E = mRSContext->export_vars_end();
515       I != E;
516       I++) {
517    const RSExportVar *EV = *I;
518    if (!EV->getInit().isUninit())
519      genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
520  }
521
522  C.endFunction();
523  return;
524}
525
526void RSReflection::genInitBoolExportVariable(Context &C,
527                                             const std::string &VarName,
528                                             const clang::APValue &Val) {
529  assert(!Val.isUninit() && "Not a valid initializer");
530
531  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
532  assert((Val.getKind() == clang::APValue::Int) &&
533         "Bool type has wrong initial APValue");
534
535  C.out() << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
536          << ";" << std::endl;
537
538  return;
539}
540
541void RSReflection::genInitPrimitiveExportVariable(Context &C,
542                                                  const std::string &VarName,
543                                                  const clang::APValue &Val) {
544  assert(!Val.isUninit() && "Not a valid initializer");
545
546  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
547  switch (Val.getKind()) {
548    case clang::APValue::Int: {
549      C.out() << Val.getInt().getSExtValue();
550      break;
551    }
552    case clang::APValue::Float: {
553      llvm::APFloat apf = Val.getFloat();
554      if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
555        C.out() << apf.convertToFloat() << "f";
556      } else {
557        C.out() << apf.convertToDouble();
558      }
559      break;
560    }
561
562    case clang::APValue::ComplexInt:
563    case clang::APValue::ComplexFloat:
564    case clang::APValue::LValue:
565    case clang::APValue::Vector: {
566      assert(false && "Primitive type cannot have such kind of initializer");
567      break;
568    }
569    default: {
570      assert(false && "Unknown kind of initializer");
571    }
572  }
573  C.out() << ";" << std::endl;
574
575  return;
576}
577
578void RSReflection::genInitExportVariable(Context &C,
579                                         const RSExportType *ET,
580                                         const std::string &VarName,
581                                         const clang::APValue &Val) {
582  assert(!Val.isUninit() && "Not a valid initializer");
583
584  switch (ET->getClass()) {
585    case RSExportType::ExportClassPrimitive: {
586      const RSExportPrimitiveType *EPT =
587          static_cast<const RSExportPrimitiveType*>(ET);
588      if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) {
589        genInitBoolExportVariable(C, VarName, Val);
590      } else {
591        genInitPrimitiveExportVariable(C, VarName, Val);
592      }
593      break;
594    }
595    case RSExportType::ExportClassPointer: {
596      if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
597        std::cout << "Initializer which is non-NULL to pointer type variable "
598                     "will be ignored" << std::endl;
599      break;
600    }
601    case RSExportType::ExportClassVector: {
602      const RSExportVectorType *EVT =
603          static_cast<const RSExportVectorType*>(ET);
604      switch (Val.getKind()) {
605        case clang::APValue::Int:
606        case clang::APValue::Float: {
607          for (unsigned i = 0; i < EVT->getNumElement(); i++) {
608            std::string Name =  VarName + "." + GetVectorAccessor(i);
609            genInitPrimitiveExportVariable(C, Name, Val);
610          }
611          break;
612        }
613        case clang::APValue::Vector: {
614          C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "
615                     << GetVectorTypeName(EVT) << "();" << std::endl;
616
617          unsigned NumElements =
618              std::min(static_cast<unsigned>(EVT->getNumElement()),
619                       Val.getVectorLength());
620          for (unsigned i = 0; i < NumElements; i++) {
621            const clang::APValue &ElementVal = Val.getVectorElt(i);
622            std::string Name = VarName + "." + GetVectorAccessor(i);
623            genInitPrimitiveExportVariable(C, Name, ElementVal);
624          }
625          break;
626        }
627        case clang::APValue::Uninitialized:
628        case clang::APValue::ComplexInt:
629        case clang::APValue::ComplexFloat:
630        case clang::APValue::LValue: {
631          assert(false && "Unexpected type of value of initializer.");
632        }
633      }
634      break;
635    }
636    // TODO(zonr): Resolving initializer of a record (and matrix) type variable
637    // is complex. It cannot obtain by just simply evaluating the initializer
638    // expression.
639    case RSExportType::ExportClassMatrix:
640    case RSExportType::ExportClassConstantArray:
641    case RSExportType::ExportClassRecord: {
642#if 0
643      unsigned InitIndex = 0;
644      const RSExportRecordType *ERT =
645          static_cast<const RSExportRecordType*>(ET);
646
647      assert((Val.getKind() == clang::APValue::Vector) && "Unexpected type of "
648             "initializer for record type variable");
649
650      C.indent() << RS_EXPORT_VAR_PREFIX << VarName
651                 << " = new "RS_TYPE_CLASS_NAME_PREFIX << ERT->getName()
652                 <<  "."RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
653
654      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
655               E = ERT->fields_end();
656           I != E;
657           I++) {
658        const RSExportRecordType::Field *F = *I;
659        std::string FieldName = VarName + "." + F->getName();
660
661        if (InitIndex > Val.getVectorLength())
662          break;
663
664        genInitPrimitiveExportVariable(C,
665                                       FieldName,
666                                       Val.getVectorElt(InitIndex++));
667      }
668#endif
669      assert(false && "Unsupported initializer for record/matrix/constant "
670                      "array type variable currently");
671      break;
672    }
673    default: {
674      assert(false && "Unknown class of type");
675    }
676  }
677  return;
678}
679
680void RSReflection::genExportVariable(Context &C, const RSExportVar *EV) {
681  const RSExportType *ET = EV->getType();
682
683  C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX
684             << EV->getName() << " = " << C.getNextExportVarSlot() << ";"
685             << std::endl;
686
687  switch (ET->getClass()) {
688    case RSExportType::ExportClassPrimitive: {
689      genPrimitiveTypeExportVariable(C, EV);
690      break;
691    }
692    case RSExportType::ExportClassPointer: {
693      genPointerTypeExportVariable(C, EV);
694      break;
695    }
696    case RSExportType::ExportClassVector: {
697      genVectorTypeExportVariable(C, EV);
698      break;
699    }
700    case RSExportType::ExportClassMatrix: {
701      genMatrixTypeExportVariable(C, EV);
702      break;
703    }
704    case RSExportType::ExportClassConstantArray: {
705      genConstantArrayTypeExportVariable(C, EV);
706      break;
707    }
708    case RSExportType::ExportClassRecord: {
709      genRecordTypeExportVariable(C, EV);
710      break;
711    }
712    default: {
713      assert(false && "Unknown class of type");
714    }
715  }
716
717  return;
718}
719
720void RSReflection::genExportFunction(Context &C, const RSExportFunc *EF) {
721  C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX
722             << EF->getName() << " = " << C.getNextExportFuncSlot() << ";"
723             << std::endl;
724
725  // invoke_*()
726  Context::ArgTy Args;
727
728  if (EF->hasParam()) {
729    for (RSExportFunc::const_param_iterator I = EF->params_begin(),
730             E = EF->params_end();
731         I != E;
732         I++) {
733      Args.push_back(std::make_pair(GetTypeName((*I)->getType()),
734                                    (*I)->getName()));
735    }
736  }
737
738  C.startFunction(Context::AM_Public,
739                  false,
740                  "void",
741                  "invoke_" + EF->getName(),
742                  Args);
743
744  if (!EF->hasParam()) {
745    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");"
746               << std::endl;
747  } else {
748    const RSExportRecordType *ERT = EF->getParamPacketType();
749    std::string FieldPackerName = EF->getName() + "_fp";
750
751    if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
752      genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
753
754    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", "
755               << FieldPackerName << ");" << std::endl;
756  }
757
758  C.endFunction();
759  return;
760}
761
762void RSReflection::genPrimitiveTypeExportVariable(Context &C,
763                                                  const RSExportVar *EV) {
764  assert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive) &&
765         "Variable should be type of primitive here");
766
767  const RSExportPrimitiveType *EPT =
768      static_cast<const RSExportPrimitiveType*>(EV->getType());
769  const char *TypeName = GetPrimitiveTypeName(EPT);
770
771  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
772             << EV->getName() << ";" << std::endl;
773
774  // set_*()
775  if (!EV->isConst()) {
776    C.startFunction(Context::AM_Public,
777                    false,
778                    "void",
779                    "set_" + EV->getName(),
780                    1,
781                    TypeName,
782                    "v");
783    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
784
785    if (EPT->isRSObjectType())
786      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
787                 << ", (v == null) ? 0 : v.getID());" << std::endl;
788    else
789      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
790                 << ", v);" << std::endl;
791
792    C.endFunction();
793  }
794
795  genGetExportVariable(C, TypeName, EV->getName());
796
797  return;
798}
799
800void RSReflection::genPointerTypeExportVariable(Context &C,
801                                                const RSExportVar *EV) {
802  const RSExportType *ET = EV->getType();
803  const RSExportType *PointeeType;
804  std::string TypeName;
805
806  assert((ET->getClass() == RSExportType::ExportClassPointer) &&
807         "Variable should be type of pointer here");
808
809  PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
810  TypeName = GetTypeName(ET);
811
812  // bind_*()
813  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
814             << EV->getName() << ";" << std::endl;
815
816  C.startFunction(Context::AM_Public,
817                  false,
818                  "void",
819                  "bind_" + EV->getName(),
820                  1,
821                  TypeName.c_str(),
822                  "v");
823
824  C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
825  C.indent() << "if (v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX
826             << EV->getName() << ");" << std::endl;
827
828  if (PointeeType->getClass() == RSExportType::ExportClassRecord)
829    C.indent() << "else bindAllocation(v.getAllocation(), "
830        RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ");"
831               << std::endl;
832  else
833    C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX
834               << EV->getName() << ");" << std::endl;
835
836  C.endFunction();
837
838  genGetExportVariable(C, TypeName, EV->getName());
839
840  return;
841}
842
843void RSReflection::genVectorTypeExportVariable(Context &C,
844                                               const RSExportVar *EV) {
845  assert((EV->getType()->getClass() == RSExportType::ExportClassVector) &&
846         "Variable should be type of vector here");
847
848  const RSExportVectorType *EVT =
849      static_cast<const RSExportVectorType*>(EV->getType());
850  const char *TypeName = GetVectorTypeName(EVT);
851  const char *FieldPackerName = "fp";
852
853  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
854             << EV->getName() << ";" << std::endl;
855
856  // set_*()
857  if (!EV->isConst()) {
858    C.startFunction(Context::AM_Public,
859                    false,
860                    "void",
861                    "set_" + EV->getName(),
862                    1,
863                    TypeName,
864                    "v");
865    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
866
867    if (genCreateFieldPacker(C, EVT, FieldPackerName))
868      genPackVarOfType(C, EVT, "v", FieldPackerName);
869    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
870               << FieldPackerName << ");" << std::endl;
871
872    C.endFunction();
873  }
874
875  genGetExportVariable(C, TypeName, EV->getName());
876  return;
877}
878
879void RSReflection::genMatrixTypeExportVariable(Context &C,
880                                               const RSExportVar *EV) {
881  assert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) &&
882         "Variable should be type of matrix here");
883
884  const RSExportMatrixType *EMT =
885      static_cast<const RSExportMatrixType*>(EV->getType());
886  const char *TypeName = GetMatrixTypeName(EMT);
887  const char *FieldPackerName = "fp";
888
889  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
890             << EV->getName() << ";" << std::endl;
891
892  // set_*()
893  if (!EV->isConst()) {
894    C.startFunction(Context::AM_Public,
895                    false,
896                    "void",
897                    "set_" + EV->getName(),
898                    1,
899                    TypeName, "v");
900    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
901
902    if (genCreateFieldPacker(C, EMT, FieldPackerName))
903      genPackVarOfType(C, EMT, "v", FieldPackerName);
904    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
905               << FieldPackerName << ");" << std::endl;
906
907    C.endFunction();
908  }
909
910  genGetExportVariable(C, TypeName, EV->getName());
911  return;
912}
913
914void RSReflection::genConstantArrayTypeExportVariable(Context &C,
915                                                      const RSExportVar *EV) {
916  assert((EV->getType()->getClass() == RSExportType::ExportClassConstantArray)&&
917         "Variable should be type of constant array here");
918
919  const RSExportConstantArrayType *ECAT =
920      static_cast<const RSExportConstantArrayType*>(EV->getType());
921  std::string TypeName = GetTypeName(ECAT);
922  const char *FieldPackerName = "fp";
923
924  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
925             << EV->getName() << ";" << std::endl;
926
927  // set_*()
928  if (!EV->isConst()) {
929    C.startFunction(Context::AM_Public,
930                    false,
931                    "void",
932                    "set_" + EV->getName(),
933                    1,
934                    TypeName.c_str(), "v");
935    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
936
937    if (genCreateFieldPacker(C, ECAT, FieldPackerName))
938      genPackVarOfType(C, ECAT, "v", FieldPackerName);
939    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName() << ", "
940               << FieldPackerName << ");" << std::endl;
941
942    C.endFunction();
943  }
944
945  genGetExportVariable(C, TypeName, EV->getName());
946  return;
947}
948
949void RSReflection::genRecordTypeExportVariable(Context &C,
950                                               const RSExportVar *EV) {
951  assert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
952         "Variable should be type of struct here");
953
954  const RSExportRecordType *ERT =
955      static_cast<const RSExportRecordType*>(EV->getType());
956  std::string TypeName =
957      RS_TYPE_CLASS_NAME_PREFIX + ERT->getName() + "."RS_TYPE_ITEM_CLASS_NAME;
958  const char *FieldPackerName = "fp";
959
960  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
961             << EV->getName() << ";" << std::endl;
962
963  // set_*()
964  if (!EV->isConst()) {
965    C.startFunction(Context::AM_Public,
966                    false,
967                    "void",
968                    "set_" + EV->getName(),
969                    1,
970                    TypeName.c_str(),
971                    "v");
972    C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = v;" << std::endl;
973
974    if (genCreateFieldPacker(C, ERT, FieldPackerName))
975      genPackVarOfType(C, ERT, "v", FieldPackerName);
976    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << EV->getName()
977               << ", " << FieldPackerName << ");" << std::endl;
978
979    C.endFunction();
980  }
981
982  genGetExportVariable(C, TypeName.c_str(), EV->getName());
983  return;
984}
985
986void RSReflection::genGetExportVariable(Context &C,
987                                        const std::string &TypeName,
988                                        const std::string &VarName) {
989  C.startFunction(Context::AM_Public,
990                  false,
991                  TypeName.c_str(),
992                  "get_" + VarName,
993                  0);
994
995  C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << std::endl;
996
997  C.endFunction();
998  return;
999}
1000
1001/******************* Methods to generate script class /end *******************/
1002
1003bool RSReflection::genCreateFieldPacker(Context &C,
1004                                        const RSExportType *ET,
1005                                        const char *FieldPackerName) {
1006  size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
1007  if (AllocSize > 0)
1008    C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
1009               << AllocSize << ");" << std::endl;
1010  else
1011    return false;
1012  return true;
1013}
1014
1015void RSReflection::genPackVarOfType(Context &C,
1016                                    const RSExportType *ET,
1017                                    const char *VarName,
1018                                    const char *FieldPackerName) {
1019  switch (ET->getClass()) {
1020    case RSExportType::ExportClassPrimitive:
1021    case RSExportType::ExportClassVector: {
1022      C.indent() << FieldPackerName << "."
1023                 << GetPackerAPIName(
1024                     static_cast<const RSExportPrimitiveType*>(ET))
1025                 << "(" << VarName << ");" << std::endl;
1026      break;
1027    }
1028    case RSExportType::ExportClassPointer: {
1029      // Must reflect as type Allocation in Java
1030      const RSExportType *PointeeType =
1031          static_cast<const RSExportPointerType*>(ET)->getPointeeType();
1032
1033      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
1034        C.indent() << FieldPackerName << ".addI32(" << VarName
1035                   << ".getPtr());" << std::endl;
1036      else
1037        C.indent() << FieldPackerName << ".addI32(" << VarName
1038                   << ".getAllocation().getPtr());" << std::endl;
1039      break;
1040    }
1041    case RSExportType::ExportClassMatrix: {
1042      C.indent() << FieldPackerName << ".addObj(" << VarName << ");"
1043                 << std::endl;
1044      break;
1045    }
1046    case RSExportType::ExportClassConstantArray: {
1047      const RSExportConstantArrayType *ECAT =
1048          static_cast<const RSExportConstantArrayType *>(ET);
1049      C.indent() << "for (int ct = 0; ct < " << ECAT->getSize() << "; ct++)";
1050      C.startBlock();
1051
1052      std::string ElementVarName(VarName);
1053      ElementVarName.append("[ct]");
1054      genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
1055                       FieldPackerName);
1056
1057      C.endBlock();
1058      break;
1059    }
1060    case RSExportType::ExportClassRecord: {
1061      const RSExportRecordType *ERT =
1062          static_cast<const RSExportRecordType*>(ET);
1063      // Relative pos from now on in field packer
1064      unsigned Pos = 0;
1065
1066      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1067               E = ERT->fields_end();
1068           I != E;
1069           I++) {
1070        const RSExportRecordType::Field *F = *I;
1071        std::string FieldName;
1072        size_t FieldOffset = F->getOffsetInParent();
1073        size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1074        size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1075
1076        if (VarName != NULL)
1077          FieldName = VarName + ("." + F->getName());
1078        else
1079          FieldName = F->getName();
1080
1081        if (FieldOffset > Pos)
1082          C.indent() << FieldPackerName << ".skip("
1083                     << (FieldOffset - Pos) << ");" << std::endl;
1084
1085        genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);
1086
1087        // There is padding in the field type
1088        if (FieldAllocSize > FieldStoreSize)
1089            C.indent() << FieldPackerName << ".skip("
1090                       << (FieldAllocSize - FieldStoreSize)
1091                       << ");" << std::endl;
1092
1093          Pos = FieldOffset + FieldAllocSize;
1094      }
1095
1096      // There maybe some padding after the struct
1097      size_t Padding = RSExportType::GetTypeAllocSize(ERT) - Pos;
1098      if (Padding > 0)
1099        C.indent() << FieldPackerName << ".skip(" << Padding << ");"
1100                   << std::endl;
1101      break;
1102    }
1103    default: {
1104      assert(false && "Unknown class of type");
1105    }
1106  }
1107
1108  return;
1109}
1110
1111void RSReflection::genAllocateVarOfType(Context &C,
1112                                        const RSExportType *T,
1113                                        const std::string &VarName) {
1114  switch (T->getClass()) {
1115    case RSExportType::ExportClassPrimitive: {
1116      // Primitive type like int in Java has its own storage once it's declared.
1117      //
1118      // FIXME: Should we allocate storage for RS object?
1119      // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType())
1120      //  C.indent() << VarName << " = new " << GetTypeName(T) << "();"
1121      //             << std::endl;
1122      break;
1123    }
1124    case RSExportType::ExportClassPointer: {
1125      // Pointer type is an instance of Allocation or a TypeClass whose value is
1126      // expected to be assigned by programmer later in Java program. Therefore
1127      // we don't reflect things like [VarName] = new Allocation();
1128      C.indent() << VarName << " = null;" << std::endl;
1129      break;
1130    }
1131    case RSExportType::ExportClassConstantArray: {
1132      const RSExportConstantArrayType *ECAT =
1133          static_cast<const RSExportConstantArrayType *>(T);
1134      const RSExportType *ElementType = ECAT->getElementType();
1135
1136      // Primitive type element doesn't need allocation code.
1137      if (ElementType->getClass() != RSExportType::ExportClassPrimitive) {
1138        C.indent() << VarName << " = new " << GetTypeName(ElementType)
1139                   << "[" << ECAT->getSize() << "];" << std::endl;
1140
1141        C.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() << "; "
1142                            "$ct++)";
1143        C.startBlock();
1144
1145        std::string ElementVarName(VarName);
1146        ElementVarName.append("[$ct]");
1147        genAllocateVarOfType(C, ElementType, ElementVarName);
1148
1149        C.endBlock();
1150      }
1151      break;
1152    }
1153    case RSExportType::ExportClassVector:
1154    case RSExportType::ExportClassMatrix:
1155    case RSExportType::ExportClassRecord: {
1156      C.indent() << VarName << " = new " << GetTypeName(T) << "();"
1157                 << std::endl;
1158      break;
1159    }
1160  }
1161  return;
1162}
1163
1164void RSReflection::genNewItemBufferIfNull(Context &C, const char *Index) {
1165  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) "
1166                  RS_TYPE_ITEM_BUFFER_NAME" = "
1167                    "new "RS_TYPE_ITEM_CLASS_NAME"[mType.getX() /* count */];"
1168             << std::endl;
1169  if (Index != NULL)
1170    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] == null) "
1171                    RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = "
1172                      "new "RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
1173  return;
1174}
1175
1176void RSReflection::genNewItemBufferPackerIfNull(Context &C) {
1177  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_PACKER_NAME" == null) "
1178                  RS_TYPE_ITEM_BUFFER_PACKER_NAME" = "
1179                    "new FieldPacker("
1180                      RS_TYPE_ITEM_CLASS_NAME".sizeof * mType.getX()/* count */"
1181                    ");" << std::endl;
1182  return;
1183}
1184
1185/********************** Methods to generate type class  **********************/
1186bool RSReflection::genTypeClass(Context &C,
1187                                const RSExportRecordType *ERT,
1188                                std::string &ErrorMsg) {
1189  std::string ClassName = RS_TYPE_CLASS_NAME_PREFIX + ERT->getName();
1190
1191  // Open the file
1192  if (!openScriptFile(C, ClassName, ErrorMsg)) {
1193    return false;
1194  }
1195
1196  if (!C.startClass(Context::AM_Public,
1197                    false,
1198                    ClassName,
1199                    RS_TYPE_CLASS_SUPER_CLASS_NAME,
1200                    ErrorMsg))
1201    return false;
1202
1203  genTypeItemClass(C, ERT);
1204
1205  // Declare item buffer and item buffer packer
1206  C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[]"
1207      ";" << std::endl;
1208  C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";"
1209             << std::endl;
1210
1211  genTypeClassConstructor(C, ERT);
1212  genTypeClassCopyToArray(C, ERT);
1213  genTypeClassItemSetter(C, ERT);
1214  genTypeClassItemGetter(C, ERT);
1215  genTypeClassComponentSetter(C, ERT);
1216  genTypeClassComponentGetter(C, ERT);
1217  genTypeClassCopyAll(C, ERT);
1218
1219  C.endClass();
1220
1221  C.resetFieldIndex();
1222  C.clearFieldIndexMap();
1223
1224  return true;
1225}
1226
1227void RSReflection::genTypeItemClass(Context &C, const RSExportRecordType *ERT) {
1228  C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
1229  C.startBlock();
1230
1231  C.indent() << "public static final int sizeof = "
1232             << RSExportType::GetTypeAllocSize(ERT) << ";" << std::endl;
1233
1234  // Member elements
1235  C.out() << std::endl;
1236  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1237           FE = ERT->fields_end();
1238       FI != FE;
1239       FI++) {
1240    C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
1241               << ";" << std::endl;
1242  }
1243
1244  // Constructor
1245  C.out() << std::endl;
1246  C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
1247  C.startBlock();
1248
1249  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1250           FE = ERT->fields_end();
1251       FI != FE;
1252       FI++) {
1253    const RSExportRecordType::Field *F = *FI;
1254    genAllocateVarOfType(C, F->getType(), F->getName());
1255  }
1256
1257  // end Constructor
1258  C.endBlock();
1259
1260  // end Item class
1261  C.endBlock();
1262
1263  return;
1264}
1265
1266void RSReflection::genTypeClassConstructor(Context &C,
1267                                           const RSExportRecordType *ERT) {
1268  const char *RenderScriptVar = "rs";
1269
1270  C.startFunction(Context::AM_Public,
1271                  true,
1272                  "Element",
1273                  "createElement",
1274                  1,
1275                  "RenderScript",
1276                  RenderScriptVar);
1277  genBuildElement(C, ERT, RenderScriptVar);
1278  C.endFunction();
1279
1280  C.startFunction(Context::AM_Public,
1281                  false,
1282                  NULL,
1283                  C.getClassName(),
1284                  2,
1285                  "RenderScript",
1286                  RenderScriptVar,
1287                  "int",
1288                  "count");
1289
1290  C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl;
1291  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl;
1292  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
1293             << std::endl;
1294  // Call init() in super class
1295  C.indent() << "init(" << RenderScriptVar << ", count);" << std::endl;
1296  C.endFunction();
1297
1298  return;
1299}
1300
1301void RSReflection::genTypeClassCopyToArray(Context &C,
1302                                           const RSExportRecordType *ERT) {
1303  C.startFunction(Context::AM_Private,
1304                  false,
1305                  "void",
1306                  "copyToArray",
1307                  2,
1308                  RS_TYPE_ITEM_CLASS_NAME,
1309                  "i",
1310                  "int",
1311                  "index");
1312
1313  genNewItemBufferPackerIfNull(C);
1314  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1315                ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);"
1316             << std::endl;
1317
1318  genPackVarOfType(C, ERT, "i", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1319
1320  C.endFunction();
1321  return;
1322}
1323
1324void RSReflection::genTypeClassItemSetter(Context &C,
1325                                          const RSExportRecordType *ERT) {
1326  C.startFunction(Context::AM_Public,
1327                  false,
1328                  "void",
1329                  "set",
1330                  3,
1331                  RS_TYPE_ITEM_CLASS_NAME,
1332                  "i",
1333                  "int",
1334                  "index",
1335                  "boolean",
1336                  "copyNow");
1337  genNewItemBufferIfNull(C, NULL);
1338  C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << std::endl;
1339
1340  C.indent() << "if (copyNow) ";
1341  C.startBlock();
1342
1343  C.indent() << "copyToArray(i, index);" << std::endl;
1344  C.indent() << "mAllocation.subData1D(index, 1, "
1345                  RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());" << std::endl;
1346
1347  // End of if (copyNow)
1348  C.endBlock();
1349
1350  C.endFunction();
1351  return;
1352}
1353
1354void RSReflection::genTypeClassItemGetter(Context &C,
1355                                          const RSExportRecordType *ERT) {
1356  C.startFunction(Context::AM_Public,
1357                  false,
1358                  RS_TYPE_ITEM_CLASS_NAME,
1359                  "get",
1360                  1,
1361                  "int",
1362                  "index");
1363  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;"
1364             << std::endl;
1365  C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index];" << std::endl;
1366  C.endFunction();
1367  return;
1368}
1369
1370void RSReflection::genTypeClassComponentSetter(Context &C,
1371                                               const RSExportRecordType *ERT) {
1372  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1373           FE = ERT->fields_end();
1374       FI != FE;
1375       FI++) {
1376    const RSExportRecordType::Field *F = *FI;
1377    size_t FieldOffset = F->getOffsetInParent();
1378    size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1379    unsigned FieldIndex = C.getFieldIndex(F);
1380
1381    C.startFunction(Context::AM_Public,
1382                    false,
1383                    "void",
1384                    "set_" + F->getName(), 3,
1385                    "int",
1386                    "index",
1387                    GetTypeName(F->getType()).c_str(),
1388                    "v",
1389                    "boolean",
1390                    "copyNow");
1391    genNewItemBufferPackerIfNull(C);
1392    genNewItemBufferIfNull(C, "index");
1393    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
1394               << " = v;" << std::endl;
1395
1396    C.indent() << "if (copyNow) ";
1397    C.startBlock();
1398
1399    if (FieldOffset > 0)
1400      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1401                    ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof + "
1402                 << FieldOffset << ");" << std::endl;
1403    else
1404      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
1405                    ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);"
1406                 << std::endl;
1407    genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);
1408
1409    C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");"
1410               << std::endl;
1411    genPackVarOfType(C, F->getType(), "v", "fp");
1412    C.indent() << "mAllocation.subElementData(index, " << FieldIndex << ", fp);"
1413               << std::endl;
1414
1415    // End of if (copyNow)
1416    C.endBlock();
1417
1418    C.endFunction();
1419  }
1420  return;
1421}
1422
1423void RSReflection::genTypeClassComponentGetter(Context &C,
1424                                               const RSExportRecordType *ERT) {
1425  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
1426           FE = ERT->fields_end();
1427       FI != FE;
1428       FI++) {
1429    const RSExportRecordType::Field *F = *FI;
1430    C.startFunction(Context::AM_Public,
1431                    false,
1432                    GetTypeName(F->getType()).c_str(),
1433                    "get_" + F->getName(),
1434                    1,
1435                    "int",
1436                    "index");
1437    C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
1438               << ";" << std::endl;
1439    C.endFunction();
1440  }
1441  return;
1442}
1443
1444void RSReflection::genTypeClassCopyAll(Context &C,
1445                                       const RSExportRecordType *ERT) {
1446  C.startFunction(Context::AM_Public, false, "void", "copyAll", 0);
1447
1448  C.indent() << "for (int ct = 0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++)"
1449                  " copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);"
1450             << std::endl;
1451  C.indent() << "mAllocation.data("RS_TYPE_ITEM_BUFFER_PACKER_NAME".getData());"
1452             << std::endl;
1453
1454  C.endFunction();
1455  return;
1456}
1457
1458/******************** Methods to generate type class /end ********************/
1459
1460/********** Methods to create Element in Java of given record type ***********/
1461void RSReflection::genBuildElement(Context &C, const RSExportRecordType *ERT,
1462                                   const char *RenderScriptVar) {
1463  const char *ElementBuilderName = "eb";
1464
1465  // Create element builder
1466  //    C.startBlock(true);
1467
1468  C.indent() << "Element.Builder " << ElementBuilderName << " = "
1469      "new Element.Builder(" << RenderScriptVar << ");" << std::endl;
1470
1471  // eb.add(...)
1472  genAddElementToElementBuilder(C,
1473                                ERT,
1474                                "",
1475                                ElementBuilderName,
1476                                RenderScriptVar);
1477
1478  C.indent() << "return " << ElementBuilderName << ".create();" << std::endl;
1479
1480  //   C.endBlock();
1481  return;
1482}
1483
1484#define EB_ADD(x)                                                   \
1485  C.indent() << ElementBuilderName                                  \
1486             << ".add(Element." << x << ", \"" << VarName << "\");" \
1487             << std::endl;                                          \
1488  C.incFieldIndex()
1489
1490void RSReflection::genAddElementToElementBuilder(Context &C,
1491                                                 const RSExportType *ET,
1492                                                 const std::string &VarName,
1493                                                 const char *ElementBuilderName,
1494                                                 const char *RenderScriptVar) {
1495  const char *ElementConstruct = GetBuiltinElementConstruct(ET);
1496
1497  if (ElementConstruct != NULL) {
1498    EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
1499  } else {
1500    if ((ET->getClass() == RSExportType::ExportClassPrimitive) ||
1501        (ET->getClass() == RSExportType::ExportClassVector)) {
1502      const RSExportPrimitiveType *EPT =
1503          static_cast<const RSExportPrimitiveType*>(ET);
1504      const char *DataKindName = GetElementDataKindName(EPT->getKind());
1505      const char *DataTypeName = GetElementDataTypeName(EPT->getType());
1506      int Size = (ET->getClass() == RSExportType::ExportClassVector) ?
1507          static_cast<const RSExportVectorType*>(ET)->getNumElement() :
1508          1;
1509
1510      switch (EPT->getKind()) {
1511        case RSExportPrimitiveType::DataKindPixelL:
1512        case RSExportPrimitiveType::DataKindPixelA:
1513        case RSExportPrimitiveType::DataKindPixelLA:
1514        case RSExportPrimitiveType::DataKindPixelRGB:
1515        case RSExportPrimitiveType::DataKindPixelRGBA: {
1516          // Element.createPixel()
1517          EB_ADD("createPixel(" << RenderScriptVar << ", "
1518                                << DataTypeName << ", "
1519                                << DataKindName << ")");
1520          break;
1521        }
1522        case RSExportPrimitiveType::DataKindUser:
1523        default: {
1524          if (EPT->getClass() == RSExportType::ExportClassPrimitive) {
1525            // Element.createUser()
1526            EB_ADD("createUser(" << RenderScriptVar << ", "
1527                                 << DataTypeName << ")");
1528          } else {
1529            assert((ET->getClass() == RSExportType::ExportClassVector) &&
1530                   "Unexpected type.");
1531            EB_ADD("createVector(" << RenderScriptVar << ", "
1532                                   << DataTypeName << ", "
1533                                   << Size << ")");
1534          }
1535          break;
1536        }
1537      }
1538#ifndef NDEBUG
1539    } else if (ET->getClass() == RSExportType::ExportClassPointer) {
1540      // Pointer type variable should be resolved in
1541      // GetBuiltinElementConstruct()
1542      assert(false && "??");
1543    } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
1544      // Matrix type variable should be resolved
1545      // in GetBuiltinElementConstruct()
1546      assert(false && "??");
1547#endif
1548    } else if (ET->getClass() == RSExportType::ExportClassConstantArray) {
1549      const RSExportConstantArrayType *ECAT =
1550          static_cast<const RSExportConstantArrayType *>(ET);
1551      C.indent() << "for (int ct = 0; ct < " << ECAT->getSize() << "; ct++)";
1552      C.startBlock();
1553
1554      std::string ElementVarName(VarName);
1555      ElementVarName.append("[\" + ct + \"]");
1556      genAddElementToElementBuilder(C,
1557                                    ECAT->getElementType(),
1558                                    ElementVarName,
1559                                    ElementBuilderName,
1560                                    RenderScriptVar);
1561
1562      C.endBlock();
1563    } else if (ET->getClass() == RSExportType::ExportClassRecord) {
1564      // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
1565      //
1566      // TODO(zonr): Generalize these two function such that there's no
1567      //             duplicated codes.
1568      const RSExportRecordType *ERT =
1569          static_cast<const RSExportRecordType*>(ET);
1570      int Pos = 0;    // relative pos from now on
1571
1572      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
1573               E = ERT->fields_end();
1574           I != E;
1575           I++) {
1576        const RSExportRecordType::Field *F = *I;
1577        std::string FieldName;
1578        int FieldOffset = F->getOffsetInParent();
1579        int FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
1580        int FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());
1581
1582        if (!VarName.empty())
1583          FieldName = VarName + "." + F->getName();
1584        else
1585          FieldName = F->getName();
1586
1587        // Alignment
1588        genAddPaddingToElementBuiler(C,
1589                                     (FieldOffset - Pos),
1590                                     ElementBuilderName,
1591                                     RenderScriptVar);
1592
1593        // eb.add(...)
1594        C.addFieldIndexMapping(F);
1595        genAddElementToElementBuilder(C,
1596                                      F->getType(),
1597                                      FieldName,
1598                                      ElementBuilderName,
1599                                      RenderScriptVar);
1600
1601        // There is padding within the field type
1602        genAddPaddingToElementBuiler(C,
1603                                     (FieldAllocSize - FieldStoreSize),
1604                                     ElementBuilderName,
1605                                     RenderScriptVar);
1606
1607        Pos = FieldOffset + FieldAllocSize;
1608      }
1609
1610      // There maybe some padding after the struct
1611      //unsigned char align = RSExportType::GetTypeAlignment(ERT);
1612      //size_t siz = RSExportType::GetTypeAllocSize(ERT);
1613      size_t siz1 = RSExportType::GetTypeStoreSize(ERT);
1614
1615      genAddPaddingToElementBuiler(C,
1616                                   siz1 - Pos,
1617                                   ElementBuilderName,
1618                                   RenderScriptVar);
1619    } else {
1620      assert(false && "Unknown class of type");
1621    }
1622  }
1623}
1624
1625void RSReflection::genAddPaddingToElementBuiler(Context &C,
1626                                                int PaddingSize,
1627                                                const char *ElementBuilderName,
1628                                                const char *RenderScriptVar) {
1629  while (PaddingSize > 0) {
1630    const std::string &VarName = C.createPaddingField();
1631    if (PaddingSize >= 4) {
1632      EB_ADD("U32(" << RenderScriptVar << ")");
1633      PaddingSize -= 4;
1634    } else if (PaddingSize >= 2) {
1635      EB_ADD("U16(" << RenderScriptVar << ")");
1636      PaddingSize -= 2;
1637    } else if (PaddingSize >= 1) {
1638      EB_ADD("U8(" << RenderScriptVar << ")");
1639      PaddingSize -= 1;
1640    }
1641  }
1642  return;
1643}
1644
1645#undef EB_ADD
1646/******** Methods to create Element in Java of given record type /end ********/
1647
1648bool RSReflection::reflect(const char *OutputPackageName,
1649                           const std::string &InputFileName,
1650                           const std::string &OutputBCFileName) {
1651  Context *C = NULL;
1652  std::string ResourceId = "";
1653
1654  if (!GetClassNameFromFileName(OutputBCFileName, ResourceId))
1655    return false;
1656
1657  if (ResourceId.empty())
1658    ResourceId = "<Resource ID>";
1659
1660  if ((OutputPackageName == NULL) ||
1661      (*OutputPackageName == '\0') ||
1662      strcmp(OutputPackageName, "-") == 0)
1663    C = new Context(InputFileName, "<Package Name>", ResourceId, true);
1664  else
1665    C = new Context(InputFileName, OutputPackageName, ResourceId, false);
1666
1667  if (C != NULL) {
1668    std::string ErrorMsg, ScriptClassName;
1669    // class ScriptC_<ScriptName>
1670    if (!GetClassNameFromFileName(InputFileName, ScriptClassName))
1671      return false;
1672
1673    if (ScriptClassName.empty())
1674      ScriptClassName = "<Input Script Name>";
1675
1676    ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);
1677
1678    if (mRSContext->getLicenseNote() != NULL) {
1679      C->setLicenseNote(*(mRSContext->getLicenseNote()));
1680    }
1681
1682    if (!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
1683      std::cerr << "Failed to generate class " << ScriptClassName << " ("
1684                << ErrorMsg << ")" << std::endl;
1685      return false;
1686    }
1687
1688    // class ScriptField_<TypeName>
1689    for (RSContext::const_export_type_iterator TI =
1690             mRSContext->export_types_begin(),
1691             TE = mRSContext->export_types_end();
1692         TI != TE;
1693         TI++) {
1694      const RSExportType *ET = TI->getValue();
1695
1696      if (ET->getClass() == RSExportType::ExportClassRecord) {
1697        const RSExportRecordType *ERT =
1698            static_cast<const RSExportRecordType*>(ET);
1699
1700        if (!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
1701          std::cerr << "Failed to generate type class for struct '"
1702                    << ERT->getName() << "' (" << ErrorMsg << ")" << std::endl;
1703          return false;
1704        }
1705      }
1706    }
1707  }
1708
1709  return true;
1710}
1711
1712/************************** RSReflection::Context **************************/
1713const char *const RSReflection::Context::ApacheLicenseNote =
1714    "/*\n"
1715    " * Copyright (C) 2010 The Android Open Source Project\n"
1716    " *\n"
1717    " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
1718    " * you may not use this file except in compliance with the License.\n"
1719    " * You may obtain a copy of the License at\n"
1720    " *\n"
1721    " *      http://www.apache.org/licenses/LICENSE-2.0\n"
1722    " *\n"
1723    " * Unless required by applicable law or agreed to in writing, software\n"
1724    " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
1725    " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
1726    "implied.\n"
1727    " * See the License for the specific language governing permissions and\n"
1728    " * limitations under the License.\n"
1729    " */\n"
1730    "\n";
1731
1732const char *const RSReflection::Context::Import[] = {
1733  // RenderScript java class
1734  "android.renderscript.*",
1735  // Import R
1736  "android.content.res.Resources",
1737  // Import for debugging
1738  "android.util.Log",
1739};
1740
1741const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) {
1742  switch (AM) {
1743    case AM_Public: return "public"; break;
1744    case AM_Protected: return "protected"; break;
1745    case AM_Private: return "private"; break;
1746    default: return ""; break;
1747  }
1748}
1749
1750bool RSReflection::Context::startClass(AccessModifier AM,
1751                                       bool IsStatic,
1752                                       const std::string &ClassName,
1753                                       const char *SuperClassName,
1754                                       std::string &ErrorMsg) {
1755  if (mVerbose)
1756    std::cout << "Generating " << ClassName << ".java ..." << std::endl;
1757
1758  // License
1759  out() << mLicenseNote;
1760
1761  // Notice of generated file
1762  out() << "/*" << std::endl;
1763  out() << " * This file is auto-generated. DO NOT MODIFY!" << std::endl;
1764  out() << " * The source RenderScript file: " << mInputRSFile << std::endl;
1765  out() << " */" << std::endl;
1766
1767  // Package
1768  if (!mPackageName.empty())
1769    out() << "package " << mPackageName << ";" << std::endl;
1770  out() << std::endl;
1771
1772  // Imports
1773  for (unsigned i = 0;i < (sizeof(Import) / sizeof(const char*)); i++)
1774    out() << "import " << Import[i] << ";" << std::endl;
1775  out() << std::endl;
1776
1777  // All reflected classes should be annotated as hidden, so that they won't
1778  // be exposed in SDK.
1779  out() << "/**" << std::endl;
1780  out() << " * @hide" << std::endl;
1781  out() << " */" << std::endl;
1782
1783  out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
1784        << ClassName;
1785  if (SuperClassName != NULL)
1786    out() << " extends " << SuperClassName;
1787
1788  startBlock();
1789
1790  mClassName = ClassName;
1791
1792  return true;
1793}
1794
1795void RSReflection::Context::endClass() {
1796  endBlock();
1797  if (!mUseStdout)
1798    mOF.close();
1799  clear();
1800  return;
1801}
1802
1803void RSReflection::Context::startBlock(bool ShouldIndent) {
1804  if (ShouldIndent)
1805    indent() << "{" << std::endl;
1806  else
1807    out() << " {" << std::endl;
1808  incIndentLevel();
1809  return;
1810}
1811
1812void RSReflection::Context::endBlock() {
1813  decIndentLevel();
1814  indent() << "}" << std::endl << std::endl;
1815  return;
1816}
1817
1818void RSReflection::Context::startTypeClass(const std::string &ClassName) {
1819  indent() << "public static class " << ClassName;
1820  startBlock();
1821  return;
1822}
1823
1824void RSReflection::Context::endTypeClass() {
1825  endBlock();
1826  return;
1827}
1828
1829void RSReflection::Context::startFunction(AccessModifier AM,
1830                                          bool IsStatic,
1831                                          const char *ReturnType,
1832                                          const std::string &FunctionName,
1833                                          int Argc, ...) {
1834  ArgTy Args;
1835  va_list vl;
1836  va_start(vl, Argc);
1837
1838  for (int i = 0; i < Argc; i++) {
1839    const char *ArgType = va_arg(vl, const char*);
1840    const char *ArgName = va_arg(vl, const char*);
1841
1842    Args.push_back(std::make_pair(ArgType, ArgName));
1843  }
1844  va_end(vl);
1845
1846  startFunction(AM, IsStatic, ReturnType, FunctionName, Args);
1847
1848  return;
1849}
1850
1851void RSReflection::Context::startFunction(AccessModifier AM,
1852                                          bool IsStatic,
1853                                          const char *ReturnType,
1854                                          const std::string &FunctionName,
1855                                          const ArgTy &Args) {
1856  indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
1857           << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";
1858
1859  bool FirstArg = true;
1860  for (ArgTy::const_iterator I = Args.begin(), E = Args.end();
1861       I != E;
1862       I++) {
1863    if (!FirstArg)
1864      out() << ", ";
1865    else
1866      FirstArg = false;
1867
1868    out() << I->first << " " << I->second;
1869  }
1870
1871  out() << ")";
1872  startBlock();
1873
1874  return;
1875}
1876
1877void RSReflection::Context::endFunction() {
1878  endBlock();
1879  return;
1880}
1881