1 /*
2 * Copyright (C) 2013 Team XBMC
3 * http://xbmc.org
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 */
20 /*
21 * Copyright (c) 2011-2012 Dmitry Moskalchuk <dm@crystax.net>.
22 * All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without modification, are
25 * permitted provided that the following conditions are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright notice, this list of
28 * conditions and the following disclaimer.
29 *
30 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
31 * of conditions and the following disclaimer in the documentation and/or other materials
32 * provided with the distribution.
33 *
34 * THIS SOFTWARE IS PROVIDED BY Dmitry Moskalchuk ''AS IS'' AND ANY EXPRESS OR IMPLIED
35 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Dmitry Moskalchuk OR
37 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
40 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 *
44 * The views and conclusions contained in the software and documentation are those of the
45 * authors and should not be interpreted as representing official policies, either expressed
46 * or implied, of Dmitry Moskalchuk.
47 */
48
49 #define DBG(fmt, ...)
50 #include <string>
51 #include <string.h>
52 #include "jutils-details.hpp"
53
54 namespace jni
55 {
56
57 namespace details
58 {
59
cast(jstring const & v)60 std::string jcast_helper<std::string, jstring>::cast(jstring const &v)
61 {
62 JNIEnv *env = xbmc_jnienv();
63 std::string ret;
64 if (!v)
65 return ret;
66
67 const char *s = env->GetStringUTFChars(v, JNI_FALSE);
68 if (s)
69 {
70 ret = s;
71 env->ReleaseStringUTFChars(v, s);
72 }
73 return ret;
74 }
75
cast(const std::string & s)76 jhstring jcast_helper<jhstring, std::string>::cast(const std::string &s)
77 {
78 JNIEnv *env = xbmc_jnienv();
79 jstring ret = NULL;
80 if (!s.empty())
81 {
82 ret = env->NewStringUTF(s.c_str());
83 }
84 return jhstring(ret);
85 }
86
cast(const std::vector<char> & s)87 jhbyteArray jcast_helper<jhbyteArray, std::vector<char> >::cast(const std::vector<char> &s)
88 {
89 JNIEnv *env = xbmc_jnienv();
90 jbyteArray ret = NULL;
91 if (!s.empty())
92 {
93 char* pArray;
94 ret = env->NewByteArray(s.size());
95 if ((pArray = (char*)env->GetPrimitiveArrayCritical(ret, NULL)))
96 {
97 memcpy(pArray, s.data(), s.size());
98 env->ReleasePrimitiveArrayCritical(ret, pArray, 0);
99 }
100 }
101 return jhbyteArray(ret);
102 }
103
104
cast(const std::vector<int16_t> & s)105 jhshortArray jcast_helper<jhshortArray, std::vector<int16_t> >::cast(const std::vector<int16_t> &s)
106 {
107 JNIEnv *env = xbmc_jnienv();
108 jshortArray ret = NULL;
109 if (!s.empty())
110 {
111 char* pArray;
112 ret = env->NewShortArray(s.size());
113 if ((pArray = (char*)env->GetPrimitiveArrayCritical(ret, NULL)))
114 {
115 memcpy(pArray, s.data(), s.size() * sizeof(int16_t));
116 env->ReleasePrimitiveArrayCritical(ret, pArray, 0);
117 }
118 }
119 return jhshortArray(ret);
120 }
121
cast(const std::vector<float> & s)122 jhfloatArray jcast_helper<jhfloatArray, std::vector<float> >::cast(const std::vector<float> &s)
123 {
124 JNIEnv *env = xbmc_jnienv();
125 jfloatArray ret = NULL;
126 if (!s.empty())
127 {
128 char* pArray;
129 ret = env->NewFloatArray(s.size());
130 if ((pArray = (char*)env->GetPrimitiveArrayCritical(ret, NULL)))
131 {
132 memcpy(pArray, s.data(), s.size() * sizeof(float));
133 env->ReleasePrimitiveArrayCritical(ret, pArray, 0);
134 }
135 }
136 return jhfloatArray(ret);
137 }
138
cast(const std::vector<std::string> & s)139 jhobjectArray jcast_helper<jhobjectArray, std::vector<std::string> >::cast(const std::vector<std::string> &s)
140 {
141 JNIEnv *env = xbmc_jnienv();
142 jobjectArray ret = NULL;
143 if (!s.empty())
144 {
145 ret = env->NewObjectArray(s.size(), env->FindClass("java/lang/String"), NULL);
146 for (unsigned int i = 0; i < s.size(); i++)
147 env->SetObjectArrayElement(ret, i, env->NewStringUTF(s[i].c_str()));
148 }
149 return jhobjectArray(ret);
150 }
151
cast(const jobjectArray & s)152 std::vector<std::string> jcast_helper<std::vector<std::string>, jobjectArray >::cast(const jobjectArray &s)
153 {
154 JNIEnv *env = xbmc_jnienv();
155 std::vector<std::string> ret;
156 jstring element;
157 const char* newString = NULL;
158 if (!s)
159 return ret;
160
161 unsigned int arraySize = env->GetArrayLength(s);
162 ret.reserve(arraySize);
163 for (unsigned int i = 0; i < arraySize; ++i)
164 {
165 element = (jstring) env->GetObjectArrayElement(s, i);
166 newString = env->GetStringUTFChars(element, JNI_FALSE);
167 if (newString)
168 {
169 ret.push_back(newString);
170 env->ReleaseStringUTFChars(element, newString);
171 }
172 env->DeleteLocalRef(element);
173 }
174 return ret;
175 }
176
177 #define CRYSTAX_PP_CAT(a, b, c) CRYSTAX_PP_CAT_IMPL(a, b, c)
178 #define CRYSTAX_PP_CAT_IMPL(a, b, c) a ## b ## c
179
180 #define CRYSTAX_PP_STRINGIZE(a) CRYSTAX_PP_STRINGIZE_IMPL(a)
181 #define CRYSTAX_PP_STRINGIZE_IMPL(a) #a
182
183 #define JNI_MAP_void Void
184 #define JNI_MAP_jboolean Boolean
185 #define JNI_MAP_jbyte Byte
186 #define JNI_MAP_jchar Char
187 #define JNI_MAP_jshort Short
188 #define JNI_MAP_jint Int
189 #define JNI_MAP_jlong Long
190 #define JNI_MAP_jfloat Float
191 #define JNI_MAP_jdouble Double
192 #define JNI_MAP_jhobject Object
193 #define JNI_MAP_jhclass Object
194 #define JNI_MAP_jhstring Object
195 #define JNI_MAP_jhthrowable Object
196 #define JNI_MAP_jharray Object
197 #define JNI_MAP_jhbooleanArray Object
198 #define JNI_MAP_jhbyteArray Object
199 #define JNI_MAP_jhshortArray Object
200 #define JNI_MAP_jhintArray Object
201 #define JNI_MAP_jhlongArray Object
202 #define JNI_MAP_jhfloatArray Object
203 #define JNI_MAP_jhdoubleArray Object
204 #define JNI_MAP_jhobjectArray Object
205
206 #define JNI_MAP(type) JNI_MAP_ ## type
207
208 template <typename T>
209 struct jni_base_type
210 {
211 typedef T type_t;
212 };
213
214 template <typename T>
215 struct jni_base_type<jholder<T> >
216 {
217 typedef T type_t;
218 };
219
call_void_method(JNIEnv * env,jobject obj,jmethodID mid,...)220 void call_void_method(JNIEnv *env, jobject obj, jmethodID mid, ...)
221 {
222 va_list vl;
223 va_start(vl, mid);
224 env->CallVoidMethodV(obj, mid, vl);
225 va_end(vl);
226 }
227
call_void_method(JNIEnv * env,jclass cls,jmethodID mid,...)228 void call_void_method(JNIEnv *env, jclass cls, jmethodID mid, ...)
229 {
230 va_list vl;
231 va_start(vl, mid);
232 env->CallStaticVoidMethodV(cls, mid, vl);
233 va_end(vl);
234 }
235
new_object(JNIEnv * env,jclass cls,jmethodID mid,...)236 jhobject new_object(JNIEnv *env, jclass cls, jmethodID mid, ...)
237 {
238 va_list vl;
239 va_start(vl,mid);
240 jhobject ret;
241 if (env && cls && mid)
242 ret = jholder<jobject>(env->NewObjectV(cls, mid, vl));
243 va_end(vl);
244 return ret;
245 }
246
247 template <typename T>
248 struct result_helper
249 {
make_resultjni::details::result_helper250 static T make_result(JNIEnv *env, T obj) {(void)env; return obj;}
251 };
252
253 template <typename T>
254 struct result_helper<jholder<T> >
255 {
make_resultjni::details::result_helper256 static jholder<T> make_result(JNIEnv *env, T obj) {return jholder<T>(env->ExceptionCheck() ? 0 : obj);}
257 };
258
259 #define CRYSTAX_PP_STEP(type) \
260 type CRYSTAX_PP_CAT(get_, type, _field)(JNIEnv *env, jobject obj, jfieldID fid) \
261 { \
262 DBG("calling Get" CRYSTAX_PP_STRINGIZE(JNI_MAP(type)) "Field"); \
263 return type((jni_base_type<type>::type_t)CRYSTAX_PP_CAT(env->Get, JNI_MAP(type), Field)(obj, fid)); \
264 } \
265 type CRYSTAX_PP_CAT(get_static_, type, _field)(JNIEnv *env, jclass cls, jfieldID fid) \
266 { \
267 DBG("calling GetStatic" CRYSTAX_PP_STRINGIZE(JNI_MAP(type)) "Field"); \
268 return type((jni_base_type<type>::type_t)CRYSTAX_PP_CAT(env->GetStatic, JNI_MAP(type), Field)(cls, fid)); \
269 } \
270 void CRYSTAX_PP_CAT(set_, type, _field)(JNIEnv *env, jobject obj, jfieldID fid, type const &arg) \
271 { \
272 DBG("calling Set" CRYSTAX_PP_STRINGIZE(JNI_MAP(type)) "Field"); \
273 CRYSTAX_PP_CAT(env->Set, JNI_MAP(type), Field)(obj, fid, (jni_base_type<type>::type_t)raw_arg(arg)); \
274 } \
275 void CRYSTAX_PP_CAT(set_, type, _field)(JNIEnv *env, jclass cls, jfieldID fid, type const &arg) \
276 { \
277 DBG("calling SetStatic" CRYSTAX_PP_STRINGIZE(JNI_MAP(type)) "Field"); \
278 CRYSTAX_PP_CAT(env->SetStatic, JNI_MAP(type), Field)(cls, fid, (jni_base_type<type>::type_t)raw_arg(arg)); \
279 } \
280 type CRYSTAX_PP_CAT(call_, type, _method)(JNIEnv *env, jobject obj, jmethodID mid, ...) \
281 { \
282 DBG("calling Call" CRYSTAX_PP_STRINGIZE(JNI_MAP(type)) "MethodV"); \
283 va_list vl; \
284 va_start(vl, mid); \
285 typedef jni_base_type<type>::type_t result_t; \
286 result_t result = (result_t)CRYSTAX_PP_CAT(env->Call, JNI_MAP(type), MethodV)(obj, mid, vl); \
287 va_end(vl); \
288 return result_helper<type>::make_result(env, result); \
289 } \
290 type CRYSTAX_PP_CAT(call_, type, _method)(JNIEnv *env, jclass cls, jmethodID mid, ...) \
291 { \
292 DBG("calling CallStatic" CRYSTAX_PP_STRINGIZE(JNI_MAP(type)) "MethodV"); \
293 va_list vl; \
294 va_start(vl, mid); \
295 typedef jni_base_type<type>::type_t result_t; \
296 result_t result = (result_t)CRYSTAX_PP_CAT(env->CallStatic, JNI_MAP(type), MethodV)(cls, mid, vl); \
297 va_end(vl); \
298 return result_helper<type>::make_result(env, result); \
299 }
300 #include "jni.inc"
301 #undef CRYSTAX_PP_STEP
302
303 template <> const char *jni_signature<jboolean>::signature = "Z";
304 template <> const char *jni_signature<jbyte>::signature = "B";
305 template <> const char *jni_signature<jchar>::signature = "C";
306 template <> const char *jni_signature<jshort>::signature = "S";
307 template <> const char *jni_signature<jint>::signature = "I";
308 template <> const char *jni_signature<jlong>::signature = "J";
309 template <> const char *jni_signature<jfloat>::signature = "F";
310 template <> const char *jni_signature<jdouble>::signature = "D";
311 template <> const char *jni_signature<jhobject>::signature = "Ljava/lang/Object;";
312 template <> const char *jni_signature<jhclass>::signature = "Ljava/lang/Class;";
313 template <> const char *jni_signature<jhstring>::signature = "Ljava/lang/String;";
314 template <> const char *jni_signature<jhthrowable>::signature = "Ljava/lang/Throwable;";
315 template <> const char *jni_signature<jhbooleanArray>::signature = "[Z";
316 template <> const char *jni_signature<jhbyteArray>::signature = "[B";
317 template <> const char *jni_signature<jhcharArray>::signature = "[C";
318 template <> const char *jni_signature<jhshortArray>::signature = "[S";
319 template <> const char *jni_signature<jhintArray>::signature = "[I";
320 template <> const char *jni_signature<jhlongArray>::signature = "[J";
321 template <> const char *jni_signature<jhfloatArray>::signature = "[F";
322 template <> const char *jni_signature<jhdoubleArray>::signature = "[D";
323 template <> const char *jni_signature<jhobjectArray>::signature = "[Ljava/lang/Object;";
324
325 } // namespace details
326 } // namespace jni
327