/*
 * Copyright 2010-2012, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "slang_rs_reflection.h"

#include <sys/stat.h>

#include <cstdarg>
#include <cctype>

#include <algorithm>
#include <sstream>
#include <string>
#include <utility>

#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/StringExtras.h"

#include "os_sep.h"
#include "slang_rs_context.h"
#include "slang_rs_export_var.h"
#include "slang_rs_export_foreach.h"
#include "slang_rs_export_func.h"
#include "slang_rs_reflect_utils.h"
#include "slang_version.h"
#include "slang_utils.h"

#include "slang_rs_reflection_base.h"

#define RS_SCRIPT_CLASS_NAME_PREFIX      "ScriptC_"
#define RS_SCRIPT_CLASS_SUPER_CLASS_NAME "ScriptC"

#define RS_TYPE_CLASS_SUPER_CLASS_NAME   "android.renderscript.Script.FieldBase"

#define RS_TYPE_ITEM_CLASS_NAME          "Item"

#define RS_TYPE_ITEM_BUFFER_NAME         "mItemArray"
#define RS_TYPE_ITEM_BUFFER_PACKER_NAME  "mIOBuffer"
#define RS_TYPE_ELEMENT_REF_NAME         "mElementCache"

#define RS_EXPORT_VAR_INDEX_PREFIX       "mExportVarIdx_"
#define RS_EXPORT_VAR_PREFIX             "mExportVar_"
#define RS_EXPORT_VAR_ELEM_PREFIX        "mExportVarElem_"
#define RS_EXPORT_VAR_DIM_PREFIX         "mExportVarDim_"
#define RS_EXPORT_VAR_CONST_PREFIX       "const_"

#define RS_ELEM_PREFIX                   "__"

#define RS_FP_PREFIX                     "__rs_fp_"

#define RS_RESOURCE_NAME                 "__rs_resource_name"

#define RS_EXPORT_FUNC_INDEX_PREFIX      "mExportFuncIdx_"
#define RS_EXPORT_FOREACH_INDEX_PREFIX   "mExportForEachIdx_"

#define RS_EXPORT_VAR_ALLOCATION_PREFIX  "mAlloction_"
#define RS_EXPORT_VAR_DATA_STORAGE_PREFIX "mData_"

namespace slang {

// Some utility function using internal in RSReflection
static bool GetClassNameFromFileName(const std::string &FileName,
                                     std::string &ClassName) {
  ClassName.clear();

  if (FileName.empty() || (FileName == "-"))
    return true;

  ClassName =
      RSSlangReflectUtils::JavaClassNameFromRSFileName(FileName.c_str());

  return true;
}

static const char *GetMatrixTypeName(const RSExportMatrixType *EMT) {
  static const char *MatrixTypeJavaNameMap[] = {
    /* 2x2 */ "Matrix2f",
    /* 3x3 */ "Matrix3f",
    /* 4x4 */ "Matrix4f",
  };
  unsigned Dim = EMT->getDim();

  if ((Dim - 2) < (sizeof(MatrixTypeJavaNameMap) / sizeof(const char*)))
    return MatrixTypeJavaNameMap[ EMT->getDim() - 2 ];

  slangAssert(false && "GetMatrixTypeName : Unsupported matrix dimension");
  return NULL;
}

static const char *GetVectorAccessor(unsigned Index) {
  static const char *VectorAccessorMap[] = {
    /* 0 */ "x",
    /* 1 */ "y",
    /* 2 */ "z",
    /* 3 */ "w",
  };

  slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) &&
              "Out-of-bound index to access vector member");

  return VectorAccessorMap[Index];
}

static const char *GetPackerAPIName(const RSExportPrimitiveType *EPT) {
  static const char *PrimitiveTypePackerAPINameMap[] = {
    "",         // RSExportPrimitiveType::DataTypeFloat16
    "addF32",   // RSExportPrimitiveType::DataTypeFloat32
    "addF64",   // RSExportPrimitiveType::DataTypeFloat64
    "addI8",    // RSExportPrimitiveType::DataTypeSigned8
    "addI16",   // RSExportPrimitiveType::DataTypeSigned16
    "addI32",   // RSExportPrimitiveType::DataTypeSigned32
    "addI64",   // RSExportPrimitiveType::DataTypeSigned64
    "addU8",    // RSExportPrimitiveType::DataTypeUnsigned8
    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned16
    "addU32",   // RSExportPrimitiveType::DataTypeUnsigned32
    "addU64",   // RSExportPrimitiveType::DataTypeUnsigned64
    "addBoolean",  // RSExportPrimitiveType::DataTypeBoolean

    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned565
    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned5551
    "addU16",   // RSExportPrimitiveType::DataTypeUnsigned4444

    "addMatrix",   // RSExportPrimitiveType::DataTypeRSMatrix2x2
    "addMatrix",   // RSExportPrimitiveType::DataTypeRSMatrix3x3
    "addMatrix",   // RSExportPrimitiveType::DataTypeRSMatrix4x4

    "addObj",   // RSExportPrimitiveType::DataTypeRSElement
    "addObj",   // RSExportPrimitiveType::DataTypeRSType
    "addObj",   // RSExportPrimitiveType::DataTypeRSAllocation
    "addObj",   // RSExportPrimitiveType::DataTypeRSSampler
    "addObj",   // RSExportPrimitiveType::DataTypeRSScript
    "addObj",   // RSExportPrimitiveType::DataTypeRSMesh
    "addObj",   // RSExportPrimitiveType::DataTypeRSPath
    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramFragment
    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramVertex
    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramRaster
    "addObj",   // RSExportPrimitiveType::DataTypeRSProgramStore
    "addObj",   // RSExportPrimitiveType::DataTypeRSFont
  };
  unsigned TypeId = EPT->getType();

  if (TypeId < (sizeof(PrimitiveTypePackerAPINameMap) / sizeof(const char*)))
    return PrimitiveTypePackerAPINameMap[ EPT->getType() ];

  slangAssert(false && "GetPackerAPIName : Unknown primitive data type");
  return NULL;
}

static std::string GetTypeName(const RSExportType *ET, bool Brackets = true) {
  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive: {
      return RSExportPrimitiveType::getRSReflectionType(
          static_cast<const RSExportPrimitiveType*>(ET))->java_name;
    }
    case RSExportType::ExportClassPointer: {
      const RSExportType *PointeeType =
          static_cast<const RSExportPointerType*>(ET)->getPointeeType();

      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
        return "Allocation";
      else
        return PointeeType->getElementName();
    }
    case RSExportType::ExportClassVector: {
      const RSExportVectorType *EVT =
          static_cast<const RSExportVectorType*>(ET);
      std::stringstream VecName;
      VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix
              << EVT->getNumElement();
      return VecName.str();
    }
    case RSExportType::ExportClassMatrix: {
      return GetMatrixTypeName(static_cast<const RSExportMatrixType*>(ET));
    }
    case RSExportType::ExportClassConstantArray: {
      const RSExportConstantArrayType* CAT =
          static_cast<const RSExportConstantArrayType*>(ET);
      std::string ElementTypeName = GetTypeName(CAT->getElementType());
      if (Brackets) {
        ElementTypeName.append("[]");
      }
      return ElementTypeName;
    }
    case RSExportType::ExportClassRecord: {
      return ET->getElementName() + "."RS_TYPE_ITEM_CLASS_NAME;
    }
    default: {
      slangAssert(false && "Unknown class of type");
    }
  }

  return "";
}

static const char *GetTypeNullValue(const RSExportType *ET) {
  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive: {
      const RSExportPrimitiveType *EPT =
          static_cast<const RSExportPrimitiveType*>(ET);
      if (EPT->isRSObjectType())
        return "null";
      else if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean)
        return "false";
      else
        return "0";
      break;
    }
    case RSExportType::ExportClassPointer:
    case RSExportType::ExportClassVector:
    case RSExportType::ExportClassMatrix:
    case RSExportType::ExportClassConstantArray:
    case RSExportType::ExportClassRecord: {
      return "null";
      break;
    }
    default: {
      slangAssert(false && "Unknown class of type");
    }
  }
  return "";
}

static std::string GetBuiltinElementConstruct(const RSExportType *ET) {
  if (ET->getClass() == RSExportType::ExportClassPrimitive) {
    return std::string("Element.") + ET->getElementName();
  } else if (ET->getClass() == RSExportType::ExportClassVector) {
    const RSExportVectorType *EVT = static_cast<const RSExportVectorType*>(ET);
    if (EVT->getType() == RSExportPrimitiveType::DataTypeFloat32) {
      if (EVT->getNumElement() == 2)
        return "Element.F32_2";
      else if (EVT->getNumElement() == 3)
        return "Element.F32_3";
      else if (EVT->getNumElement() == 4)
        return "Element.F32_4";
    } else if (EVT->getType() == RSExportPrimitiveType::DataTypeUnsigned8) {
      if (EVT->getNumElement() == 4)
        return "Element.U8_4";
    }
  } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
    const RSExportMatrixType *EMT = static_cast<const RSExportMatrixType *>(ET);
    switch (EMT->getDim()) {
      case 2: return "Element.MATRIX_2X2";
      case 3: return "Element.MATRIX_3X3";
      case 4: return "Element.MATRIX_4X4";
      default: slangAssert(false && "Unsupported dimension of matrix");
    }
  }
  // RSExportType::ExportClassPointer can't be generated in a struct.

  return "";
}


/********************** Methods to generate script class **********************/
bool RSReflection::genScriptClass(Context &C,
                                  const std::string &ClassName,
                                  std::string &ErrorMsg) {
  if (!C.startClass(Context::AM_Public,
                    false,
                    ClassName,
                    RS_SCRIPT_CLASS_SUPER_CLASS_NAME,
                    ErrorMsg))
    return false;

  genScriptClassConstructor(C);

  // Reflect export variable
  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
           E = mRSContext->export_vars_end();
       I != E;
       I++)
    genExportVariable(C, *I);

  // Reflect export for each functions (only available on ICS+)
  if (mRSContext->getTargetAPI() >= SLANG_ICS_TARGET_API) {
    for (RSContext::const_export_foreach_iterator
             I = mRSContext->export_foreach_begin(),
             E = mRSContext->export_foreach_end();
         I != E; I++)
      genExportForEach(C, *I);
  }

  // Reflect export function
  for (RSContext::const_export_func_iterator
           I = mRSContext->export_funcs_begin(),
           E = mRSContext->export_funcs_end();
       I != E; I++)
    genExportFunction(C, *I);

  C.endClass();

  return true;
}

void RSReflection::genScriptClassConstructor(Context &C) {
  // Provide a simple way to reference this object.
  C.indent() << "private static final String " RS_RESOURCE_NAME " = \""
             << C.getResourceId()
             << "\";" << std::endl;

  // Generate a simple constructor with only a single parameter (the rest
  // can be inferred from information we already have).
  C.indent() << "// Constructor" << std::endl;
  C.startFunction(Context::AM_Public,
                  false,
                  NULL,
                  C.getClassName(),
                  1,
                  "RenderScript", "rs");
  // Call alternate constructor with required parameters.
  // Look up the proper raw bitcode resource id via the context.
  C.indent() << "this(rs," << std::endl;
  C.indent() << "     rs.getApplicationContext().getResources()," << std::endl;
  C.indent() << "     rs.getApplicationContext().getResources()."
                "getIdentifier(" << std::endl;
  C.indent() << "         " RS_RESOURCE_NAME ", \"raw\"," << std::endl;
  C.indent() << "         rs.getApplicationContext().getPackageName()));"
             << std::endl;
  C.endFunction();

  // Alternate constructor (legacy) with 3 original parameters.
  C.startFunction(Context::AM_Public,
                  false,
                  NULL,
                  C.getClassName(),
                  3,
                  "RenderScript", "rs",
                  "Resources", "resources",
                  "int", "id");
  // Call constructor of super class
  C.indent() << "super(rs, resources, id);" << std::endl;

  // If an exported variable has initial value, reflect it

  for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
           E = mRSContext->export_vars_end();
       I != E;
       I++) {
    const RSExportVar *EV = *I;
    if (!EV->getInit().isUninit()) {
      genInitExportVariable(C, EV->getType(), EV->getName(), EV->getInit());
    } else if (EV->getArraySize()) {
      // Always create an initial zero-init array object.
      C.indent() << RS_EXPORT_VAR_PREFIX << EV->getName() << " = new "
                 << GetTypeName(EV->getType(), false) << "["
                 << EV->getArraySize() << "];" << std::endl;
      size_t NumInits = EV->getNumInits();
      const RSExportConstantArrayType *ECAT =
          static_cast<const RSExportConstantArrayType*>(EV->getType());
      const RSExportType *ET = ECAT->getElementType();
      for (size_t i = 0; i < NumInits; i++) {
        std::stringstream Name;
        Name << EV->getName() << "[" << i << "]";
        genInitExportVariable(C, ET, Name.str(), EV->getInitArray(i));
      }
    }
    if (mRSContext->getTargetAPI() >= SLANG_JB_TARGET_API) {
      genTypeInstance(C, EV->getType());
    }
    genFieldPackerInstance(C, EV->getType());
  }

  for (RSContext::const_export_foreach_iterator
           I = mRSContext->export_foreach_begin(),
           E = mRSContext->export_foreach_end();
       I != E;
       I++) {
    const RSExportForEach *EF = *I;

    const RSExportType *IET = EF->getInType();
    if (IET) {
      genTypeInstanceFromPointer(C, IET);
    }
    const RSExportType *OET = EF->getOutType();
    if (OET) {
      genTypeInstanceFromPointer(C, OET);
    }
  }

  C.endFunction();

  for (std::set<std::string>::iterator I = C.mTypesToCheck.begin(),
                                       E = C.mTypesToCheck.end();
       I != E;
       I++) {
    C.indent() << "private Element " RS_ELEM_PREFIX << *I << ";" << std::endl;
  }

  for (std::set<std::string>::iterator I = C.mFieldPackerTypes.begin(),
                                       E = C.mFieldPackerTypes.end();
       I != E;
       I++) {
    C.indent() << "private FieldPacker " RS_FP_PREFIX << *I << ";" << std::endl;
  }

  return;
}

void RSReflection::genInitBoolExportVariable(Context &C,
                                             const std::string &VarName,
                                             const clang::APValue &Val) {
  slangAssert(!Val.isUninit() && "Not a valid initializer");

  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
  slangAssert((Val.getKind() == clang::APValue::Int) &&
              "Bool type has wrong initial APValue");

  C.out() << ((Val.getInt().getSExtValue() == 0) ? "false" : "true")
          << ";" << std::endl;

  return;
}

void RSReflection::genInitPrimitiveExportVariable(
      Context &C,
      const std::string &VarName,
      const clang::APValue &Val) {
  slangAssert(!Val.isUninit() && "Not a valid initializer");

  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = ";
  C.out() << RSReflectionBase::genInitValue(Val);
  C.out() << ";" << std::endl;

  return;
}

void RSReflection::genInitExportVariable(Context &C,
                                         const RSExportType *ET,
                                         const std::string &VarName,
                                         const clang::APValue &Val) {
  slangAssert(!Val.isUninit() && "Not a valid initializer");

  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive: {
      const RSExportPrimitiveType *EPT =
          static_cast<const RSExportPrimitiveType*>(ET);
      if (EPT->getType() == RSExportPrimitiveType::DataTypeBoolean) {
        genInitBoolExportVariable(C, VarName, Val);
      } else {
        genInitPrimitiveExportVariable(C, VarName, Val);
      }
      break;
    }
    case RSExportType::ExportClassPointer: {
      if (!Val.isInt() || Val.getInt().getSExtValue() != 0)
        std::cout << "Initializer which is non-NULL to pointer type variable "
                     "will be ignored" << std::endl;
      break;
    }
    case RSExportType::ExportClassVector: {
      const RSExportVectorType *EVT =
          static_cast<const RSExportVectorType*>(ET);
      switch (Val.getKind()) {
        case clang::APValue::Int:
        case clang::APValue::Float: {
          for (unsigned i = 0; i < EVT->getNumElement(); i++) {
            std::string Name =  VarName + "." + GetVectorAccessor(i);
            genInitPrimitiveExportVariable(C, Name, Val);
          }
          break;
        }
        case clang::APValue::Vector: {
          std::stringstream VecName;
          VecName << EVT->getRSReflectionType(EVT)->rs_java_vector_prefix
                  << EVT->getNumElement();
          C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = new "
                     << VecName.str() << "();" << std::endl;

          unsigned NumElements =
              std::min(static_cast<unsigned>(EVT->getNumElement()),
                       Val.getVectorLength());
          for (unsigned i = 0; i < NumElements; i++) {
            const clang::APValue &ElementVal = Val.getVectorElt(i);
            std::string Name = VarName + "." + GetVectorAccessor(i);
            genInitPrimitiveExportVariable(C, Name, ElementVal);
          }
          break;
        }
        case clang::APValue::MemberPointer:
        case clang::APValue::Uninitialized:
        case clang::APValue::ComplexInt:
        case clang::APValue::ComplexFloat:
        case clang::APValue::LValue:
        case clang::APValue::Array:
        case clang::APValue::Struct:
        case clang::APValue::Union:
        case clang::APValue::AddrLabelDiff: {
          slangAssert(false && "Unexpected type of value of initializer.");
        }
      }
      break;
    }
    // TODO(zonr): Resolving initializer of a record (and matrix) type variable
    // is complex. It cannot obtain by just simply evaluating the initializer
    // expression.
    case RSExportType::ExportClassMatrix:
    case RSExportType::ExportClassConstantArray:
    case RSExportType::ExportClassRecord: {
#if 0
      unsigned InitIndex = 0;
      const RSExportRecordType *ERT =
          static_cast<const RSExportRecordType*>(ET);

      slangAssert((Val.getKind() == clang::APValue::Vector) &&
          "Unexpected type of initializer for record type variable");

      C.indent() << RS_EXPORT_VAR_PREFIX << VarName
                 << " = new " << ERT->getElementName()
                 <<  "."RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;

      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
               E = ERT->fields_end();
           I != E;
           I++) {
        const RSExportRecordType::Field *F = *I;
        std::string FieldName = VarName + "." + F->getName();

        if (InitIndex > Val.getVectorLength())
          break;

        genInitPrimitiveExportVariable(C,
                                       FieldName,
                                       Val.getVectorElt(InitIndex++));
      }
#endif
      slangAssert(false && "Unsupported initializer for record/matrix/constant "
                           "array type variable currently");
      break;
    }
    default: {
      slangAssert(false && "Unknown class of type");
    }
  }
  return;
}

void RSReflection::genExportVariable(Context &C, const RSExportVar *EV) {
  const RSExportType *ET = EV->getType();

  C.indent() << "private final static int "RS_EXPORT_VAR_INDEX_PREFIX
             << EV->getName() << " = " << C.getNextExportVarSlot() << ";"
             << std::endl;

  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive: {
      genPrimitiveTypeExportVariable(C, EV);
      break;
    }
    case RSExportType::ExportClassPointer: {
      genPointerTypeExportVariable(C, EV);
      break;
    }
    case RSExportType::ExportClassVector: {
      genVectorTypeExportVariable(C, EV);
      break;
    }
    case RSExportType::ExportClassMatrix: {
      genMatrixTypeExportVariable(C, EV);
      break;
    }
    case RSExportType::ExportClassConstantArray: {
      genConstantArrayTypeExportVariable(C, EV);
      break;
    }
    case RSExportType::ExportClassRecord: {
      genRecordTypeExportVariable(C, EV);
      break;
    }
    default: {
      slangAssert(false && "Unknown class of type");
    }
  }

  return;
}

void RSReflection::genExportFunction(Context &C, const RSExportFunc *EF) {
  C.indent() << "private final static int "RS_EXPORT_FUNC_INDEX_PREFIX
             << EF->getName() << " = " << C.getNextExportFuncSlot() << ";"
             << std::endl;

  // invoke_*()
  Context::ArgTy Args;

  if (EF->hasParam()) {
    for (RSExportFunc::const_param_iterator I = EF->params_begin(),
             E = EF->params_end();
         I != E;
         I++) {
      Args.push_back(std::make_pair(GetTypeName((*I)->getType()),
                                    (*I)->getName()));
    }
  }

  C.startFunction(Context::AM_Public,
                  false,
                  "void",
                  "invoke_" + EF->getName(/*Mangle=*/ false),
                      // We are using un-mangled name since Java
                      // supports method overloading.
                  Args);

  if (!EF->hasParam()) {
    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ");"
               << std::endl;
  } else {
    const RSExportRecordType *ERT = EF->getParamPacketType();
    std::string FieldPackerName = EF->getName() + "_fp";

    if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str()))
      genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());

    C.indent() << "invoke("RS_EXPORT_FUNC_INDEX_PREFIX << EF->getName() << ", "
               << FieldPackerName << ");" << std::endl;
  }

  C.endFunction();
  return;
}

void RSReflection::genExportForEach(Context &C, const RSExportForEach *EF) {
  if (EF->isDummyRoot()) {
    // Skip reflection for dummy root() kernels. Note that we have to
    // advance the next slot number for ForEach, however.
    C.indent() << "//private final static int "RS_EXPORT_FOREACH_INDEX_PREFIX
               << EF->getName() << " = " << C.getNextExportForEachSlot() << ";"
               << std::endl;
    return;
  }

  C.indent() << "private final static int "RS_EXPORT_FOREACH_INDEX_PREFIX
             << EF->getName() << " = " << C.getNextExportForEachSlot() << ";"
             << std::endl;

  // forEach_*()
  Context::ArgTy Args;

  slangAssert(EF->getNumParameters() > 0 || EF->hasReturn());

  if (EF->hasIn())
    Args.push_back(std::make_pair("Allocation", "ain"));
  if (EF->hasOut() || EF->hasReturn())
    Args.push_back(std::make_pair("Allocation", "aout"));

  const RSExportRecordType *ERT = EF->getParamPacketType();
  if (ERT) {
    for (RSExportForEach::const_param_iterator I = EF->params_begin(),
             E = EF->params_end();
         I != E;
         I++) {
      Args.push_back(std::make_pair(GetTypeName((*I)->getType()),
                                    (*I)->getName()));
    }
  }

  const RSExportType *IET = EF->getInType();
  const RSExportType *OET = EF->getOutType();

  if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
      int signature = 0;
      C.startFunction(Context::AM_Public,
                      false,
                      "Script.KernelID",
                      "getKernelID_" + EF->getName(),
                      0);

      if (IET)
          signature |= 1;
      if (OET)
          signature |= 2;

      //TODO: add element checking
      C.indent() << "return createKernelID(" << RS_EXPORT_FOREACH_INDEX_PREFIX
                 << EF->getName() << ", " << signature << ", null, null);"
                 << std::endl;

      C.endFunction();
  }

  C.startFunction(Context::AM_Public,
                  false,
                  "void",
                  "forEach_" + EF->getName(),
                  Args);

  if (IET) {
    genTypeCheck(C, IET, "ain");
  }
  if (OET) {
    genTypeCheck(C, OET, "aout");
  }

  if (EF->hasIn() && (EF->hasOut() || EF->hasReturn())) {
    C.indent() << "// Verify dimensions" << std::endl;
    C.indent() << "Type tIn = ain.getType();" << std::endl;
    C.indent() << "Type tOut = aout.getType();" << std::endl;
    C.indent() << "if ((tIn.getCount() != tOut.getCount()) ||" << std::endl;
    C.indent() << "    (tIn.getX() != tOut.getX()) ||" << std::endl;
    C.indent() << "    (tIn.getY() != tOut.getY()) ||" << std::endl;
    C.indent() << "    (tIn.getZ() != tOut.getZ()) ||" << std::endl;
    C.indent() << "    (tIn.hasFaces() != tOut.hasFaces()) ||" << std::endl;
    C.indent() << "    (tIn.hasMipmaps() != tOut.hasMipmaps())) {" << std::endl;
    C.indent() << "    throw new RSRuntimeException(\"Dimension mismatch "
               << "between input and output parameters!\");";
    C.out()    << std::endl;
    C.indent() << "}" << std::endl;
  }

  std::string FieldPackerName = EF->getName() + "_fp";
  if (ERT) {
    if (genCreateFieldPacker(C, ERT, FieldPackerName.c_str())) {
      genPackVarOfType(C, ERT, NULL, FieldPackerName.c_str());
    }
  }
  C.indent() << "forEach("RS_EXPORT_FOREACH_INDEX_PREFIX << EF->getName();

  if (EF->hasIn())
    C.out() << ", ain";
  else
    C.out() << ", null";

  if (EF->hasOut() || EF->hasReturn())
    C.out() << ", aout";
  else
    C.out() << ", null";

  if (EF->hasUsrData())
    C.out() << ", " << FieldPackerName;
  else
    C.out() << ", null";

  C.out() << ");" << std::endl;

  C.endFunction();
  return;
}

void RSReflection::genTypeInstanceFromPointer(Context &C,
                                              const RSExportType *ET) {
  if (ET->getClass() == RSExportType::ExportClassPointer) {
    // For pointer parameters to original forEach kernels.
    const RSExportPointerType *EPT =
        static_cast<const RSExportPointerType*>(ET);
    genTypeInstance(C, EPT->getPointeeType());
  } else {
    // For handling pass-by-value kernel parameters.
    genTypeInstance(C, ET);
  }
}

void RSReflection::genTypeInstance(Context &C,
                                   const RSExportType *ET) {
  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive:
    case RSExportType::ExportClassVector:
    case RSExportType::ExportClassConstantArray: {
      std::string TypeName = ET->getElementName();
      if (C.addTypeNameForElement(TypeName)) {
        C.indent() << RS_ELEM_PREFIX << TypeName << " = Element." << TypeName
                   << "(rs);" << std::endl;
      }
      break;
    }

    case RSExportType::ExportClassRecord: {
      std::string ClassName = ET->getElementName();
      if (C.addTypeNameForElement(ClassName)) {
        C.indent() << RS_ELEM_PREFIX << ClassName << " = " << ClassName <<
                      ".createElement(rs);" << std::endl;
      }
      break;
    }

    default:
      break;
  }
}

void RSReflection::genFieldPackerInstance(Context &C,
                                          const RSExportType *ET) {
  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive:
    case RSExportType::ExportClassVector:
    case RSExportType::ExportClassConstantArray:
    case RSExportType::ExportClassRecord: {
      std::string TypeName = ET->getElementName();
      C.addTypeNameForFieldPacker(TypeName);
      break;
    }

    default:
      break;
  }
}

void RSReflection::genTypeCheck(Context &C,
                                const RSExportType *ET,
                                const char *VarName) {
  C.indent() << "// check " << VarName << std::endl;

  if (ET->getClass() == RSExportType::ExportClassPointer) {
    const RSExportPointerType *EPT =
        static_cast<const RSExportPointerType*>(ET);
    ET = EPT->getPointeeType();
  }

  std::string TypeName;

  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive:
    case RSExportType::ExportClassVector:
    case RSExportType::ExportClassRecord: {
      TypeName = ET->getElementName();
      break;
    }

    default:
      break;
  }

  if (!TypeName.empty()) {
    C.indent() << "if (!" << VarName
               << ".getType().getElement().isCompatible(" RS_ELEM_PREFIX
               << TypeName << ")) {" << std::endl;
    C.indent() << "    throw new RSRuntimeException(\"Type mismatch with "
               << TypeName << "!\");" << std::endl;
    C.indent() << "}" << std::endl;
  }

  return;
}


void RSReflection::genPrimitiveTypeExportVariable(
    Context &C,
    const RSExportVar *EV) {
  slangAssert((EV->getType()->getClass() == RSExportType::ExportClassPrimitive)
              && "Variable should be type of primitive here");

  const RSExportPrimitiveType *EPT =
      static_cast<const RSExportPrimitiveType*>(EV->getType());
  std::string TypeName = GetTypeName(EPT);
  std::string VarName = EV->getName();

  genPrivateExportVariable(C, TypeName, EV->getName());

  if (EV->isConst()) {
    C.indent() << "public final static " << TypeName
               << " " RS_EXPORT_VAR_CONST_PREFIX << VarName << " = ";
    const clang::APValue &Val = EV->getInit();
    C.out() << RSReflectionBase::genInitValue(Val, EPT->getType() ==
        RSExportPrimitiveType::DataTypeBoolean) << ";" << std::endl;
  } else {
    // set_*()
    // This must remain synchronized, since multiple Dalvik threads may
    // be calling setters.
    C.startFunction(Context::AM_PublicSynchronized,
                    false,
                    "void",
                    "set_" + VarName,
                    1,
                    TypeName.c_str(), "v");
    if ((EPT->getSize() < 4) || EV->isUnsigned()) {
      // We create/cache a per-type FieldPacker. This allows us to reuse the
      // validation logic (for catching negative inputs from Dalvik, as well
      // as inputs that are too large to be represented in the unsigned type).
      // Sub-integer types are also handled specially here, so that we don't
      // overwrite bytes accidentally.
      std::string ElemName = EPT->getElementName();
      std::string FPName;
      FPName = RS_FP_PREFIX + ElemName;
      C.indent() << "if (" << FPName << "!= null) {"
                 << std::endl;
      C.incIndentLevel();
      C.indent() << FPName << ".reset();" << std::endl;
      C.decIndentLevel();
      C.indent() << "} else {" << std::endl;
      C.incIndentLevel();
      C.indent() << FPName << " = new FieldPacker("
                 << EPT->getSize() << ");" << std::endl;
      C.decIndentLevel();
      C.indent() << "}" << std::endl;

      genPackVarOfType(C, EPT, "v", FPName.c_str());
      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << VarName
                 << ", " << FPName << ");" << std::endl;
    } else {
      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << VarName
                 << ", v);" << std::endl;
    }

    // Dalvik update comes last, since the input may be invalid (and hence
    // throw an exception).
    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;" << std::endl;

    C.endFunction();
  }

  genGetExportVariable(C, TypeName, VarName);
  genGetFieldID(C, VarName);
  return;
}

void RSReflection::genPointerTypeExportVariable(Context &C,
                                                const RSExportVar *EV) {
  const RSExportType *ET = EV->getType();
  const RSExportType *PointeeType;

  slangAssert((ET->getClass() == RSExportType::ExportClassPointer) &&
              "Variable should be type of pointer here");

  PointeeType = static_cast<const RSExportPointerType*>(ET)->getPointeeType();
  std::string TypeName = GetTypeName(ET);
  std::string VarName = EV->getName();

  genPrivateExportVariable(C, TypeName, VarName);

  // bind_*()
  C.startFunction(Context::AM_Public,
                  false,
                  "void",
                  "bind_" + VarName,
                  1,
                  TypeName.c_str(), "v");

  C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;" << std::endl;
  C.indent() << "if (v == null) bindAllocation(null, "RS_EXPORT_VAR_INDEX_PREFIX
             << VarName << ");" << std::endl;

  if (PointeeType->getClass() == RSExportType::ExportClassRecord)
    C.indent() << "else bindAllocation(v.getAllocation(), "
        RS_EXPORT_VAR_INDEX_PREFIX << VarName << ");"
               << std::endl;
  else
    C.indent() << "else bindAllocation(v, "RS_EXPORT_VAR_INDEX_PREFIX
               << VarName << ");" << std::endl;

  C.endFunction();

  genGetExportVariable(C, TypeName, VarName);
  return;
}

void RSReflection::genVectorTypeExportVariable(Context &C,
                                               const RSExportVar *EV) {
  slangAssert((EV->getType()->getClass() == RSExportType::ExportClassVector) &&
              "Variable should be type of vector here");

  std::string TypeName = GetTypeName(EV->getType());
  std::string VarName = EV->getName();

  genPrivateExportVariable(C, TypeName, VarName);
  genSetExportVariable(C, TypeName, EV);
  genGetExportVariable(C, TypeName, VarName);
  genGetFieldID(C, VarName);
  return;
}

void RSReflection::genMatrixTypeExportVariable(Context &C,
                                               const RSExportVar *EV) {
  slangAssert((EV->getType()->getClass() == RSExportType::ExportClassMatrix) &&
              "Variable should be type of matrix here");

    const RSExportType *ET = EV->getType();
  std::string TypeName = GetTypeName(ET);
  std::string VarName = EV->getName();

  genPrivateExportVariable(C, TypeName, VarName);

  // set_*()
  if (!EV->isConst()) {
    const char *FieldPackerName = "fp";
    C.startFunction(Context::AM_PublicSynchronized,
                    false,
                    "void",
                    "set_" + VarName,
                    1,
                    TypeName.c_str(), "v");
    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;" << std::endl;

    if (genCreateFieldPacker(C, ET, FieldPackerName))
      genPackVarOfType(C, ET, "v", FieldPackerName);
    C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", "
               << FieldPackerName << ");" << std::endl;

    C.endFunction();
  }

  genGetExportVariable(C, TypeName, VarName);
  genGetFieldID(C, VarName);
  return;
}

void RSReflection::genConstantArrayTypeExportVariable(
    Context &C,
    const RSExportVar *EV) {
  slangAssert((EV->getType()->getClass() ==
               RSExportType::ExportClassConstantArray) &&
              "Variable should be type of constant array here");

  std::string TypeName = GetTypeName(EV->getType());
  std::string VarName = EV->getName();

  genPrivateExportVariable(C, TypeName, VarName);
  genSetExportVariable(C, TypeName, EV);
  genGetExportVariable(C, TypeName, VarName);
  genGetFieldID(C, VarName);
  return;
}

void RSReflection::genRecordTypeExportVariable(Context &C,
                                               const RSExportVar *EV) {
  slangAssert((EV->getType()->getClass() == RSExportType::ExportClassRecord) &&
              "Variable should be type of struct here");

  std::string TypeName = GetTypeName(EV->getType());
  std::string VarName = EV->getName();

  genPrivateExportVariable(C, TypeName, VarName);
  genSetExportVariable(C, TypeName, EV);
  genGetExportVariable(C, TypeName, VarName);
  genGetFieldID(C, VarName);
  return;
}

void RSReflection::genPrivateExportVariable(Context &C,
                                            const std::string &TypeName,
                                            const std::string &VarName) {
  C.indent() << "private " << TypeName << " "RS_EXPORT_VAR_PREFIX
             << VarName << ";" << std::endl;
  return;
}

void RSReflection::genSetExportVariable(Context &C,
                                        const std::string &TypeName,
                                        const RSExportVar *EV) {
  if (!EV->isConst()) {
    const char *FieldPackerName = "fp";
    std::string VarName = EV->getName();
    const RSExportType *ET = EV->getType();
    C.startFunction(Context::AM_PublicSynchronized,
                    false,
                    "void",
                    "set_" + VarName,
                    1,
                    TypeName.c_str(), "v");
    C.indent() << RS_EXPORT_VAR_PREFIX << VarName << " = v;" << std::endl;

    if (genCreateFieldPacker(C, ET, FieldPackerName))
      genPackVarOfType(C, ET, "v", FieldPackerName);

    if (mRSContext->getTargetAPI() < SLANG_JB_TARGET_API) {
      // Legacy apps must use the old setVar() without Element/dim components.
      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << VarName
                 << ", " << FieldPackerName << ");" << std::endl;
    } else {
      // We only have support for one-dimensional array reflection today,
      // but the entry point (i.e. setVar()) takes an array of dimensions.
      C.indent() << "int []__dimArr = new int[1];" << std::endl;
      C.indent() << "__dimArr[0] = " << ET->getSize() << ";" << std::endl;
      C.indent() << "setVar("RS_EXPORT_VAR_INDEX_PREFIX << VarName << ", "
                 << FieldPackerName << ", " RS_ELEM_PREFIX
                 << ET->getElementName() << ", __dimArr);" << std::endl;
    }

    C.endFunction();
  }
  return;
}

void RSReflection::genGetExportVariable(Context &C,
                                        const std::string &TypeName,
                                        const std::string &VarName) {
  C.startFunction(Context::AM_Public,
                  false,
                  TypeName.c_str(),
                  "get_" + VarName,
                  0);

  C.indent() << "return "RS_EXPORT_VAR_PREFIX << VarName << ";" << std::endl;

  C.endFunction();
}

void RSReflection::genGetFieldID(Context &C, const std::string &VarName) {
  // We only generate getFieldID_*() for non-Pointer (bind) types.
  if (mRSContext->getTargetAPI() >= SLANG_JB_MR1_TARGET_API) {
    C.startFunction(Context::AM_Public,
                    false,
                    "Script.FieldID",
                    "getFieldID_" + VarName,
                    0);

    C.indent() << "return createFieldID(" << RS_EXPORT_VAR_INDEX_PREFIX
               << VarName << ", null);" << std::endl;

    C.endFunction();
  }
}

/******************* Methods to generate script class /end *******************/

bool RSReflection::genCreateFieldPacker(Context &C,
                                        const RSExportType *ET,
                                        const char *FieldPackerName) {
  size_t AllocSize = RSExportType::GetTypeAllocSize(ET);
  if (AllocSize > 0)
    C.indent() << "FieldPacker " << FieldPackerName << " = new FieldPacker("
               << AllocSize << ");" << std::endl;
  else
    return false;
  return true;
}

void RSReflection::genPackVarOfType(Context &C,
                                    const RSExportType *ET,
                                    const char *VarName,
                                    const char *FieldPackerName) {
  switch (ET->getClass()) {
    case RSExportType::ExportClassPrimitive:
    case RSExportType::ExportClassVector: {
      C.indent() << FieldPackerName << "."
                 << GetPackerAPIName(
                     static_cast<const RSExportPrimitiveType*>(ET))
                 << "(" << VarName << ");" << std::endl;
      break;
    }
    case RSExportType::ExportClassPointer: {
      // Must reflect as type Allocation in Java
      const RSExportType *PointeeType =
          static_cast<const RSExportPointerType*>(ET)->getPointeeType();

      if (PointeeType->getClass() != RSExportType::ExportClassRecord)
        C.indent() << FieldPackerName << ".addI32(" << VarName
                   << ".getPtr());" << std::endl;
      else
        C.indent() << FieldPackerName << ".addI32(" << VarName
                   << ".getAllocation().getPtr());" << std::endl;
      break;
    }
    case RSExportType::ExportClassMatrix: {
      C.indent() << FieldPackerName << ".addMatrix(" << VarName << ");"
                 << std::endl;
      break;
    }
    case RSExportType::ExportClassConstantArray: {
      const RSExportConstantArrayType *ECAT =
          static_cast<const RSExportConstantArrayType *>(ET);

      // TODO(zonr): more elegant way. Currently, we obtain the unique index
      //             variable (this method involves recursive call which means
      //             we may have more than one level loop, therefore we can't
      //             always use the same index variable name here) name given
      //             in the for-loop from counting the '.' in @VarName.
      unsigned Level = 0;
      size_t LastDotPos = 0;
      std::string ElementVarName(VarName);

      while (LastDotPos != std::string::npos) {
        LastDotPos = ElementVarName.find_first_of('.', LastDotPos + 1);
        Level++;
      }
      std::string IndexVarName("ct");
      IndexVarName.append(llvm::utostr_32(Level));

      C.indent() << "for (int " << IndexVarName << " = 0; " <<
                          IndexVarName << " < " << ECAT->getSize() << "; " <<
                          IndexVarName << "++)";
      C.startBlock();

      ElementVarName.append("[" + IndexVarName + "]");
      genPackVarOfType(C, ECAT->getElementType(), ElementVarName.c_str(),
                       FieldPackerName);

      C.endBlock();
      break;
    }
    case RSExportType::ExportClassRecord: {
      const RSExportRecordType *ERT =
          static_cast<const RSExportRecordType*>(ET);
      // Relative pos from now on in field packer
      unsigned Pos = 0;

      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
               E = ERT->fields_end();
           I != E;
           I++) {
        const RSExportRecordType::Field *F = *I;
        std::string FieldName;
        size_t FieldOffset = F->getOffsetInParent();
        size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
        size_t FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());

        if (VarName != NULL)
          FieldName = VarName + ("." + F->getName());
        else
          FieldName = F->getName();

        if (FieldOffset > Pos)
          C.indent() << FieldPackerName << ".skip("
                     << (FieldOffset - Pos) << ");" << std::endl;

        genPackVarOfType(C, F->getType(), FieldName.c_str(), FieldPackerName);

        // There is padding in the field type
        if (FieldAllocSize > FieldStoreSize)
            C.indent() << FieldPackerName << ".skip("
                       << (FieldAllocSize - FieldStoreSize)
                       << ");" << std::endl;

        Pos = FieldOffset + FieldAllocSize;
      }

      // There maybe some padding after the struct
      if (RSExportType::GetTypeAllocSize(ERT) > Pos)
        C.indent() << FieldPackerName << ".skip("
                   << RSExportType::GetTypeAllocSize(ERT) - Pos << ");"
                   << std::endl;
      break;
    }
    default: {
      slangAssert(false && "Unknown class of type");
    }
  }

  return;
}

void RSReflection::genAllocateVarOfType(Context &C,
                                        const RSExportType *T,
                                        const std::string &VarName) {
  switch (T->getClass()) {
    case RSExportType::ExportClassPrimitive: {
      // Primitive type like int in Java has its own storage once it's declared.
      //
      // FIXME: Should we allocate storage for RS object?
      // if (static_cast<const RSExportPrimitiveType *>(T)->isRSObjectType())
      //  C.indent() << VarName << " = new " << GetTypeName(T) << "();"
      //             << std::endl;
      break;
    }
    case RSExportType::ExportClassPointer: {
      // Pointer type is an instance of Allocation or a TypeClass whose value is
      // expected to be assigned by programmer later in Java program. Therefore
      // we don't reflect things like [VarName] = new Allocation();
      C.indent() << VarName << " = null;" << std::endl;
      break;
    }
    case RSExportType::ExportClassConstantArray: {
      const RSExportConstantArrayType *ECAT =
          static_cast<const RSExportConstantArrayType *>(T);
      const RSExportType *ElementType = ECAT->getElementType();

      C.indent() << VarName << " = new " << GetTypeName(ElementType)
                 << "[" << ECAT->getSize() << "];" << std::endl;

      // Primitive type element doesn't need allocation code.
      if (ElementType->getClass() != RSExportType::ExportClassPrimitive) {
        C.indent() << "for (int $ct = 0; $ct < " << ECAT->getSize() << "; "
                            "$ct++)";
        C.startBlock();

        std::string ElementVarName(VarName);
        ElementVarName.append("[$ct]");
        genAllocateVarOfType(C, ElementType, ElementVarName);

        C.endBlock();
      }
      break;
    }
    case RSExportType::ExportClassVector:
    case RSExportType::ExportClassMatrix:
    case RSExportType::ExportClassRecord: {
      C.indent() << VarName << " = new " << GetTypeName(T) << "();"
                 << std::endl;
      break;
    }
  }
  return;
}

void RSReflection::genNewItemBufferIfNull(Context &C,
                                          const char *Index) {
  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_NAME " == null) "
                  RS_TYPE_ITEM_BUFFER_NAME " = "
                    "new " RS_TYPE_ITEM_CLASS_NAME
                      "[getType().getX() /* count */];"
             << std::endl;
  if (Index != NULL)
    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] == null) "
                    RS_TYPE_ITEM_BUFFER_NAME"[" << Index << "] = "
                      "new "RS_TYPE_ITEM_CLASS_NAME"();" << std::endl;
  return;
}

void RSReflection::genNewItemBufferPackerIfNull(Context &C) {
  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME " == null) "
                  RS_TYPE_ITEM_BUFFER_PACKER_NAME " = "
                    "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME
                      ".sizeof * getType().getX()/* count */"
                        ");" << std::endl;
  return;
}

/********************** Methods to generate type class  **********************/
bool RSReflection::genTypeClass(Context &C,
                                const RSExportRecordType *ERT,
                                std::string &ErrorMsg) {
  std::string ClassName = ERT->getElementName();

  if (!C.startClass(Context::AM_Public,
                    false,
                    ClassName,
                    RS_TYPE_CLASS_SUPER_CLASS_NAME,
                    ErrorMsg))
    return false;

  mGeneratedFileNames->push_back(ClassName);

  genTypeItemClass(C, ERT);

  // Declare item buffer and item buffer packer
  C.indent() << "private "RS_TYPE_ITEM_CLASS_NAME" "RS_TYPE_ITEM_BUFFER_NAME"[]"
      ";" << std::endl;
  C.indent() << "private FieldPacker "RS_TYPE_ITEM_BUFFER_PACKER_NAME";"
             << std::endl;
  C.indent() << "private static java.lang.ref.WeakReference<Element> "
             RS_TYPE_ELEMENT_REF_NAME
             " = new java.lang.ref.WeakReference<Element>(null);" << std::endl;

  genTypeClassConstructor(C, ERT);
  genTypeClassCopyToArrayLocal(C, ERT);
  genTypeClassCopyToArray(C, ERT);
  genTypeClassItemSetter(C, ERT);
  genTypeClassItemGetter(C, ERT);
  genTypeClassComponentSetter(C, ERT);
  genTypeClassComponentGetter(C, ERT);
  genTypeClassCopyAll(C, ERT);
  genTypeClassResize(C);

  C.endClass();

  C.resetFieldIndex();
  C.clearFieldIndexMap();

  return true;
}

void RSReflection::genTypeItemClass(Context &C,
                                    const RSExportRecordType *ERT) {
  C.indent() << "static public class "RS_TYPE_ITEM_CLASS_NAME;
  C.startBlock();

  C.indent() << "public static final int sizeof = "
             << RSExportType::GetTypeAllocSize(ERT) << ";" << std::endl;

  // Member elements
  C.out() << std::endl;
  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
           FE = ERT->fields_end();
       FI != FE;
       FI++) {
    C.indent() << GetTypeName((*FI)->getType()) << " " << (*FI)->getName()
               << ";" << std::endl;
  }

  // Constructor
  C.out() << std::endl;
  C.indent() << RS_TYPE_ITEM_CLASS_NAME"()";
  C.startBlock();

  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
           FE = ERT->fields_end();
       FI != FE;
       FI++) {
    const RSExportRecordType::Field *F = *FI;
    genAllocateVarOfType(C, F->getType(), F->getName());
  }

  // end Constructor
  C.endBlock();

  // end Item class
  C.endBlock();

  return;
}

void RSReflection::genTypeClassConstructor(Context &C,
                                           const RSExportRecordType *ERT) {
  const char *RenderScriptVar = "rs";

  C.startFunction(Context::AM_Public,
                  true,
                  "Element",
                  "createElement",
                  1,
                  "RenderScript", RenderScriptVar);

  // TODO(all): Fix weak-refs + multi-context issue.
  // C.indent() << "Element e = " << RS_TYPE_ELEMENT_REF_NAME
  //            << ".get();" << std::endl;
  // C.indent() << "if (e != null) return e;" << std::endl;
  genBuildElement(C, "eb", ERT, RenderScriptVar, /* IsInline = */true);
  C.indent() << "return eb.create();" << std::endl;
  // C.indent() << "e = eb.create();" << std::endl;
  // C.indent() << RS_TYPE_ELEMENT_REF_NAME
  //            << " = new java.lang.ref.WeakReference<Element>(e);"
  //            << std::endl;
  // C.indent() << "return e;" << std::endl;
  C.endFunction();


  // private with element
  C.startFunction(Context::AM_Private,
                  false,
                  NULL,
                  C.getClassName(),
                  1,
                  "RenderScript", RenderScriptVar);
  C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl;
  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl;
  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
             << std::endl;
  C.endFunction();

  // 1D without usage
  C.startFunction(Context::AM_Public,
                  false,
                  NULL,
                  C.getClassName(),
                  2,
                  "RenderScript", RenderScriptVar,
                  "int", "count");

  C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl;
  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl;
  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
             << std::endl;
  // Call init() in super class
  C.indent() << "init(" << RenderScriptVar << ", count);" << std::endl;
  C.endFunction();

  // 1D with usage
  C.startFunction(Context::AM_Public,
                  false,
                  NULL,
                  C.getClassName(),
                  3,
                  "RenderScript", RenderScriptVar,
                  "int", "count",
                  "int", "usages");

  C.indent() << RS_TYPE_ITEM_BUFFER_NAME" = null;" << std::endl;
  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME" = null;" << std::endl;
  C.indent() << "mElement = createElement(" << RenderScriptVar << ");"
             << std::endl;
  // Call init() in super class
  C.indent() << "init(" << RenderScriptVar << ", count, usages);" << std::endl;
  C.endFunction();


  // create1D with usage
  C.startFunction(Context::AM_Public,
                  true,
                  C.getClassName().c_str(),
                  "create1D",
                  3,
                  "RenderScript", RenderScriptVar,
                  "int", "dimX",
                  "int", "usages");
  C.indent() << C.getClassName() << " obj = new " << C.getClassName() << "("
             << RenderScriptVar << ");" << std::endl;
  C.indent() << "obj.mAllocation = Allocation.createSized("
                "rs, obj.mElement, dimX, usages);" << std::endl;
  C.indent() << "return obj;" << std::endl;
  C.endFunction();

  // create1D without usage
  C.startFunction(Context::AM_Public,
                  true,
                  C.getClassName().c_str(),
                  "create1D",
                  2,
                  "RenderScript", RenderScriptVar,
                  "int", "dimX");
  C.indent() << "return create1D(" << RenderScriptVar
             << ", dimX, Allocation.USAGE_SCRIPT);" << std::endl;
  C.endFunction();


  // create2D without usage
  C.startFunction(Context::AM_Public,
                  true,
                  C.getClassName().c_str(),
                  "create2D",
                  3,
                  "RenderScript", RenderScriptVar,
                  "int", "dimX",
                  "int", "dimY");
  C.indent() << "return create2D(" << RenderScriptVar
             << ", dimX, dimY, Allocation.USAGE_SCRIPT);" << std::endl;
  C.endFunction();

  // create2D with usage
  C.startFunction(Context::AM_Public,
                  true,
                  C.getClassName().c_str(),
                  "create2D",
                  4,
                  "RenderScript", RenderScriptVar,
                  "int", "dimX",
                  "int", "dimY",
                  "int", "usages");

  C.indent() << C.getClassName() << " obj = new " << C.getClassName() << "("
             << RenderScriptVar << ");" << std::endl;
  C.indent() << "Type.Builder b = new Type.Builder(rs, obj.mElement);"
             << std::endl;
  C.indent() << "b.setX(dimX);" << std::endl;
  C.indent() << "b.setY(dimY);" << std::endl;
  C.indent() << "Type t = b.create();" << std::endl;
  C.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);"
             << std::endl;
  C.indent() << "return obj;" << std::endl;
  C.endFunction();


  // createTypeBuilder
  C.startFunction(Context::AM_Public,
                  true,
                  "Type.Builder",
                  "createTypeBuilder",
                  1,
                  "RenderScript", RenderScriptVar);
  C.indent() << "Element e = createElement(" << RenderScriptVar << ");"
             << std::endl;
  C.indent() << "return new Type.Builder(rs, e);" << std::endl;
  C.endFunction();

  // createCustom with usage
  C.startFunction(Context::AM_Public,
                  true,
                  C.getClassName().c_str(),
                  "createCustom",
                  3,
                  "RenderScript", RenderScriptVar,
                  "Type.Builder", "tb",
                  "int", "usages");
  C.indent() << C.getClassName() << " obj = new " << C.getClassName() << "("
             << RenderScriptVar << ");" << std::endl;
  C.indent() << "Type t = tb.create();" << std::endl;
  C.indent() << "if (t.getElement() != obj.mElement) {" << std::endl;
  C.indent() << "    throw new RSIllegalArgumentException("
                "\"Type.Builder did not match expected element type.\");"
             << std::endl;
  C.indent() << "}" << std::endl;
  C.indent() << "obj.mAllocation = Allocation.createTyped(rs, t, usages);"
             << std::endl;
  C.indent() << "return obj;" << std::endl;
  C.endFunction();
}


void RSReflection::genTypeClassCopyToArray(Context &C,
                                           const RSExportRecordType *ERT) {
  C.startFunction(Context::AM_Private,
                  false,
                  "void",
                  "copyToArray",
                  2,
                  RS_TYPE_ITEM_CLASS_NAME, "i",
                  "int", "index");

  genNewItemBufferPackerIfNull(C);
  C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
                ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);"
             << std::endl;

  C.indent() << "copyToArrayLocal(i, " RS_TYPE_ITEM_BUFFER_PACKER_NAME
                ");" << std::endl;

  C.endFunction();
  return;
}

void RSReflection::genTypeClassCopyToArrayLocal(Context &C,
                                                const RSExportRecordType *ERT) {
  C.startFunction(Context::AM_Private,
                  false,
                  "void",
                  "copyToArrayLocal",
                  2,
                  RS_TYPE_ITEM_CLASS_NAME, "i",
                  "FieldPacker", "fp");

  genPackVarOfType(C, ERT, "i", "fp");

  C.endFunction();
  return;
}

void RSReflection::genTypeClassItemSetter(Context &C,
                                          const RSExportRecordType *ERT) {
  C.startFunction(Context::AM_PublicSynchronized,
                  false,
                  "void",
                  "set",
                  3,
                  RS_TYPE_ITEM_CLASS_NAME, "i",
                  "int", "index",
                  "boolean", "copyNow");
  genNewItemBufferIfNull(C, NULL);
  C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index] = i;" << std::endl;

  C.indent() << "if (copyNow) ";
  C.startBlock();

  C.indent() << "copyToArray(i, index);" << std::endl;
  C.indent() << "FieldPacker fp = new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME
                ".sizeof);" << std::endl;
  C.indent() << "copyToArrayLocal(i, fp);" << std::endl;
  C.indent() << "mAllocation.setFromFieldPacker(index, fp);" << std::endl;

  // End of if (copyNow)
  C.endBlock();

  C.endFunction();
  return;
}

void RSReflection::genTypeClassItemGetter(Context &C,
                                          const RSExportRecordType *ERT) {
  C.startFunction(Context::AM_PublicSynchronized,
                  false,
                  RS_TYPE_ITEM_CLASS_NAME,
                  "get",
                  1,
                  "int", "index");
  C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return null;"
             << std::endl;
  C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index];" << std::endl;
  C.endFunction();
  return;
}

void RSReflection::genTypeClassComponentSetter(Context &C,
                                               const RSExportRecordType *ERT) {
  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
           FE = ERT->fields_end();
       FI != FE;
       FI++) {
    const RSExportRecordType::Field *F = *FI;
    size_t FieldOffset = F->getOffsetInParent();
    size_t FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
    unsigned FieldIndex = C.getFieldIndex(F);

    C.startFunction(Context::AM_PublicSynchronized,
                    false,
                    "void",
                    "set_" + F->getName(), 3,
                    "int", "index",
                    GetTypeName(F->getType()).c_str(), "v",
                    "boolean", "copyNow");
    genNewItemBufferPackerIfNull(C);
    genNewItemBufferIfNull(C, "index");
    C.indent() << RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
               << " = v;" << std::endl;

    C.indent() << "if (copyNow) ";
    C.startBlock();

    if (FieldOffset > 0)
      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
                    ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof + "
                 << FieldOffset << ");" << std::endl;
    else
      C.indent() << RS_TYPE_ITEM_BUFFER_PACKER_NAME
                    ".reset(index * "RS_TYPE_ITEM_CLASS_NAME".sizeof);"
                 << std::endl;
    genPackVarOfType(C, F->getType(), "v", RS_TYPE_ITEM_BUFFER_PACKER_NAME);

    C.indent() << "FieldPacker fp = new FieldPacker(" << FieldStoreSize << ");"
               << std::endl;
    genPackVarOfType(C, F->getType(), "v", "fp");
    C.indent() << "mAllocation.setFromFieldPacker(index, " << FieldIndex
               << ", fp);"
               << std::endl;

    // End of if (copyNow)
    C.endBlock();

    C.endFunction();
  }
  return;
}

void RSReflection::genTypeClassComponentGetter(Context &C,
                                               const RSExportRecordType *ERT) {
  for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
           FE = ERT->fields_end();
       FI != FE;
       FI++) {
    const RSExportRecordType::Field *F = *FI;
    C.startFunction(Context::AM_PublicSynchronized,
                    false,
                    GetTypeName(F->getType()).c_str(),
                    "get_" + F->getName(),
                    1,
                    "int", "index");
    C.indent() << "if ("RS_TYPE_ITEM_BUFFER_NAME" == null) return "
               << GetTypeNullValue(F->getType()) << ";" << std::endl;
    C.indent() << "return "RS_TYPE_ITEM_BUFFER_NAME"[index]." << F->getName()
               << ";" << std::endl;
    C.endFunction();
  }
  return;
}

void RSReflection::genTypeClassCopyAll(Context &C,
                                       const RSExportRecordType *ERT) {
  C.startFunction(Context::AM_PublicSynchronized, false, "void", "copyAll", 0);

  C.indent() << "for (int ct = 0; ct < "RS_TYPE_ITEM_BUFFER_NAME".length; ct++)"
                  " copyToArray("RS_TYPE_ITEM_BUFFER_NAME"[ct], ct);"
             << std::endl;
  C.indent() << "mAllocation.setFromFieldPacker(0, "
                  RS_TYPE_ITEM_BUFFER_PACKER_NAME");"
             << std::endl;

  C.endFunction();
  return;
}

void RSReflection::genTypeClassResize(Context &C) {
  C.startFunction(Context::AM_PublicSynchronized,
                  false,
                  "void",
                  "resize",
                  1,
                  "int", "newSize");

  C.indent() << "if (mItemArray != null) ";
  C.startBlock();
  C.indent() << "int oldSize = mItemArray.length;" << std::endl;
  C.indent() << "int copySize = Math.min(oldSize, newSize);" << std::endl;
  C.indent() << "if (newSize == oldSize) return;" << std::endl;
  C.indent() << "Item ni[] = new Item[newSize];" << std::endl;
  C.indent() << "System.arraycopy(mItemArray, 0, ni, 0, copySize);"
             << std::endl;
  C.indent() << "mItemArray = ni;" << std::endl;
  C.endBlock();
  C.indent() << "mAllocation.resize(newSize);" << std::endl;

  C.indent() << "if (" RS_TYPE_ITEM_BUFFER_PACKER_NAME " != null) "
                  RS_TYPE_ITEM_BUFFER_PACKER_NAME " = "
                    "new FieldPacker(" RS_TYPE_ITEM_CLASS_NAME
                      ".sizeof * getType().getX()/* count */"
                        ");" << std::endl;

  C.endFunction();
  return;
}

/******************** Methods to generate type class /end ********************/

/********** Methods to create Element in Java of given record type ***********/
void RSReflection::genBuildElement(Context &C,
                                   const char *ElementBuilderName,
                                   const RSExportRecordType *ERT,
                                   const char *RenderScriptVar,
                                   bool IsInline) {
  C.indent() << "Element.Builder " << ElementBuilderName << " = "
      "new Element.Builder(" << RenderScriptVar << ");" << std::endl;

  // eb.add(...)
  genAddElementToElementBuilder(C,
                                ERT,
                                "",
                                ElementBuilderName,
                                RenderScriptVar,
                                /* ArraySize = */0);

  if (!IsInline)
    C.indent() << "return " << ElementBuilderName << ".create();" << std::endl;
  return;
}

#define EB_ADD(x) do {                                              \
  C.indent() << ElementBuilderName                                  \
             << ".add(" << x << ", \"" << VarName << "\"";  \
  if (ArraySize > 0)                                                \
    C.out() << ", " << ArraySize;                                   \
  C.out() << ");" << std::endl;                                     \
  C.incFieldIndex();                                                \
} while (false)

void RSReflection::genAddElementToElementBuilder(Context &C,
                                                 const RSExportType *ET,
                                                 const std::string &VarName,
                                                 const char *ElementBuilderName,
                                                 const char *RenderScriptVar,
                                                 unsigned ArraySize) {
  std::string ElementConstruct = GetBuiltinElementConstruct(ET);

  if (ElementConstruct != "") {
    EB_ADD(ElementConstruct << "(" << RenderScriptVar << ")");
  } else {
    if ((ET->getClass() == RSExportType::ExportClassPrimitive) ||
        (ET->getClass() == RSExportType::ExportClassVector)) {
      const RSExportPrimitiveType *EPT =
          static_cast<const RSExportPrimitiveType*>(ET);
      const char *DataTypeName =
          RSExportPrimitiveType::getRSReflectionType(EPT)->rs_type;
      int Size = (ET->getClass() == RSExportType::ExportClassVector) ?
          static_cast<const RSExportVectorType*>(ET)->getNumElement() :
          1;

      if (EPT->getClass() == RSExportType::ExportClassPrimitive) {
        // Element.createUser()
        EB_ADD("Element.createUser(" << RenderScriptVar
                                     << ", Element.DataType."
                                     << DataTypeName << ")");
      } else {
        slangAssert((ET->getClass() == RSExportType::ExportClassVector) &&
                    "Unexpected type.");
        EB_ADD("Element.createVector(" << RenderScriptVar
                                       << ", Element.DataType."
                                       << DataTypeName << ", "
                                       << Size << ")");
      }
#ifndef NDEBUG
    } else if (ET->getClass() == RSExportType::ExportClassPointer) {
      // Pointer type variable should be resolved in
      // GetBuiltinElementConstruct()
      slangAssert(false && "??");
    } else if (ET->getClass() == RSExportType::ExportClassMatrix) {
      // Matrix type variable should be resolved
      // in GetBuiltinElementConstruct()
      slangAssert(false && "??");
#endif
    } else if (ET->getClass() == RSExportType::ExportClassConstantArray) {
      const RSExportConstantArrayType *ECAT =
          static_cast<const RSExportConstantArrayType *>(ET);

      const RSExportType *ElementType = ECAT->getElementType();
      if (ElementType->getClass() != RSExportType::ExportClassRecord) {
        genAddElementToElementBuilder(C,
                                      ECAT->getElementType(),
                                      VarName,
                                      ElementBuilderName,
                                      RenderScriptVar,
                                      ECAT->getSize());
      } else {
        std::string NewElementBuilderName(ElementBuilderName);
        NewElementBuilderName.append(1, '_');

        genBuildElement(C,
                        NewElementBuilderName.c_str(),
                        static_cast<const RSExportRecordType*>(ElementType),
                        RenderScriptVar,
                        /* IsInline = */true);
        ArraySize = ECAT->getSize();
        EB_ADD(NewElementBuilderName << ".create()");
      }
    } else if (ET->getClass() == RSExportType::ExportClassRecord) {
      // Simalar to case of RSExportType::ExportClassRecord in genPackVarOfType.
      //
      // TODO(zonr): Generalize these two function such that there's no
      //             duplicated codes.
      const RSExportRecordType *ERT =
          static_cast<const RSExportRecordType*>(ET);
      int Pos = 0;    // relative pos from now on

      for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(),
               E = ERT->fields_end();
           I != E;
           I++) {
        const RSExportRecordType::Field *F = *I;
        std::string FieldName;
        int FieldOffset = F->getOffsetInParent();
        int FieldStoreSize = RSExportType::GetTypeStoreSize(F->getType());
        int FieldAllocSize = RSExportType::GetTypeAllocSize(F->getType());

        if (!VarName.empty())
          FieldName = VarName + "." + F->getName();
        else
          FieldName = F->getName();

        // Alignment
        genAddPaddingToElementBuiler(C,
                                     (FieldOffset - Pos),
                                     ElementBuilderName,
                                     RenderScriptVar);

        // eb.add(...)
        C.addFieldIndexMapping(F);
        if (F->getType()->getClass() != RSExportType::ExportClassRecord) {
          genAddElementToElementBuilder(C,
                                        F->getType(),
                                        FieldName,
                                        ElementBuilderName,
                                        RenderScriptVar,
                                        0);
        } else {
          std::string NewElementBuilderName(ElementBuilderName);
          NewElementBuilderName.append(1, '_');

          genBuildElement(C,
                          NewElementBuilderName.c_str(),
                          static_cast<const RSExportRecordType*>(F->getType()),
                          RenderScriptVar,
                          /* IsInline = */true);

          const std::string &VarName = FieldName;  // Hack for EB_ADD macro
          EB_ADD(NewElementBuilderName << ".create()");
        }

        if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
          // There is padding within the field type. This is only necessary
          // for HC-targeted APIs.
          genAddPaddingToElementBuiler(C,
                                       (FieldAllocSize - FieldStoreSize),
                                       ElementBuilderName,
                                       RenderScriptVar);
        }

        Pos = FieldOffset + FieldAllocSize;
      }

      // There maybe some padding after the struct
      size_t RecordAllocSize = RSExportType::GetTypeAllocSize(ERT);

      genAddPaddingToElementBuiler(C,
                                   RecordAllocSize - Pos,
                                   ElementBuilderName,
                                   RenderScriptVar);
    } else {
      slangAssert(false && "Unknown class of type");
    }
  }
}

void RSReflection::genAddPaddingToElementBuiler(Context &C,
                                                int PaddingSize,
                                                const char *ElementBuilderName,
                                                const char *RenderScriptVar) {
  unsigned ArraySize = 0;   // Hack the EB_ADD macro
  while (PaddingSize > 0) {
    const std::string &VarName = C.createPaddingField();
    if (PaddingSize >= 4) {
      EB_ADD("Element.U32(" << RenderScriptVar << ")");
      PaddingSize -= 4;
    } else if (PaddingSize >= 2) {
      EB_ADD("Element.U16(" << RenderScriptVar << ")");
      PaddingSize -= 2;
    } else if (PaddingSize >= 1) {
      EB_ADD("Element.U8(" << RenderScriptVar << ")");
      PaddingSize -= 1;
    }
  }
  return;
}

#undef EB_ADD
/******** Methods to create Element in Java of given record type /end ********/

bool RSReflection::reflect(const std::string &OutputPathBase,
                           const std::string &OutputPackageName,
                           const std::string &RSPackageName,
                           const std::string &InputFileName,
                           const std::string &OutputBCFileName) {
  Context *C = NULL;
  std::string ResourceId = "";
  std::string PaddingPrefix = "";

  if (mRSContext->getTargetAPI() < SLANG_ICS_TARGET_API) {
    PaddingPrefix = "#padding_";
  } else {
    PaddingPrefix = "#rs_padding_";
  }

  if (!GetClassNameFromFileName(OutputBCFileName, ResourceId))
    return false;

  if (ResourceId.empty())
    ResourceId = "<Resource ID>";

  if (OutputPackageName.empty() || OutputPackageName == "-")
    C = new Context(OutputPathBase, InputFileName, "<Package Name>",
                    RSPackageName, ResourceId, PaddingPrefix, true);
  else
    C = new Context(OutputPathBase, InputFileName, OutputPackageName,
                    RSPackageName, ResourceId, PaddingPrefix, false);

  if (C != NULL) {
    std::string ErrorMsg, ScriptClassName;
    // class ScriptC_<ScriptName>
    if (!GetClassNameFromFileName(InputFileName, ScriptClassName))
      return false;

    if (ScriptClassName.empty())
      ScriptClassName = "<Input Script Name>";

    ScriptClassName.insert(0, RS_SCRIPT_CLASS_NAME_PREFIX);

    if (mRSContext->getLicenseNote() != NULL) {
      C->setLicenseNote(*(mRSContext->getLicenseNote()));
    }

    if (!genScriptClass(*C, ScriptClassName, ErrorMsg)) {
      std::cerr << "Failed to generate class " << ScriptClassName << " ("
                << ErrorMsg << ")" << std::endl;
      return false;
    }

    mGeneratedFileNames->push_back(ScriptClassName);

    // class ScriptField_<TypeName>
    for (RSContext::const_export_type_iterator TI =
             mRSContext->export_types_begin(),
             TE = mRSContext->export_types_end();
         TI != TE;
         TI++) {
      const RSExportType *ET = TI->getValue();

      if (ET->getClass() == RSExportType::ExportClassRecord) {
        const RSExportRecordType *ERT =
            static_cast<const RSExportRecordType*>(ET);

        if (!ERT->isArtificial() && !genTypeClass(*C, ERT, ErrorMsg)) {
          std::cerr << "Failed to generate type class for struct '"
                    << ERT->getName() << "' (" << ErrorMsg << ")" << std::endl;
          return false;
        }
      }
    }
  }

  return true;
}

/************************** RSReflection::Context **************************/
const char *const RSReflection::Context::ApacheLicenseNote =
    "/*\n"
    " * Copyright (C) 2011-2012 The Android Open Source Project\n"
    " *\n"
    " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
    " * you may not use this file except in compliance with the License.\n"
    " * You may obtain a copy of the License at\n"
    " *\n"
    " *      http://www.apache.org/licenses/LICENSE-2.0\n"
    " *\n"
    " * Unless required by applicable law or agreed to in writing, software\n"
    " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
    " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
    "implied.\n"
    " * See the License for the specific language governing permissions and\n"
    " * limitations under the License.\n"
    " */\n"
    "\n";

bool RSReflection::Context::openClassFile(const std::string &ClassName,
                                          std::string &ErrorMsg) {
  if (!mUseStdout) {
    mOF.clear();
    std::string Path =
        RSSlangReflectUtils::ComputePackagedPath(mOutputPathBase.c_str(),
                                                 mPackageName.c_str());

    if (!SlangUtils::CreateDirectoryWithParents(Path, &ErrorMsg))
      return false;

    std::string ClassFile = Path + OS_PATH_SEPARATOR_STR + ClassName + ".java";

    mOF.open(ClassFile.c_str());
    if (!mOF.good()) {
      ErrorMsg = "failed to open file '" + ClassFile + "' for write";
      return false;
    }
  }
  return true;
}

const char *RSReflection::Context::AccessModifierStr(AccessModifier AM) {
  switch (AM) {
    case AM_Public: return "public"; break;
    case AM_Protected: return "protected"; break;
    case AM_Private: return "private"; break;
    case AM_PublicSynchronized: return "public synchronized"; break;
    default: return ""; break;
  }
}

bool RSReflection::Context::startClass(AccessModifier AM,
                                       bool IsStatic,
                                       const std::string &ClassName,
                                       const char *SuperClassName,
                                       std::string &ErrorMsg) {
  if (mVerbose)
    std::cout << "Generating " << ClassName << ".java ..." << std::endl;

  // Open file for class
  if (!openClassFile(ClassName, ErrorMsg))
    return false;

  // License
  out() << mLicenseNote;

  // Notice of generated file
  out() << "/*" << std::endl;
  out() << " * This file is auto-generated. DO NOT MODIFY!" << std::endl;
  out() << " * The source Renderscript file: " << mInputRSFile << std::endl;
  out() << " */" << std::endl;

  // Package
  if (!mPackageName.empty())
    out() << "package " << mPackageName << ";" << std::endl;
  out() << std::endl;

  // Imports
  out() << "import " << mRSPackageName << ".*;" << std::endl;
  out() << "import android.content.res.Resources;" << std::endl;
  out() << std::endl;

  // All reflected classes should be annotated as hidden, so that they won't
  // be exposed in SDK.
  out() << "/**" << std::endl;
  out() << " * @hide" << std::endl;
  out() << " */" << std::endl;

  out() << AccessModifierStr(AM) << ((IsStatic) ? " static" : "") << " class "
        << ClassName;
  if (SuperClassName != NULL)
    out() << " extends " << SuperClassName;

  startBlock();

  mClassName = ClassName;

  return true;
}

void RSReflection::Context::endClass() {
  endBlock();
  if (!mUseStdout)
    mOF.close();
  clear();
  return;
}

void RSReflection::Context::startBlock(bool ShouldIndent) {
  if (ShouldIndent)
    indent() << "{" << std::endl;
  else
    out() << " {" << std::endl;
  incIndentLevel();
  return;
}

void RSReflection::Context::endBlock() {
  decIndentLevel();
  indent() << "}" << std::endl << std::endl;
  return;
}

void RSReflection::Context::startTypeClass(const std::string &ClassName) {
  indent() << "public static class " << ClassName;
  startBlock();
  return;
}

void RSReflection::Context::endTypeClass() {
  endBlock();
  return;
}

void RSReflection::Context::startFunction(AccessModifier AM,
                                          bool IsStatic,
                                          const char *ReturnType,
                                          const std::string &FunctionName,
                                          int Argc, ...) {
  ArgTy Args;
  va_list vl;
  va_start(vl, Argc);

  for (int i = 0; i < Argc; i++) {
    const char *ArgType = va_arg(vl, const char*);
    const char *ArgName = va_arg(vl, const char*);

    Args.push_back(std::make_pair(ArgType, ArgName));
  }
  va_end(vl);

  startFunction(AM, IsStatic, ReturnType, FunctionName, Args);

  return;
}

void RSReflection::Context::startFunction(AccessModifier AM,
                                          bool IsStatic,
                                          const char *ReturnType,
                                          const std::string &FunctionName,
                                          const ArgTy &Args) {
  indent() << AccessModifierStr(AM) << ((IsStatic) ? " static " : " ")
           << ((ReturnType) ? ReturnType : "") << " " << FunctionName << "(";

  bool FirstArg = true;
  for (ArgTy::const_iterator I = Args.begin(), E = Args.end();
       I != E;
       I++) {
    if (!FirstArg)
      out() << ", ";
    else
      FirstArg = false;

    out() << I->first << " " << I->second;
  }

  out() << ")";
  startBlock();

  return;
}

void RSReflection::Context::endFunction() {
  endBlock();
  return;
}

bool RSReflection::Context::addTypeNameForElement(
    const std::string &TypeName) {
  if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
    mTypesToCheck.insert(TypeName);
    return true;
  } else {
    return false;
  }
}

bool RSReflection::Context::addTypeNameForFieldPacker(
    const std::string &TypeName) {
  if (mFieldPackerTypes.find(TypeName) == mFieldPackerTypes.end()) {
    mFieldPackerTypes.insert(TypeName);
    return true;
  } else {
    return false;
  }
}

}  // namespace slang
