1/*******************************************************************************
2 * Copyright 2011 See AUTHORS file.
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
17package com.badlogic.gdx.jnigen.parsing;
18
19import java.util.ArrayList;
20
21public interface JavaMethodParser {
22	public ArrayList<JavaSegment> parse (String classFile) throws Exception;
23
24	public interface JavaSegment {
25		public int getStartIndex ();
26
27		public int getEndIndex ();
28	}
29
30	public class JniSection implements JavaSegment {
31		private String nativeCode;
32		private final int startIndex;
33		private final int endIndex;
34
35		public JniSection (String nativeCode, int startIndex, int endIndex) {
36			this.nativeCode = nativeCode;
37			this.startIndex = startIndex;
38			this.endIndex = endIndex;
39		}
40
41		public String getNativeCode () {
42			return nativeCode;
43		}
44
45		public void setNativeCode (String nativeCode) {
46			this.nativeCode = nativeCode;
47		}
48
49		public int getStartIndex () {
50			return startIndex;
51		}
52
53		public int getEndIndex () {
54			return endIndex;
55		}
56
57		@Override
58		public String toString () {
59			return "JniSection [nativeCode=" + nativeCode + ", startIndex=" + startIndex + ", endIndex=" + endIndex + "]";
60		}
61	}
62
63	public enum ArgumentType {
64		Boolean("jboolean"), Byte("jbyte"), Char("jchar"), Short("jshort"), Integer("jint"), Long("jlong"), Float("jfloat"), Double(
65			"jdouble"), Buffer("jobject"), ByteBuffer("jobject"), CharBuffer("jobject"), ShortBuffer("jobject"), IntBuffer("jobject"), LongBuffer(
66			"jobject"), FloatBuffer("jobject"), DoubleBuffer("jobject"), BooleanArray("jbooleanArray"), ByteArray("jbyteArray"), CharArray(
67			"jcharArray"), ShortArray("jshortArray"), IntegerArray("jintArray"), LongArray("jlongArray"), FloatArray("jfloatArray"), DoubleArray(
68			"jdoubleArray"), String("jstring"), Object("jobject"), ObjectArray("jobjectArray");
69
70		private final String jniType;
71
72		ArgumentType (String jniType) {
73			this.jniType = jniType;
74		}
75
76		public boolean isPrimitiveArray () {
77			return toString().endsWith("Array") && this != ObjectArray;
78		}
79
80		public boolean isBuffer () {
81			return toString().endsWith("Buffer");
82		}
83
84		public boolean isObject () {
85			return toString().equals("Object") || this == ObjectArray;
86		}
87
88		public boolean isString () {
89			return toString().equals("String");
90		}
91
92		public boolean isPlainOldDataType () {
93			return !isString() && !isPrimitiveArray() && !isBuffer() && !isObject();
94		}
95
96		public String getBufferCType () {
97			if (!this.isBuffer()) throw new RuntimeException("ArgumentType " + this + " is not a Buffer!");
98			if (this == Buffer) return "unsigned char*";
99			if (this == ByteBuffer) return "char*";
100			if (this == CharBuffer) return "unsigned short*";
101			if (this == ShortBuffer) return "short*";
102			if (this == IntBuffer) return "int*";
103			if (this == LongBuffer) return "long long*";
104			if (this == FloatBuffer) return "float*";
105			if (this == DoubleBuffer) return "double*";
106			throw new RuntimeException("Unknown Buffer type " + this);
107		}
108
109		public String getArrayCType () {
110			if (!this.isPrimitiveArray()) throw new RuntimeException("ArgumentType " + this + " is not an Array!");
111			if (this == BooleanArray) return "bool*";
112			if (this == ByteArray) return "char*";
113			if (this == CharArray) return "unsigned short*";
114			if (this == ShortArray) return "short*";
115			if (this == IntegerArray) return "int*";
116			if (this == LongArray) return "long long*";
117			if (this == FloatArray) return "float*";
118			if (this == DoubleArray) return "double*";
119			throw new RuntimeException("Unknown Array type " + this);
120		}
121
122		public String getJniType () {
123			return jniType;
124		}
125	}
126
127	public static class Argument {
128		final ArgumentType type;
129		private final String name;
130
131		public Argument (ArgumentType type, String name) {
132			this.type = type;
133			this.name = name;
134		}
135
136		public ArgumentType getType () {
137			return type;
138		}
139
140		public String getName () {
141			return name;
142		}
143
144		@Override
145		public String toString () {
146			return "Argument [type=" + type + ", name=" + name + "]";
147		}
148	}
149
150	/** @author mzechner */
151	public static class JavaMethod implements JavaSegment {
152		private final String className;
153		private final String name;
154		private final boolean isStatic;
155		private boolean isManual;
156		private final String returnType;
157		private String nativeCode;
158		private final ArrayList<Argument> arguments;
159		private final boolean hasDisposableArgument;
160		private final int startIndex;
161		private final int endIndex;
162
163		public JavaMethod (String className, String name, boolean isStatic, String returnType, String nativeCode,
164			ArrayList<Argument> arguments, int startIndex, int endIndex) {
165			this.className = className;
166			this.name = name;
167			this.isStatic = isStatic;
168			this.returnType = returnType;
169			this.nativeCode = nativeCode;
170			this.arguments = arguments;
171			this.startIndex = startIndex;
172			this.endIndex = endIndex;
173			for (Argument arg : arguments) {
174				if (arg.type.isPrimitiveArray() || arg.type.isBuffer() || arg.type.isString()) {
175					hasDisposableArgument = true;
176					return;
177				}
178			}
179			hasDisposableArgument = false;
180		}
181
182		public String getName () {
183			return name;
184		}
185
186		public boolean isStatic () {
187			return isStatic;
188		}
189
190		public void setManual (boolean isManual) {
191			this.isManual = isManual;
192		}
193
194		public boolean isManual () {
195			return this.isManual;
196		}
197
198		public String getReturnType () {
199			return returnType;
200		}
201
202		public String getNativeCode () {
203			return nativeCode;
204		}
205
206		public void setNativeCode (String nativeCode) {
207			this.nativeCode = nativeCode;
208		}
209
210		public ArrayList<Argument> getArguments () {
211			return arguments;
212		}
213
214		public boolean hasDisposableArgument () {
215			return hasDisposableArgument;
216		}
217
218		@Override
219		public int getStartIndex () {
220			return startIndex;
221		}
222
223		@Override
224		public int getEndIndex () {
225			return endIndex;
226		}
227
228		public CharSequence getClassName () {
229			return className;
230		}
231
232		@Override
233		public String toString () {
234			return "JavaMethod [className=" + className + ", name=" + name + ", isStatic=" + isStatic + ", returnType=" + returnType
235				+ ", nativeCode=" + nativeCode + ", arguments=" + arguments + ", hasDisposableArgument=" + hasDisposableArgument
236				+ ", startIndex=" + startIndex + ", endIndex=" + endIndex + "]";
237		}
238	}
239}
240