/* * 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. */ #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_ // NOLINT #define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_ #include <fstream> #include <iostream> #include <map> #include <set> #include <string> #include <vector> #include "llvm/ADT/StringExtras.h" #include "slang_assert.h" #include "slang_rs_export_type.h" namespace slang { class RSContext; class RSExportVar; class RSExportFunc; class RSExportForEach; class RSReflection { private: const RSContext *mRSContext; std::string mLastError; std::vector<std::string> *mGeneratedFileNames; inline void setError(const std::string &Error) { mLastError = Error; } class Context { private: static const char *const ApacheLicenseNote; bool mVerbose; std::string mOutputPathBase; std::string mInputRSFile; std::string mPackageName; std::string mRSPackageName; std::string mResourceId; std::string mPaddingPrefix; std::string mClassName; std::string mLicenseNote; std::string mIndent; int mPaddingFieldIndex; int mNextExportVarSlot; int mNextExportFuncSlot; int mNextExportForEachSlot; // A mapping from a field in a record type to its index in the rsType // instance. Only used when generates TypeClass (ScriptField_*). typedef std::map<const RSExportRecordType::Field*, unsigned> FieldIndexMapTy; FieldIndexMapTy mFieldIndexMap; // Field index of current processing TypeClass. unsigned mFieldIndex; inline void clear() { mClassName = ""; mIndent = ""; mPaddingFieldIndex = 1; mNextExportVarSlot = 0; mNextExportFuncSlot = 0; mNextExportForEachSlot = 0; return; } bool openClassFile(const std::string &ClassName, std::string &ErrorMsg); public: typedef enum { AM_Public, AM_Protected, AM_Private, AM_PublicSynchronized } AccessModifier; bool mUseStdout; mutable std::ofstream mOF; // Generated RS Elements for type-checking code. std::set<std::string> mTypesToCheck; // Generated FieldPackers for unsigned setters/validation. std::set<std::string> mFieldPackerTypes; bool addTypeNameForElement(const std::string &TypeName); bool addTypeNameForFieldPacker(const std::string &TypeName); static const char *AccessModifierStr(AccessModifier AM); Context(const std::string &OutputPathBase, const std::string &InputRSFile, const std::string &PackageName, const std::string &RSPackageName, const std::string &ResourceId, const std::string &PaddingPrefix, bool UseStdout) : mVerbose(true), mOutputPathBase(OutputPathBase), mInputRSFile(InputRSFile), mPackageName(PackageName), mRSPackageName(RSPackageName), mResourceId(ResourceId), mPaddingPrefix(PaddingPrefix), mLicenseNote(ApacheLicenseNote), mUseStdout(UseStdout) { clear(); resetFieldIndex(); clearFieldIndexMap(); return; } inline std::ostream &out() const { return ((mUseStdout) ? std::cout : mOF); } inline std::ostream &indent() const { out() << mIndent; return out(); } inline void incIndentLevel() { mIndent.append(4, ' '); return; } inline void decIndentLevel() { slangAssert(getIndentLevel() > 0 && "No indent"); mIndent.erase(0, 4); return; } inline int getIndentLevel() { return (mIndent.length() >> 2); } inline int getNextExportVarSlot() { return mNextExportVarSlot++; } inline int getNextExportFuncSlot() { return mNextExportFuncSlot++; } inline int getNextExportForEachSlot() { return mNextExportForEachSlot++; } // Will remove later due to field name information is not necessary for // C-reflect-to-Java inline std::string createPaddingField() { return mPaddingPrefix + llvm::itostr(mPaddingFieldIndex++); } inline void setLicenseNote(const std::string &LicenseNote) { mLicenseNote = LicenseNote; } bool startClass(AccessModifier AM, bool IsStatic, const std::string &ClassName, const char *SuperClassName, std::string &ErrorMsg); void endClass(); void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType, const std::string &FunctionName, int Argc, ...); typedef std::vector<std::pair<std::string, std::string> > ArgTy; void startFunction(AccessModifier AM, bool IsStatic, const char *ReturnType, const std::string &FunctionName, const ArgTy &Args); void endFunction(); void startBlock(bool ShouldIndent = false); void endBlock(); inline const std::string &getPackageName() const { return mPackageName; } inline const std::string &getRSPackageName() const { return mRSPackageName; } inline const std::string &getClassName() const { return mClassName; } inline const std::string &getResourceId() const { return mResourceId; } void startTypeClass(const std::string &ClassName); void endTypeClass(); inline void incFieldIndex() { mFieldIndex++; } inline void resetFieldIndex() { mFieldIndex = 0; } inline void addFieldIndexMapping(const RSExportRecordType::Field *F) { slangAssert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) && "Nested structure never occurs in C language."); mFieldIndexMap.insert(std::make_pair(F, mFieldIndex)); } inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const { FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F); slangAssert((I != mFieldIndexMap.end()) && "Requesting field is out of scope."); return I->second; } inline void clearFieldIndexMap() { mFieldIndexMap.clear(); } }; bool genScriptClass(Context &C, const std::string &ClassName, std::string &ErrorMsg); void genScriptClassConstructor(Context &C); static void genInitBoolExportVariable(Context &C, const std::string &VarName, const clang::APValue &Val); static void genInitPrimitiveExportVariable(Context &C, const std::string &VarName, const clang::APValue &Val); static void genInitExportVariable(Context &C, const RSExportType *ET, const std::string &VarName, const clang::APValue &Val); static void genInitValue(Context &C, const clang::APValue &Val); void genExportVariable(Context &C, const RSExportVar *EV); void genPrimitiveTypeExportVariable(Context &C, const RSExportVar *EV); void genPointerTypeExportVariable(Context &C, const RSExportVar *EV); void genVectorTypeExportVariable(Context &C, const RSExportVar *EV); void genMatrixTypeExportVariable(Context &C, const RSExportVar *EV); void genConstantArrayTypeExportVariable(Context &C, const RSExportVar *EV); void genRecordTypeExportVariable(Context &C, const RSExportVar *EV); void genPrivateExportVariable(Context &C, const std::string &TypeName, const std::string &VarName); void genSetExportVariable(Context &C, const std::string &TypeName, const RSExportVar *EV); void genGetExportVariable(Context &C, const std::string &TypeName, const std::string &VarName); void genGetFieldID(Context &C, const std::string &VarName); void genExportFunction(Context &C, const RSExportFunc *EF); void genExportForEach(Context &C, const RSExportForEach *EF); static void genTypeCheck(Context &C, const RSExportType *ET, const char *VarName); static void genTypeInstanceFromPointer(Context &C, const RSExportType *ET); static void genTypeInstance(Context &C, const RSExportType *ET); static void genFieldPackerInstance(Context &C, const RSExportType *ET); bool genTypeClass(Context &C, const RSExportRecordType *ERT, std::string &ErrorMsg); void genTypeItemClass(Context &C, const RSExportRecordType *ERT); void genTypeClassConstructor(Context &C, const RSExportRecordType *ERT); void genTypeClassCopyToArray(Context &C, const RSExportRecordType *ERT); void genTypeClassCopyToArrayLocal(Context &C, const RSExportRecordType *ERT); void genTypeClassItemSetter(Context &C, const RSExportRecordType *ERT); void genTypeClassItemGetter(Context &C, const RSExportRecordType *ERT); void genTypeClassComponentSetter(Context &C, const RSExportRecordType *ERT); void genTypeClassComponentGetter(Context &C, const RSExportRecordType *ERT); void genTypeClassCopyAll(Context &C, const RSExportRecordType *ERT); void genTypeClassResize(Context &C); void genBuildElement(Context &C, const char *ElementBuilderName, const RSExportRecordType *ERT, const char *RenderScriptVar, bool IsInline); void genAddElementToElementBuilder(Context &C, const RSExportType *ERT, const std::string &VarName, const char *ElementBuilderName, const char *RenderScriptVar, unsigned ArraySize); void genAddPaddingToElementBuiler(Context &C, int PaddingSize, const char *ElementBuilderName, const char *RenderScriptVar); bool genCreateFieldPacker(Context &C, const RSExportType *T, const char *FieldPackerName); void genPackVarOfType(Context &C, const RSExportType *T, const char *VarName, const char *FieldPackerName); void genAllocateVarOfType(Context &C, const RSExportType *T, const std::string &VarName); void genNewItemBufferIfNull(Context &C, const char *Index); void genNewItemBufferPackerIfNull(Context &C); public: explicit RSReflection(const RSContext *Context, std::vector<std::string> *GeneratedFileNames) : mRSContext(Context), mLastError(""), mGeneratedFileNames(GeneratedFileNames) { slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames"); return; } bool reflect(const std::string &OutputPathBase, const std::string &OutputPackageName, const std::string &RSPackageName, const std::string &InputFileName, const std::string &OutputBCFileName); inline const char *getLastError() const { if (mLastError.empty()) return NULL; else return mLastError.c_str(); } }; // class RSReflection } // namespace slang #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_REFLECTION_H_ NOLINT