slang_rs_reflect_utils.cpp revision b1980a2eedc56df92786afc291e00f26659a60ad
1#include "slang_rs_reflect_utils.hpp"
2
3#include <cstdlib>
4#include <cstdio>
5#include <cstring>
6#include <fstream>
7
8#include <sys/stat.h>
9#include <sys/types.h>
10
11namespace slang {
12
13using std::string;
14
15string RSSlangReflectUtils::ComputePackagedPath(
16    const std::string& prefixPath, const std::string& packageName) {
17    string packaged_path(prefixPath);
18    if (!prefixPath.empty() && (prefixPath[prefixPath.length() - 1] != '/')) {
19        packaged_path += "/";
20    }
21    size_t s = packaged_path.length();
22    packaged_path += packageName;
23    while (s < packaged_path.length()) {
24        if (packaged_path[s] == '.') {
25            packaged_path[s] = '/';
26        }
27        ++s;
28    }
29    return packaged_path;
30}
31
32static string InternalFileNameConvert(const char* rsFileName, bool camelCase) {
33    const char* dot = rsFileName + strlen(rsFileName);
34    const char* slash = dot - 1;
35    while (slash >= rsFileName) {
36        if (*slash == '/') {
37            break;
38        }
39        if ((*slash == '.') && (*dot == 0)) {
40            dot = slash;
41        }
42        --slash;
43    }
44    ++slash;
45    char ret[256];
46    bool need_cap = true;
47    int i = 0;
48    for (; (i < 255) && (slash < dot); ++slash) {
49        if (isalnum(*slash)) {
50            if (need_cap && camelCase) {
51                ret[i] = toupper(*slash);
52            } else {
53                ret[i] = *slash;
54            }
55            need_cap = false;
56            ++i;
57        } else {
58            need_cap = true;
59        }
60    }
61    ret[i] = 0;
62    return string(ret);
63}
64
65std::string RSSlangReflectUtils::JavaClassNameFromRSFileName(
66    const char* rsFileName) {
67    return InternalFileNameConvert(rsFileName, true);
68}
69
70
71std::string RSSlangReflectUtils::BCFileNameFromRSFileName(
72    const char* rsFileName) {
73    return InternalFileNameConvert(rsFileName, false);
74}
75
76bool RSSlangReflectUtils::mkdir_p(const char* path) {
77    char buf[256];
78    char *tmp, *p = NULL;
79    size_t len = strlen(path);
80
81    if (len + 1 <= sizeof(buf))
82        tmp = buf;
83    else
84        tmp = new char [len + 1];
85
86    strcpy(tmp, path);
87
88    if (tmp[len - 1] == '/')
89        tmp[len - 1] = 0;
90
91    for (p = tmp + 1; *p; p++) {
92        if (*p == '/') {
93            *p = 0;
94            mkdir(tmp, S_IRWXU);
95            *p = '/';
96        }
97    }
98    mkdir(tmp, S_IRWXU);
99
100    if (tmp != buf)
101        delete[] tmp;
102
103    return true;
104}
105
106bool RSSlangReflectUtils::EncodeBitcodeToJavaFile(
107    const char* rsFileName, const char* inputBCFileName,
108    const std::string& outputPath, const std::string& packageName) {
109
110    FILE* pfin = fopen(inputBCFileName, "rb");
111    if (pfin == NULL) {
112        return false;
113    }
114
115    string output_path = ComputePackagedPath(outputPath, packageName);
116    if (!mkdir_p(output_path.c_str())) {
117      return false;
118    }
119
120    string clazz_name(JavaClassNameFromRSFileName(rsFileName));
121    clazz_name += "BitCode";
122    string filename(clazz_name);
123    filename += ".java";
124
125    string output_filename(output_path);
126    output_filename += "/";
127    output_filename += filename;
128    printf("Generating %s ...\n", filename.c_str());
129    FILE* pfout = fopen(output_filename.c_str(), "w");
130    if (pfout == NULL) {
131        return false;
132    }
133
134    // Output the header
135    fprintf(pfout, "/*\n");
136    fprintf(pfout, " * This file is auto-generated. DO NOT MODIFY!\n");
137    fprintf(pfout, " * The source RenderScript file: %s\n", rsFileName);
138    fprintf(pfout, " */\n\n");
139    fprintf(pfout, "package %s;\n\n", packageName.c_str());
140    fprintf(pfout, "/**\n");
141    fprintf(pfout, " * @hide\n");
142    fprintf(pfout, " */\n");
143    fprintf(pfout, "public class %s {\n", clazz_name.c_str());
144    fprintf(pfout, "\n");
145    fprintf(pfout, "  // return byte array representation of the bitcode file.\n");
146    fprintf(pfout, "  public static byte[] getBitCode() {\n");
147    fprintf(pfout, "    byte[] bc = new byte[data.length];\n");
148    fprintf(pfout, "    System.arraycopy(data, 0, bc, 0, data.length);\n");
149    fprintf(pfout, "    return bc;\n");
150    fprintf(pfout, "  }\n");
151    fprintf(pfout, "\n");
152    fprintf(pfout, "  // byte array representation of the bitcode file.\n");
153    fprintf(pfout, "  private static final byte[] data = {\n");
154
155    // output the data
156    const static int BUFF_SIZE = 0x10000;
157    char* buff = new char[BUFF_SIZE];
158    int read_length;
159    while ((read_length = fread(buff, 1, BUFF_SIZE, pfin)) > 0) {
160        const static int LINE_BYTE_NUM = 16;
161        char out_line[LINE_BYTE_NUM*6 + 10];
162        const char* out_line_end = out_line + sizeof(out_line);
163        char* p = out_line;
164
165        int write_length = 0;
166        while (write_length < read_length) {
167            p += snprintf(p, out_line_end - p, " %4d,", (int)buff[write_length]);
168            ++write_length;
169            if (((write_length % LINE_BYTE_NUM) == 0)
170                || (write_length == read_length)) {
171                fprintf(pfout, "   ");
172                fprintf(pfout, out_line);
173                fprintf(pfout, "\n");
174                p = out_line;
175            }
176        }
177
178    }
179    delete []buff;
180
181    // the rest of the java file.
182    fprintf(pfout, "  };\n");
183    fprintf(pfout, "}\n");
184
185    fclose(pfin);
186    fclose(pfout);
187    return true;
188}
189
190}
191