slang_rs_reflection_cpp.cpp revision c7f19ef041bb80902901b78bc4b939692206f26f
1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <sys/stat.h>
18#include <stdio.h>
19#include <stdlib.h>
20
21#include <cstdarg>
22#include <cctype>
23
24#include <algorithm>
25#include <sstream>
26#include <string>
27#include <utility>
28
29#include "os_sep.h"
30#include "slang_rs_context.h"
31#include "slang_rs_export_var.h"
32#include "slang_rs_export_foreach.h"
33#include "slang_rs_export_func.h"
34#include "slang_rs_reflect_utils.h"
35#include "slang_version.h"
36#include "slang_utils.h"
37
38#include "slang_rs_reflection_cpp.h"
39
40using namespace std;
41
42namespace slang {
43
44RSReflectionCpp::RSReflectionCpp(const RSContext *con) :
45    RSReflectionBase(con) {
46
47}
48
49RSReflectionCpp::~RSReflectionCpp() {
50
51}
52
53bool RSReflectionCpp::reflect(const string &OutputPathBase,
54                              const string &InputFileName,
55                              const string &OutputBCFileName) {
56    mInputFileName = InputFileName;
57    mOutputPath = OutputPathBase;
58    mOutputBCFileName = OutputBCFileName;
59    mClassName = string("ScriptC_") + stripRS(InputFileName);
60
61    makeHeader("android::renderscriptCpp::ScriptC");
62    std::vector< std::string > header(mText);
63    mText.clear();
64
65    makeImpl("android::renderscriptCpp::ScriptC");
66    std::vector< std::string > cpp(mText);
67    mText.clear();
68
69
70    writeFile(mClassName + ".h", header);
71    writeFile(mClassName + ".cpp", cpp);
72
73
74    return true;
75}
76
77typedef std::vector<std::pair<std::string, std::string> > ArgTy;
78
79
80#define RS_TYPE_CLASS_NAME_PREFIX        "ScriptField_"
81
82
83
84bool RSReflectionCpp::makeHeader(const std::string &baseClass) {
85    startFile(mClassName + ".h");
86
87    write("");
88    write("#include \"RenderScript.h\"");
89    write("");
90
91    // Imports
92    //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
93        //out() << "import " << Import[i] << ";" << std::endl;
94    //out() << std::endl;
95
96    if(!baseClass.empty()) {
97        write("class " + mClassName + " : public " + baseClass + " {");
98    } else {
99        write("class " + mClassName + " {");
100    }
101
102    write("private:");
103    uint32_t slot = 0;
104    incIndent();
105    for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
106           E = mRSContext->export_vars_end(); I != E; I++, slot++) {
107
108        const RSExportVar *ev = *I;
109        RSReflectionTypeData rtd;
110        ev->getType()->convertToRTD(&rtd);
111        if(!ev->isConst()) {
112            write(string(rtd.type->c_name) + " __" + ev->getName() + ";");
113        }
114    }
115    decIndent();
116
117    write("public:");
118    incIndent();
119    write(mClassName + "(android::sp<android::renderscriptCpp::RS> rs," +
120            " const char *cacheDir, size_t cacheDirLength);");
121    write("virtual ~" + mClassName + "();");
122    write("");
123
124
125    // Reflect export variable
126    slot = 0;
127    for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
128           E = mRSContext->export_vars_end(); I != E; I++, slot++) {
129
130        const RSExportVar *ev = *I;
131        RSReflectionTypeData rtd;
132        ev->getType()->convertToRTD(&rtd);
133
134        if(!ev->isConst()) {
135            write(string("void set_") + ev->getName() + "(" + rtd.type->c_name + " v) {");
136            stringstream tmp;
137            tmp << slot;
138            write(string("    setVar(") + tmp.str() + ", v);");
139            write(string("    __") + ev->getName() + " = v;");
140            write("}");
141        }
142        write(string(rtd.type->c_name) + " get_" + ev->getName() + "() const {");
143        if(ev->isConst()) {
144            const clang::APValue &val = ev->getInit();
145            bool isBool = !strcmp(rtd.type->c_name, "bool");
146            write(string("    return ") + genInitValue(val, isBool) + ";");
147        } else {
148            write(string("    return __") + ev->getName() + ";");
149        }
150        write("}");
151        write("");
152    }
153
154    // Reflect export for each functions
155    for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
156             E = mRSContext->export_foreach_end(); I != E; I++) {
157
158        const RSExportForEach *ef = *I;
159        if (ef->isDummyRoot()) {
160            write("// No forEach_root(...)");
161            continue;
162        }
163
164        stringstream tmp;
165        tmp << "void forEach_" << ef->getName() << "(";
166        if(ef->hasIn() && ef->hasOut()) {
167            tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
168            tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout";
169        } else if(ef->hasIn()) {
170            tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
171        } else {
172            tmp << "android::sp<const android::renderscriptCpp::Allocation> aout";
173        }
174
175        if(ef->getParamPacketType()) {
176            for(RSExportForEach::const_param_iterator i = ef->params_begin(),
177                     e = ef->params_end(); i != e; i++) {
178
179                RSReflectionTypeData rtd;
180                (*i)->getType()->convertToRTD(&rtd);
181                tmp << rtd.type->c_name << " " << (*i)->getName();
182            }
183        }
184        tmp << ") const;";
185        write(tmp);
186    }
187
188
189    // Reflect export function
190    for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
191           E = mRSContext->export_funcs_end(); I != E; I++) {
192
193        //genExportFunction(C, *I);
194    }
195
196    decIndent();
197    write("};");
198    return true;
199}
200
201bool RSReflectionCpp::writeBC() {
202    FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
203    if (pfin == NULL) {
204        fprintf(stderr, "Error: could not read file %s\n", mOutputBCFileName.c_str());
205        return false;
206    }
207
208    unsigned char buf[16];
209    int read_length;
210    write("static const unsigned char __txt[] = {");
211    incIndent();
212    while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
213        string s;
214        for(int i = 0; i < read_length; i++) {
215            char buf2[16];
216            sprintf(buf2, "0x%02x,", buf[i]);
217            s += buf2;
218        }
219        write(s);
220    }
221    decIndent();
222    write("};");
223    write("");
224    return true;
225}
226
227bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
228    startFile(mClassName + ".h");
229
230    write("");
231    write("#include \"" + mClassName + ".h\"");
232    write("");
233
234    writeBC();
235
236    // Imports
237    //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
238        //out() << "import " << Import[i] << ";" << std::endl;
239    //out() << std::endl;
240
241    write(mClassName + "::" + mClassName +
242          "(android::sp<android::renderscriptCpp::RS> rs, const char *cacheDir, size_t cacheDirLength) :");
243    write("        ScriptC(rs, __txt, sizeof(__txt), \"" + mClassName +
244          "\", 4, cacheDir, cacheDirLength) {");
245    incIndent();
246    //...
247    decIndent();
248    write("}");
249    write("");
250
251    write(mClassName + "::~" + mClassName + "() {");
252    write("}");
253    write("");
254
255    // Reflect export for each functions
256    uint32_t slot = 0;
257    for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
258             E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
259
260        const RSExportForEach *ef = *I;
261        if (ef->isDummyRoot()) {
262            write("// No forEach_root(...)");
263            continue;
264        }
265
266        stringstream tmp;
267        tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
268        if(ef->hasIn() && ef->hasOut()) {
269            tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
270            tmp << ", android::sp<const android::renderscriptCpp::Allocation> aout";
271        } else if(ef->hasIn()) {
272            tmp << "android::sp<const android::renderscriptCpp::Allocation> ain";
273        } else {
274            tmp << "android::sp<const android::renderscriptCpp::Allocation> aout";
275        }
276        tmp << ") const {";
277        write(tmp);
278        tmp.str("");
279
280        tmp << "    forEach(" << slot << ", ";
281        if(ef->hasIn() && ef->hasOut()) {
282            tmp << "ain, aout, NULL, 0);";
283        } else if(ef->hasIn()) {
284            tmp << "ain, NULL, 0);";
285        } else {
286            tmp << "aout, NULL, 0);";
287        }
288        write(tmp);
289
290        write("}");
291        write("");
292    }
293
294
295    // Reflect export function
296    slot = 0;
297    for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
298           E = mRSContext->export_funcs_end(); I != E; I++) {
299
300        //genExportFunction(C, *I);
301    }
302
303    decIndent();
304    return true;
305}
306
307
308
309}
310