1 /*
2 Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24 /*
25 * jtie_tconv_ptrbyval_impl.hpp
26 */
27
28 #ifndef jtie_tconv_ptrbyval_impl_hpp
29 #define jtie_tconv_ptrbyval_impl_hpp
30
31 #include <assert.h> // not using namespaces yet
32 #include <jni.h>
33
34 #include "jtie_tconv_ptrbyval.hpp"
35 #include "jtie_tconv_impl.hpp"
36 #include "jtie_tconv_array_impl.hpp"
37 #include "jtie_tconv_utils_impl.hpp"
38 #include "helpers.hpp"
39
40 // ---------------------------------------------------------------------------
41 // ArrayPtrParam, ArrayPtrResult
42 // ---------------------------------------------------------------------------
43
44 // Returns zero if an array has a min size; otherwise, an exception is pending.
45 template< jlong N >
46 inline cstatus
ensureMinArraySize(jarray ja,JNIEnv * env)47 ensureMinArraySize(jarray ja, JNIEnv * env) {
48 assert(ja != NULL);
49
50 // init return value to error
51 cstatus s = -1;
52
53 // check the array's length
54 jsize n = env->GetArrayLength(ja);
55 if (env->ExceptionCheck() != JNI_OK) {
56 // exception pending
57 assert(false); // coding error: argument not valid
58 } else {
59 if (n < N) {
60 const char * c = "java/lang/IllegalArgumentException";
61 const char * m = ("JTie: the Java array's length is too small for"
62 " the mapped parameter (file: " __FILE__ ")");
63 registerException(env, c, m);
64 } else {
65 // ok
66 s = 0;
67 }
68 }
69 return s;
70 }
71
72 // Implements the mapping of arrays to pointer parameters.
73 template< typename J, typename C >
74 struct ArrayPtrParam {
75 static C *
convertArrayPtrParam76 convert(cstatus & s, typename J::JA_t * j, JNIEnv * env) {
77 TRACE("C * ArrayPtrParam.convert(cstatus &, typename J::JA_t *, JNIEnv *)");
78 // init return value and status to error
79 s = -1;
80 C * c = NULL;
81
82 if (j == NULL) {
83 // ok
84 s = 0;
85 } else {
86 if (ensureMinArraySize< J::length >(j, env) != 0) {
87 // exception pending
88 } else {
89 assert(env->GetArrayLength(j) >= J::length);
90
91 // get a C array, to be released by releaseArrayElements()
92 // ignore whether C array is pinned or a copy of Java array
93 c = (ArrayConv< typename J::JA_t *, C * >
94 ::getArrayElements(env, j, NULL));
95 if (c == NULL) {
96 // exception pending
97 } else {
98 // ok
99 s = 0;
100 }
101 }
102 }
103 return c;
104 }
105
106 static void
releaseArrayPtrParam107 release(C * c, typename J::JA_t * j, JNIEnv * env) {
108 TRACE("void ArrayPtrParam.release(C *, typename J::JA_t *, JNIEnv *)");
109
110 // compile-time flag whether to copy back any possible changes to the
111 // Java array; tradeoff between
112 // - minor performance gains for non-mutable types (const C *)
113 // - observable data differences for C functions that modify an array
114 // argument by casting away its constness
115 //
116 // the settings below reflect this semantics: for
117 // - mutable types (C *):
118 // ==> all changes to the C array are reflected in the Java array
119 // - non-mutable types (const C *) and
120 // - C functions that modify the array despite its constness and
121 // - a JVM that returns a pointer to the pinned, original array
122 // ==> all changes are reflected in the Java array
123 // - a JVM that choses to return a copy of the original array
124 // ==> any change to the C array is lost
125 const jint copyBackMode
126 = (TypeInfo< C >::isMutable()
127 ? 0 // copy back content if needed and free buffer
128 : JNI_ABORT); // free the buffer without copying back
129
130 if (c == NULL) {
131 assert(j == NULL); // corresponding convert() succeeded (!)
132 // ok
133 } else {
134 assert(j != NULL);
135 // release the C array allocated by getArrayElements()
136 (ArrayConv< typename J::JA_t *, C * >
137 ::releaseArrayElements(env, j, c, copyBackMode));
138 }
139 }
140 };
141
142 // Implements the mapping of arrays to pointer results.
143 template< typename J, typename C >
144 struct ArrayPtrResult {
145 static J *
convertArrayPtrResult146 convert(C * c, JNIEnv * env) {
147 TRACE("J * ArrayPtrResult.convert(C *, JNIEnv *)");
148
149 // init return value to error
150 J * j = NULL;
151
152 if (c == NULL) {
153 // ok
154 } else {
155 jarray jja = (ArrayConv< typename J::JA_t *, C * >
156 ::newArray(env, J::length, c));
157 J * ja = static_cast< J * >(jja);
158 if (ja == NULL) {
159 // exception pending
160 } else {
161 assert(env->GetArrayLength(ja) == J::length);
162 // ok
163 j = ja;
164 }
165 }
166 return j;
167 }
168 };
169
170 // ---------------------------------------------------------------------------
171 // Specializations for pointer type conversions
172 // ---------------------------------------------------------------------------
173
174 // Avoid mapping types by broad, generic rules, which easily results in
175 // template instantiation ambiguities for non-primitive types. Therefore,
176 // we enumerate all specicializations for primitive type pointers.
177
178 // extend array param specializations to const pointers
179 template< typename C >
180 struct Param< _jbooleanArray *, C * const >
181 : Param< _jbooleanArray *, C * > {};
182 template< typename C >
183 struct Param< _jbyteArray *, C * const >
184 : Param< _jbyteArray *, C * > {};
185 template< typename C >
186 struct Param< _jshortArray *, C * const >
187 : Param< _jshortArray *, C * > {};
188 template< typename C >
189 struct Param< _jintArray *, C * const >
190 : Param< _jintArray *, C * > {};
191 template< typename C >
192 struct Param< _jlongArray *, C * const >
193 : Param< _jlongArray *, C * > {};
194 template< typename C >
195 struct Param< _jfloatArray *, C * const >
196 : Param< _jfloatArray *, C * > {};
197 template< typename C >
198 struct Param< _jdoubleArray *, C * const >
199 : Param< _jdoubleArray *, C * > {};
200
201 // extend result array specializations to const pointers
202 template< typename C >
203 struct Result< _jbooleanArray *, C * const >
204 : Result< _jbooleanArray *, C * > {};
205 template< typename C >
206 struct Result< _jbyteArray *, C * const >
207 : Result< _jbyteArray *, C * > {};
208 template< typename C >
209 struct Result< _jshortArray *, C * const >
210 : Result< _jshortArray *, C * > {};
211 template< typename C >
212 struct Result< _jintArray *, C * const >
213 : Result< _jintArray *, C * > {};
214 template< typename C >
215 struct Result< _jlongArray *, C * const >
216 : Result< _jlongArray *, C * > {};
217 template< typename C >
218 struct Result< _jfloatArray *, C * const >
219 : Result< _jfloatArray *, C * > {};
220 template< typename C >
221 struct Result< _jdoubleArray *, C * const >
222 : Result< _jdoubleArray *, C * > {};
223
224 // extend BoundedArrays specializations to const pointers
225 template< typename J, typename C >
226 struct Param< _jtie_j_ArrayMapper< J > *, C * const >
227 : Param< _jtie_j_ArrayMapper< J > *, C * > {};
228 template< typename J, typename C >
229 struct Result< _jtie_j_ArrayMapper< J > *, C * const >
230 : Result< _jtie_j_ArrayMapper< J > *, C * > {};
231
232 // specialize BoundedArrays mapped to pointers/arrays:
233 // - params: require a minimum array length given by the BoundedArray's
234 // static data member
235 // - results: allocate array with a length given by the BoundedArray's
236 // static data member
237 template< typename J, typename C >
238 struct Param< _jtie_j_ArrayMapper< J > *, C * >
239 : ArrayPtrParam< _jtie_j_ArrayMapper< J >, C > {};
240 template< typename J, typename C >
241 struct Result< _jtie_j_ArrayMapper< J > *, C * >
242 : ArrayPtrResult< _jtie_j_ArrayMapper< J >, C > {};
243
244 // specialize arrays mapped to pointers/arrays:
245 // - params: do not require a minimum buffer capacity, for size may be zero
246 // when just passing an address
247 // - results: allocate buffer with a capacity of zero, since the size is
248 // unknown (i.e., just returning an address)
249 #define JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING( J, C ) \
250 template<> \
251 struct Param< J *, C * > \
252 : ArrayPtrParam< _jtie_j_BoundedArray< J, 0 >, C > {}; \
253 template<> \
254 struct Param< J *, const C * > \
255 : ArrayPtrParam< _jtie_j_BoundedArray< J, 0 >, const C > {}; \
256 template<> \
257 struct Result< J *, C * > \
258 : ArrayPtrResult< _jtie_j_BoundedArray< J, 0 >, C > {}; \
259 template<> \
260 struct Result< J *, const C * > \
261 : ArrayPtrResult< _jtie_j_BoundedArray< J, 0 >, const C > {};
262
263 // ---------------------------------------------------------------------------
264 // Specializations for pointer to exact-width primitive type conversions
265 // ---------------------------------------------------------------------------
266
267 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jbooleanArray, bool)
268
269 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jbyteArray, char)
270 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jbyteArray, signed char)
271 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jbyteArray, unsigned char)
272
273 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jfloatArray, float)
274 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jdoubleArray, double)
275
276 // ---------------------------------------------------------------------------
277 // Specializations for pointer to variable-width primitive type conversions
278 // ---------------------------------------------------------------------------
279
280 // jshort in LP32, ILP32, LP64, ILP64, LLP64
281 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jshortArray, signed short)
282 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jshortArray, unsigned short)
283
284 // jshort in LP32
285 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jshortArray, signed int)
286 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jshortArray, unsigned int)
287
288 // jint in ILP32, LP64, LLP64
289 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jintArray, signed int)
290 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jintArray, unsigned int)
291
292 // jint in LP32, ILP32, LLP64
293 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jintArray, signed long)
294 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jintArray, unsigned long)
295
296 // jlong in ILP64
297 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jlongArray, signed int)
298 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jlongArray, unsigned int)
299
300 // jlong in LP64, ILP64
301 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jlongArray, signed long)
302 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jlongArray, unsigned long)
303
304 // jlong in LLP64
305 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jlongArray, signed long long)
306 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jlongArray, unsigned long long)
307
308 // jdouble
309 JTIE_SPECIALIZE_ARRAY_TYPE_MAPPING(_jdoubleArray, long double)
310
311 // ---------------------------------------------------------------------------
312
313 #endif // jtie_tconv_ptrbyval_impl_hpp
314