/* * Copyright 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 <sys/stat.h> #include <cstdarg> #include <cctype> #include <algorithm> #include <limits> #include <sstream> #include <string> #include <utility> #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" using namespace std; namespace slang { static const char *const gApacheLicenseNote = "/*\n" " * Copyright (C) 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"; RSReflectionBase::RSReflectionBase(const RSContext *con) : mVerbose(true) { mRSContext = con; mLicenseNote = gApacheLicenseNote; } RSReflectionBase::~RSReflectionBase() { } /* bool RSReflectionBase::openFile(const string &name, string &errorMsg) { if(!mUseStdout) { mOF.clear(); if(!SlangUtils::CreateDirectoryWithParents(mOutputPath, &errorMsg)) { return false; } string cf(mOutputPath + OS_PATH_SEPARATOR_STR + name); mOF.open(cf.c_str()); if(!mOF.good()) { errorMsg = "failed to open file '" + cf + "' for write"; return false; } } return true; } */ void RSReflectionBase::startFile(const string &filename) { if(mVerbose) { printf("Generating %s\n", filename.c_str()); } // License write(mLicenseNote); // Notice of generated file write("/*"); write(" * This file is auto-generated. DO NOT MODIFY!"); write(" * The source Renderscript file: " + mInputFileName); write(" */"); write(""); } // remove path plus .rs from filename to generate class name string RSReflectionBase::stripRS(const string &s) const { string tmp(s); size_t pos = tmp.rfind(".rs"); if(pos != string::npos) { tmp.erase(pos); } pos = tmp.rfind("/"); if (pos != string::npos) { tmp.erase(0, pos+1); } return tmp; } void RSReflectionBase::write(const std::string &t) { //printf("%s%s\n", mIndent.c_str(), t.c_str()); mText.push_back(mIndent + t); } void RSReflectionBase::write(const std::stringstream &t) { mText.push_back(mIndent + t.str()); } void RSReflectionBase::incIndent() { mIndent.append(" "); } void RSReflectionBase::decIndent() { mIndent.erase(0, 4); } bool RSReflectionBase::writeFile(const string &filename, const vector< string > &txt) { FILE *pfin = fopen((mOutputPath + filename).c_str(), "wt"); if (pfin == NULL) { fprintf(stderr, "Error: could not write file %s\n", filename.c_str()); return false; } for(size_t ct=0; ct < txt.size(); ct++) { fprintf(pfin, "%s\n", txt[ct].c_str()); } fclose(pfin); return true; } string RSReflectionBase::genInitValue(const clang::APValue &Val, bool asBool) { stringstream tmp; switch (Val.getKind()) { case clang::APValue::Int: { llvm::APInt api = Val.getInt(); if(asBool) { tmp << ((api.getSExtValue() == 0) ? "false" : "true"); } else { // TODO: Handle unsigned possibly for C++ API. tmp << api.getSExtValue(); if (api.getBitWidth() > 32) { tmp << "L"; } } break; } case clang::APValue::Float: { llvm::APFloat apf = Val.getFloat(); llvm::SmallString<30> s; apf.toString(s); tmp << s.c_str(); if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) { if (s.count('.') == 0) { tmp << ".f"; } else { tmp << "f"; } } break; } case clang::APValue::ComplexInt: case clang::APValue::ComplexFloat: case clang::APValue::LValue: case clang::APValue::Vector: { slangAssert(false && "Primitive type cannot have such kind of initializer"); break; } default: { slangAssert(false && "Unknown kind of initializer"); } } return tmp.str(); } bool RSReflectionBase::addTypeNameForElement( const std::string &TypeName) { if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) { mTypesToCheck.insert(TypeName); return true; } else { return false; } } const char *RSReflectionBase::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]; } }