diff options
Diffstat (limited to 'media/mca/structgen.py')
-rw-r--r-- | media/mca/structgen.py | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/media/mca/structgen.py b/media/mca/structgen.py new file mode 100644 index 000000000000..437326ca2c28 --- /dev/null +++ b/media/mca/structgen.py @@ -0,0 +1,367 @@ +#!/usr/bin/env python + +# +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import sys + +hFileTemplate = """/** + * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify! + **/ + +#ifndef %s +#define %s + +%s + +#endif // %s +""" + +jniFileTemplate = """/** + * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify! + **/ + +#include <stdint.h> +#include "native/%s.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jni.h" + +// Helper functions //////////////////////////////////////////////////////////////////////////////// +%s* Get%sAtIndex(JNIEnv* env, jobject buffer, int index) { + jclass base_class = (*env)->FindClass(env, "android/filterfw/core/NativeBuffer"); + jfieldID ptr_field = (*env)->GetFieldID(env, base_class, "mDataPointer", "J"); + uintptr_t data_ptr = (*env)->GetLongField(env, buffer, ptr_field); + %s* array = (%s*)data_ptr; + (*env)->DeleteLocalRef(env, base_class); + return &array[index]; +} + +// Declarations //////////////////////////////////////////////////////////////////////////////////// +JNIEXPORT jint JNICALL +Java_%s_getElementSize(JNIEnv* env, jobject thiz); + +%s + +#ifdef __cplusplus +} +#endif + +// Implementation ////////////////////////////////////////////////////////////////////////////////// +jint Java_%s_getElementSize(JNIEnv* env, jobject thiz) { + return sizeof(%s); +} + +%s +""" + +javaFileTemplate = """/** + * This file is auto-generated by platform/system/media/mca/structgen.py! Do NOT modify! + **/ + +package %s; + +import android.filterfw.core.NativeBuffer; + +%s +""" + + +def ToJavaName(cname, start_upper_at = 1): + lower = cname.split("_") + upper = [c.title() for c in lower] + return "".join(lower[:start_upper_at] + upper[start_upper_at:]) + +def ToJNIPackage(package, jclassname): + return "%s_%s" % (package.replace(".", "_"), jclassname) + +def ToMacroDefName(cname, pname): + return "%s_%s" % (pname.replace(".", "_").upper(), cname.upper()) + +class ParseError: + def __init__(self, lineno, message): + self.lineno = lineno + self.message = message + + def __str__(self): + return "On line %d: %s" % (self.lineno, self.message) + +class FieldType_BasePOD: + def __init__(self, name, structname, jclassname, package, javatype, ctype, jtype, defval): + self.name = name + self.structname = structname + self.jclassname = jclassname + self.package = package + self.javatype = javatype + self.ctype = ctype + self.jtype = jtype + self.defval = defval + + def cString(self): + return " %s %s;" % (self.ctype, self.name) + + def javaGetter(self): + return " public %s get%s(int index) {\n"\ + " assertReadable();\n"\ + " return nativeGet%s(index);\n"\ + " }" % (self.javatype, ToJavaName(self.name, 0), ToJavaName(self.name, 0)) + + def javaSetter(self): + return " public void set%s(int index, %s value) {\n"\ + " assertWritable();\n"\ + " nativeSet%s(index, value);\n"\ + " }" % (ToJavaName(self.name, 0), self.javatype, ToJavaName(self.name, 0)) + + def javaNativeGetter(self): + return " private native %s nativeGet%s(int index);"\ + % (self.javatype, ToJavaName(self.name, 0)) + + def javaNativeSetter(self): + return " private native boolean nativeSet%s(int index, %s value);"\ + % (ToJavaName(self.name, 0), self.javatype) + + def jniGetterDefString(self): + return "JNIEXPORT %s JNICALL\n" \ + "Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index);" \ + % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0)) + + def jniGetterImplString(self): + return \ + "%s Java_%s_nativeGet%s(JNIEnv* env, jobject thiz, jint index) {\n"\ + " %s* instance = Get%sAtIndex(env, thiz, index);\n"\ + " return instance ? instance->%s : %s;\n"\ + "}\n" % (self.jtype, ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\ + self.structname, self.structname, self.name, self.defval) + + def jniSetterDefString(self): + return "JNIEXPORT jboolean JNICALL\n" \ + "Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value);" \ + % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0), self.jtype) + + def jniSetterImplString(self): + return \ + "jboolean Java_%s_nativeSet%s(JNIEnv* env, jobject thiz, jint index, %s value) {\n"\ + " %s* instance = Get%sAtIndex(env, thiz, index);\n"\ + " if (instance) {\n"\ + " instance->%s = value;\n"\ + " return JNI_TRUE;\n"\ + " }\n"\ + " return JNI_FALSE;\n"\ + "}\n" % (ToJNIPackage(self.package, self.jclassname), ToJavaName(self.name, 0),\ + self.jtype, self.structname, self.structname, self.name) + +class FieldType_Float(FieldType_BasePOD): + def __init__(self, name, structname, jclassname, package): + FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "float", "float", "jfloat", "0.0") + +class FieldType_Int(FieldType_BasePOD): + def __init__(self, name, structname, jclassname, package): + FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "int", "int", "jint", "0") + +class FieldType_Long(FieldType_BasePOD): + def __init__(self, name, structname, jclassname, package): + FieldType_BasePOD.__init__(self, name, structname, jclassname, package, "long", "long long", "jlong", "0") + +class StructSpec: + + def parseTextFile(self, filepath): + # Init + self.name = None + self.package = None + self.fields = [] + self.structname = None + self.jclassname = None + self.libname = None + + # Open the file + txtfile = open(filepath) + + # Parse it line by line + lineno = 0 + for line in txtfile: + # Split line into components + linecomps = line.split() + if len(linecomps) == 0: + continue + + # Execute command + cmd = linecomps[0] + if cmd == "@name": + self.commandArgAssert(linecomps, 1, lineno) + self.name = linecomps[1] + if not self.structname: + self.structname = self.name + if not self.jclassname: + self.jclassname = self.name + elif cmd == "@package": + self.commandArgAssert(linecomps, 1, lineno) + self.package = linecomps[1] + elif cmd == "@libname": + self.commandArgAssert(linecomps, 1, lineno) + self.libname = linecomps[1] + elif cmd == "@structname": + self.commandArgAssert(linecomps, 1, lineno) + self.structname = linecomps[1] + elif cmd == "@javaclassname": + self.commandArgAssert(linecomps, 1, lineno) + self.jclassname = linecomps[1] + elif cmd == "@field": + self.commandArgAssert(linecomps, 2, lineno) + typestr = linecomps[1] + if typestr == "int": + fieldtype = FieldType_Int(linecomps[2], self.structname, self.jclassname, self.package) + elif typestr == "long": + fieldtype = FieldType_Long(linecomps[2], self.structname, self.jclassname, self.package) + elif typestr == "float": + fieldtype = FieldType_Float(linecomps[2], self.structname, self.jclassname, self.package) + else: + raise ParseError(lineno, "Unknown field type '%s'!" % typestr) + self.fields.append(fieldtype) + else: + raise ParseError(lineno, "Unknown command: '%s'!" % cmd) + + lineno = lineno + 1 + + # Make sure we have all required info + if not self.name: + raise ParseError(lineno, "Required field '@name' missing!") + elif not self.package: + raise ParseError(lineno, "Required field '@package' missing!") + elif not self.libname: + raise ParseError(lineno, "Required field '@libname' missing!") + + # Normalize values + if self.libname[:3] == "lib": + self.libname = self.libname[3:] + + def commandArgAssert(self, linecomps, expectedcount, lineno): + foundcount = len(linecomps) - 1 + if foundcount < expectedcount: + raise ParseError(lineno, "Not enough arguments specifed for command '%s'! Expected %d, " \ + "but got only %d!" % (linecomps[0], expectedcount, foundcount)) + elif foundcount > expectedcount + 1: + raise ParseError(lineno, "Too many arguments specifed for command '%s'! Expected %d, " \ + "but got %d!" % (linecomps[0], expectedcount, foundcount)) + + + def cStructString(self): + cfields = [f.cString() for f in self.fields] + return "typedef struct Struct%s {\n%s\n} %s;\n" % (self.structname,\ + "\n".join(cfields),\ + self.structname) + + def javaClassString(self): + jgetters = [f.javaGetter() for f in self.fields] + jsetters = [f.javaSetter() for f in self.fields] + jnativesetters = [f.javaNativeSetter() for f in self.fields] + jnativegetters = [f.javaNativeGetter() for f in self.fields] + return "public class %s extends NativeBuffer {\n\n"\ + " public %s() {\n"\ + " super();\n"\ + " }\n"\ + "\n"\ + " public %s(int count) {\n"\ + " super(count);\n"\ + " }\n"\ + "\n"\ + " public native int getElementSize();\n"\ + "\n"\ + "%s\n\n"\ + "%s\n\n"\ + "%s\n\n"\ + "%s\n\n"\ + " static {\n"\ + " System.loadLibrary(\"%s\");\n"\ + " }\n"\ + "\n"\ + "};\n" % (self.jclassname,\ + self.jclassname,\ + self.jclassname,\ + "\n\n".join(jgetters),\ + "\n\n".join(jsetters),\ + "\n\n".join(jnativegetters),\ + "\n\n".join(jnativesetters),\ + self.libname) + + def jniDeclString(self): + jnigetters = [f.jniGetterDefString() for f in self.fields] + jnisetters = [f.jniSetterDefString() for f in self.fields] + return "\n\n".join(jnigetters + jnisetters) + + def jniImplString(self): + jnigetters = [f.jniGetterImplString() for f in self.fields] + jnisetters = [f.jniSetterImplString() for f in self.fields] + return "\n\n".join(jnigetters + jnisetters) + + def hFileString(self): + defname = ToMacroDefName(self.structname, self.package) + return hFileTemplate % (defname, defname, self.cStructString(), defname) + + def javaFileString(self): + return javaFileTemplate % (self.package, self.javaClassString()) + + def jniFileString(self): + return jniFileTemplate % (self.structname.lower(),\ + self.structname,\ + self.structname,\ + self.structname,\ + self.structname,\ + ToJNIPackage(self.package, self.jclassname),\ + self.jniDeclString(),\ + ToJNIPackage(self.package, self.jclassname),\ + self.structname, + self.jniImplString()) + +def main(argv): + if len(argv) != 2: + print("Usage: %s <file.struct>" % argv[0]) + return -1 + + filepath = argv[1] + + structspec = StructSpec() + structspec.parseTextFile(filepath) + + hfilename = "%s.h" % structspec.structname.lower() + javafilename = "%s.java" % structspec.jclassname + jnifilename = "jni_%s.c" % structspec.structname.lower() + + javapackagepath = structspec.package.replace('.','/') + + rootdir = os.path.dirname(filepath) + hfilepath = "%s/../native/%s" % (rootdir, hfilename) + javafilepath = "%s/../java/%s/%s" % (rootdir, javapackagepath, javafilename) + jnifilepath = "%s/../jni/%s" % (rootdir, jnifilename) + + hfile = open(hfilepath, 'w') + hfile.write(structspec.hFileString()) + hfile.close() + + javafile = open(javafilepath, 'w') + javafile.write(structspec.javaFileString()) + javafile.close() + + jnifile = open(jnifilepath, 'w') + jnifile.write(structspec.jniFileString()) + jnifile.close() + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) |