1 /*
2  * Copyright 2010, 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 #ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_REFLECT_UTILS_H_ // NOLINT
18 #define _FRAMEWORKS_COMPILE_SLANG_SLANG_REFLECT_UTILS_H_
19 
20 #include <fstream>
21 #include <string>
22 
23 namespace slang {
24 
25 // BitCode storage type
26 enum BitCodeStorageType { BCST_APK_RESOURCE, BCST_JAVA_CODE, BCST_CPP_CODE };
27 
28 class RSSlangReflectUtils {
29 public:
30   // Encode a binary bitcode file into a Java source file.
31   // rsFileName: the original .rs file name (with or without path).
32   // bc32FileName: path of the 32-bit bitcode file
33   // bc64FileName: path of the 64-bit bitcode file
34   // reflectPath: where to output the generated Java file, no package name in
35   // it.
36   // packageName: the package of the output Java file.
37   // verbose: whether or not to print out additional info about compilation.
38   // bcStorage: where to emit bitcode to (resource file or embedded).
39   struct BitCodeAccessorContext {
40     const char *rsFileName;
41     const char *bc32FileName;
42     const char *bc64FileName;
43     const char *reflectPath;
44     const char *packageName;
45     const std::string *licenseNote;
46     bool verbose;
47     BitCodeStorageType bcStorage;
48   };
49 
50   // Return the stem of the file name, i.e., remove the dir and the extension.
51   // Eg, foo.ext -> foo
52   //     foo.bar.ext -> foo.bar
53   //     ./path/foo.ext -> foo
54   static std::string GetFileNameStem(const char *fileName);
55 
56   // Compute a Java source file path from a given prefixPath and its package.
57   // Eg, given prefixPath=./foo/bar and packageName=com.x.y, then it returns
58   // ./foo/bar/com/x/y
59   static std::string ComputePackagedPath(const char *prefixPath,
60                                          const char *packageName);
61 
62   // Compute Java class name from a .rs file name.
63   // Any non-alnum, non-underscore characters will be discarded.
64   // E.g. with rsFileName=./foo/bar/my-Renderscript_file.rs it returns
65   // "myRenderscript_file".
66   // rsFileName: the input .rs file name (with or without path).
67   static std::string JavaClassNameFromRSFileName(const char *rsFileName);
68 
69   // Compute a bitcode file name (no extension) from a .rs file name.
70   // Because the bitcode file name may be used as Resource ID in the generated
71   // class (something like R.raw.<bitcode_filename>), Any non-alnum,
72   // non-underscore character will be discarded.
73   // The difference from JavaClassNameFromRSFileName() is that the result is
74   // converted to lowercase.
75   // E.g. with rsFileName=./foo/bar/my-Renderscript_file.rs it returns
76   // "myrenderscript_file"
77   // rsFileName: the input .rs file name (with or without path).
78   static std::string BCFileNameFromRSFileName(const char *rsFileName);
79 
80   // Compute the bitcode-containing class name from a .rs filename.
81   // Any non-alnum, non-underscore characters will be discarded.
82   // E.g. with rsFileName=./foo/bar/my-Renderscript_file.rs it returns
83   // "myRenderscript_fileBitCode".
84   // rsFileName: the input .rs file name (with or without path).
85   static std::string JavaBitcodeClassNameFromRSFileName(const char *rsFileName);
86 
87   // Generate the bit code accessor Java source file.
88   static bool GenerateJavaBitCodeAccessor(const BitCodeAccessorContext &context);
89 };
90 
91 // Joins two sections of a path, inserting a separator if needed.
92 // E.g. JoinPath("foo/bar", "baz/a.java") returns "foo/bar/baz/a.java",
93 // JoinPath("foo", "/bar/baz") returns "foo/bar/baz", and
94 // JoinPath("foo/", "/bar") returns "foo/bar".
95 std::string JoinPath(const std::string &path1, const std::string &path2);
96 
97 /* Compute a safe root name from a .rs file name.  Any non-alphanumeric,
98  * non-underscore characters will be discarded.
99  * E.g. RootNameFromRSFileName("./foo/bar/my-Renderscript_file.rs") returns
100  * "myRenderscript_file".
101  */
102 std::string RootNameFromRSFileName(const std::string &rsFileName);
103 
104 /* This class is used to generate one source file.  There will be one instance
105  * for each generated file.
106  */
107 class GeneratedFile : public std::ofstream {
108 public:
109   /* Starts the file by:
110    * - creating the parent directories (if needed),
111    * - opening the stream,
112    * - writing out the license,
113    * - writing a message that this file has been auto-generated.
114    * If optionalLicense is nullptr, a default license is used.
115    */
116   bool startFile(const std::string &outPath, const std::string &outFileName,
117                  const std::string &sourceFileName,
118                  const std::string *optionalLicense, bool isJava, bool verbose);
119   void closeFile();
120 
121   void increaseIndent(); // Increases the new line indentation by 4.
122   void decreaseIndent(); // Decreases the new line indentation by 4.
123   void comment(const std::string& s); // Outputs a multiline comment.
124 
125   // Starts a control block.  This works both for Java and C++.
startBlock()126   void startBlock() {
127     *this << " {\n";
128     increaseIndent();
129   }
130 
131   // Ends a control block.
132   void endBlock(bool addSemicolon = false) {
133     decreaseIndent();
134     indent() << "}" << (addSemicolon ? ";" : "") << "\n\n";
135   }
136 
137   /* Indents the line.  By returning *this, we can use like this:
138    *  mOut.ident() << "a = b;\n";
139    */
indent()140   std::ofstream &indent() {
141     *this << mIndent;
142     return *this;
143   }
144 
145 private:
146   std::string mIndent; // The correct spacing at the beginning of each line.
147 };
148 
149 } // namespace slang
150 
151 #endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_REFLECT_UTILS_H_  NOLINT
152