4 # Copyright (C) 2011 The Android Open Source Project
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
22 hFileTemplate = """/**
23 * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
34 jniFileTemplate = """/**
35 * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
39 #include "native/%s.h"
47 // Helper functions ////////////////////////////////////////////////////////////////////////////////
48 %s* Get%sAtIndex(JNIEnv* env, jobject buffer, int index) {
49 jclass base_class = (*env)->FindClass(env, "android/filterfw/core/NativeBuffer");
50 jfieldID ptr_field = (*env)->GetFieldID(env, base_class, "mDataPointer", "J");
51 uintptr_t data_ptr = (*env)->GetLongField(env, buffer, ptr_field);
52 %s* array = (%s*)data_ptr;
53 (*env)->DeleteLocalRef(env, base_class);
57 // Declarations ////////////////////////////////////////////////////////////////////////////////////
58 JNIEXPORT jint JNICALL
59 Java_%s_getElementSize(JNIEnv* env, jobject thiz);
67 // Implementation //////////////////////////////////////////////////////////////////////////////////
68 jint Java_%s_getElementSize(JNIEnv* env, jobject thiz) {
75 javaFileTemplate = """/**
76 * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify!
81 import android.filterfw.core.NativeBuffer;
87 def ToJavaName(cname, start_upper_at = 1):
88 lower = cname.split("_")
89 upper = [c.title() for c in lower]
90 return "".join(lower[:start_upper_at] + upper[start_upper_at:])
92 def ToJNIPackage(package, jclassname):
93 return "%s_%s" % (package.replace(".", "_"), jclassname)
95 def ToMacroDefName(cname, pname):
96 return "%s_%s" % (pname.replace(".", "_").upper(), cname.upper())
99 def __init__(self, lineno, message):
101 self.message = message
104 return "On line %d: %s" % (self.lineno, self.message)
106 class FieldType_BasePOD:
107 def __init__(self, name, structname, jclassname, package, ctype, jtype, defval):
109 self.structname = structname
110 self.jclassname = jclassname
111 self.package = package
117 return " %s %s;" % (self.ctype, self.name)
119 def javaGetter(self):
120 return " public %s get%s(int index) {\n"\
121 " assertReadable();\n"\
122 " return nativeGet%s(index);\n"\
123 " }" % (self.ctype, ToJavaName(self.name, 0), ToJavaName(self.name, 0))
125 def javaSetter(self):
126 return " public void set%s(int index, %s value) {\n"\
127 " assertWritable();\n"\
128 " nativeSet%s(index, value);\n"\
129 " }" % (ToJavaName(self.name, 0), self.ctype, ToJavaName(self.name, 0))
131 def javaNativeGetter(self):
132 return " private native %s nativeGet%s(int index);"\
133 % (self.ctype, ToJavaName(self.name, 0))
135 def javaNativeSetter(self):
136 return " private native boolean nativeSet%s(int index, %s value);"\
137 % (ToJavaName(self.name, 0), self.ctype)
139 def jniGetterDefString(self):
140 return "JNIEXPORT %s JNICALL\n" \
141 "Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index);" \
142 % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0))
144 def jniGetterImplString(self):
146 "%s Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index) {\n"\
147 " %s* instance = Get%sAtIndex(env, thiz, index);\n"\
148 " return instance ? instance->%s : %s;\n"\
149 "}\n" % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\
150 self.structname, self.structname, self.name, self.defval)
152 def jniSetterDefString(self):
153 return "JNIEXPORT jboolean JNICALL\n" \
154 "Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value);" \
155 % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0), self.jtype)
157 def jniSetterImplString(self):
159 "jboolean Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value) {\n"\
160 " %s* instance = Get%sAtIndex(env, thiz, index);\n"\
161 " if (instance) {\n"\
162 " instance->%s = value;\n"\
163 " return JNI_TRUE;\n"\
165 " return JNI_FALSE;\n"\
166 "}\n" % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\
167 self.jtype, self.structname, self.structname, self.name)
169 class FieldType_Float(FieldType_BasePOD):
170 def __init__(self, name, structname, jclassname, package):
171 FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "float", "jfloat", "0.0")
173 class FieldType_Int(FieldType_BasePOD):
174 def __init__(self, name, structname, jclassname, package):
175 FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "int", "jint", "0")
179 def parseTextFile(self, filepath):
184 self.structname = None
185 self.jclassname = None
189 txtfile = open(filepath)
191 # Parse it line by line
194 # Split line into components
195 linecomps = line.split()
196 if len(linecomps) == 0:
202 self.commandArgAssert(linecomps, 1, lineno)
203 self.name = linecomps[1]
204 if not self.structname:
205 self.structname = self.name
206 if not self.jclassname:
207 self.jclassname = self.name
208 elif cmd == "@package":
209 self.commandArgAssert(linecomps, 1, lineno)
210 self.package = linecomps[1]
211 elif cmd == "@libname":
212 self.commandArgAssert(linecomps, 1, lineno)
213 self.libname = linecomps[1]
214 elif cmd == "@structname":
215 self.commandArgAssert(linecomps, 1, lineno)
216 self.structname = linecomps[1]
217 elif cmd == "@javaclassname":
218 self.commandArgAssert(linecomps, 1, lineno)
219 self.jclassname = linecomps[1]
220 elif cmd == "@field":
221 self.commandArgAssert(linecomps, 2, lineno)
222 typestr = linecomps[1]
224 fieldtype = FieldType_Int(linecomps[2], self.structname, self.jclassname, self.package)
225 elif typestr == "float":
226 fieldtype = FieldType_Float(linecomps[2], self.structname, self.jclassname, self.package)
228 raise ParseError(lineno, "Unknown field type '%s'!" % typestr)
229 self.fields.append(fieldtype)
231 raise ParseError(lineno, "Unknown command: '%s'!" % cmd)
235 # Make sure we have all required info
237 raise ParseError(lineno, "Required field '@name' missing!")
238 elif not self.package:
239 raise ParseError(lineno, "Required field '@package' missing!")
240 elif not self.libname:
241 raise ParseError(lineno, "Required field '@libname' missing!")
244 if self.libname[:3] == "lib":
245 self.libname = self.libname[3:]
247 def commandArgAssert(self, linecomps, expectedcount, lineno):
248 foundcount = len(linecomps) - 1
249 if foundcount < expectedcount:
250 raise ParseError(lineno, "Not enough arguments specifed for command '%s'! Expected %d, " \
251 "but got only %d!" % (linecomps[0], expectedcount, foundcount))
252 elif foundcount > expectedcount + 1:
253 raise ParseError(lineno, "Too many arguments specifed for command '%s'! Expected %d, " \
254 "but got %d!" % (linecomps[0], expectedcount, foundcount))
257 def cStructString(self):
258 cfields = [f.cString() for f in self.fields]
259 return "typedef struct Struct%s {\n%s\n} %s;\n" % (self.structname,\
263 def javaClassString(self):
264 jgetters = [f.javaGetter() for f in self.fields]
265 jsetters = [f.javaSetter() for f in self.fields]
266 jnativesetters = [f.javaNativeSetter() for f in self.fields]
267 jnativegetters = [f.javaNativeGetter() for f in self.fields]
268 return "public class %s extends NativeBuffer {\n\n"\
273 " public %s(int count) {\n"\
277 " public native int getElementSize();\n"\
284 " System.loadLibrary(\"%s\");\n"\
287 "};\n" % (self.jclassname,\
290 "\n\n".join(jgetters),\
291 "\n\n".join(jsetters),\
292 "\n\n".join(jnativegetters),\
293 "\n\n".join(jnativesetters),\
296 def jniDeclString(self):
297 jnigetters = [f.jniGetterDefString() for f in self.fields]
298 jnisetters = [f.jniSetterDefString() for f in self.fields]
299 return "\n\n".join(jnigetters + jnisetters)
301 def jniImplString(self):
302 jnigetters = [f.jniGetterImplString() for f in self.fields]
303 jnisetters = [f.jniSetterImplString() for f in self.fields]
304 return "\n\n".join(jnigetters + jnisetters)
306 def hFileString(self):
307 defname = ToMacroDefName(self.structname, self.package)
308 return hFileTemplate % (defname, defname, self.cStructString(), defname)
310 def javaFileString(self):
311 return javaFileTemplate % (self.package, self.javaClassString())
313 def jniFileString(self):
314 return jniFileTemplate % (self.structname.lower(),\
319 ToJNIPackage(self.package, self.jclassname),\
320 self.jniDeclString(),\
321 ToJNIPackage(self.package, self.jclassname),\
323 self.jniImplString())
327 print("Usage: %s <file.struct>" % argv[0])
332 structspec = StructSpec()
333 structspec.parseTextFile(filepath)
335 hfilename = "%s.h" % structspec.structname.lower()
336 javafilename = "%s.java" % structspec.jclassname
337 jnifilename = "jni_%s.c" % structspec.structname.lower()
339 javapackagepath = structspec.package.replace('.','/')
341 rootdir = os.path.dirname(filepath)
342 hfilepath = "%s/../native/%s" % (rootdir, hfilename)
343 javafilepath = "%s/../java/%s/%s" % (rootdir, javapackagepath, javafilename)
344 jnifilepath = "%s/../jni/%s" % (rootdir, jnifilename)
346 hfile = open(hfilepath, 'w')
347 hfile.write(structspec.hFileString())
350 javafile = open(javafilepath, 'w')
351 javafile.write(structspec.javaFileString())
354 jnifile = open(jnifilepath, 'w')
355 jnifile.write(structspec.jniFileString())
359 if __name__ == "__main__":
360 sys.exit(main(sys.argv))