slang_rs_reflection_cpp.cpp revision 192392fc5ffedc06eb8ae2b89d703b3c658fddd6
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("ScriptC");
62    std::vector< std::string > header(mText);
63    mText.clear();
64
65    makeImpl("ScriptC");
66    std::vector< std::string > cpp(mText);
67    mText.clear();
68
69
70    RSReflectionBase::writeFile(mClassName + ".h", header);
71    RSReflectionBase::writeFile(mClassName + ".cpp", cpp);
72
73
74    return false;
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 \"ScriptC.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 + " : protected " + 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 + "(RenderScript *rs, const char *cacheDir, size_t cacheDirLength);");
120    write("virtual ~" + mClassName + "();");
121    write("");
122
123
124    // Reflect export variable
125    slot = 0;
126    for (RSContext::const_export_var_iterator I = mRSContext->export_vars_begin(),
127           E = mRSContext->export_vars_end(); I != E; I++, slot++) {
128
129        const RSExportVar *ev = *I;
130        RSReflectionTypeData rtd;
131        ev->getType()->convertToRTD(&rtd);
132
133        if(!ev->isConst()) {
134            write(string("void set_") + ev->getName() + "(" + rtd.type->c_name + " v) {");
135            stringstream tmp;
136            tmp << slot;
137            write(string("    setVar(") + tmp.str() + ", v);");
138            write(string("    __") + ev->getName() + " = v;");
139            write("}");
140        }
141        write(string(rtd.type->c_name) + " get_" + ev->getName() + "() const {");
142        if(ev->isConst()) {
143            const clang::APValue &val = ev->getInit();
144            bool isBool = !strcmp(rtd.type->c_name, "bool");
145            write(string("    return ") + genInitValue(val, isBool) + ";");
146        } else {
147            write(string("    return __") + ev->getName() + ";");
148        }
149        write("}");
150        write("");
151    }
152
153    // Reflect export for each functions
154    for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
155             E = mRSContext->export_foreach_end(); I != E; I++) {
156
157        const RSExportForEach *ef = *I;
158        if (ef->isDummyRoot()) {
159            write("// No forEach_root(...)");
160            continue;
161        }
162
163        stringstream tmp;
164        tmp << "void forEach_" << ef->getName() << "(";
165        if(ef->hasIn() && ef->hasOut()) {
166            tmp << "const Allocation *ain, const Allocation *aout";
167        } else if(ef->hasIn()) {
168            tmp << "const Allocation *ain";
169        } else {
170            tmp << "const Allocation *aout";
171        }
172
173        if(ef->getParamPacketType()) {
174            for(RSExportForEach::const_param_iterator i = ef->params_begin(),
175                     e = ef->params_end(); i != e; i++) {
176
177                RSReflectionTypeData rtd;
178                (*i)->getType()->convertToRTD(&rtd);
179                tmp << rtd.type->c_name << " " << (*i)->getName();
180            }
181        }
182        tmp << ") const;";
183        write(tmp);
184    }
185
186
187    // Reflect export function
188    for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
189           E = mRSContext->export_funcs_end(); I != E; I++) {
190
191        //genExportFunction(C, *I);
192    }
193
194    decIndent();
195    write("};");
196    return true;
197}
198
199bool RSReflectionCpp::writeBC() {
200    FILE *pfin = fopen(mOutputBCFileName.c_str(), "rb");
201    if (pfin == NULL) {
202        fprintf(stderr, "Error: could not read file %s\n", mOutputBCFileName.c_str());
203        return false;
204    }
205
206    unsigned char buf[16];
207    int read_length;
208    write("static const unsigned char __txt[] = {");
209    incIndent();
210    while ((read_length = fread(buf, 1, sizeof(buf), pfin)) > 0) {
211        string s;
212        for(int i = 0; i < read_length; i++) {
213            char buf2[16];
214            sprintf(buf2, "0x%02x,", buf[i]);
215            s += buf2;
216        }
217        write(s);
218    }
219    decIndent();
220    write("};");
221    write("");
222    return true;
223}
224
225bool RSReflectionCpp::makeImpl(const std::string &baseClass) {
226    startFile(mClassName + ".h");
227
228    write("");
229    write("#include \"" + mClassName + ".h\"");
230    write("");
231
232    writeBC();
233
234    // Imports
235    //for(unsigned i = 0; i < (sizeof(Import) / sizeof(const char*)); i++)
236        //out() << "import " << Import[i] << ";" << std::endl;
237    //out() << std::endl;
238
239    write(mClassName + "::" + mClassName +
240          "(RenderScript *rs, const char *cacheDir, size_t cacheDirLength) :");
241    write("        ScriptC(rs, __txt, sizeof(__txt), \"" + mInputFileName +
242          "\", 4, cacheDir, cacheDirLength) {");
243    incIndent();
244    //...
245    decIndent();
246    write("}");
247    write("");
248
249    write(mClassName + "::~" + mClassName + "() {");
250    write("}");
251    write("");
252
253    // Reflect export for each functions
254    uint32_t slot = 0;
255    for (RSContext::const_export_foreach_iterator I = mRSContext->export_foreach_begin(),
256             E = mRSContext->export_foreach_end(); I != E; I++, slot++) {
257
258        const RSExportForEach *ef = *I;
259        if (ef->isDummyRoot()) {
260            write("// No forEach_root(...)");
261            continue;
262        }
263
264        stringstream tmp;
265        tmp << "void " << mClassName << "::forEach_" << ef->getName() << "(";
266        if(ef->hasIn() && ef->hasOut()) {
267            tmp << "const Allocation *ain, const Allocation *aout";
268        } else if(ef->hasIn()) {
269            tmp << "const Allocation *ain";
270        } else {
271            tmp << "const Allocation *aout";
272        }
273        tmp << ") const {";
274        write(tmp);
275        tmp.str("");
276
277        tmp << "    forEach(" << slot << ", ";
278        if(ef->hasIn() && ef->hasOut()) {
279            tmp << "ain, aout, NULL, 0);";
280        } else if(ef->hasIn()) {
281            tmp << "ain, NULL, 0);";
282        } else {
283            tmp << "aout, NULL, 0);";
284        }
285        write(tmp);
286
287        write("}");
288        write("");
289    }
290
291
292    // Reflect export function
293    slot = 0;
294    for (RSContext::const_export_func_iterator I = mRSContext->export_funcs_begin(),
295           E = mRSContext->export_funcs_end(); I != E; I++) {
296
297        //genExportFunction(C, *I);
298    }
299
300    decIndent();
301    return true;
302}
303
304
305
306}
307