MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
jtie_tconv_ptrbybb_impl.hpp
1 /*
2  Copyright 2010 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
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; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 /*
19  * jtie_tconv_ptrbybb_impl.hpp
20  */
21 
22 #ifndef jtie_tconv_ptrbybb_impl_hpp
23 #define jtie_tconv_ptrbybb_impl_hpp
24 
25 #include <assert.h> // not using namespaces yet
26 #include <string.h> // not using namespaces yet
27 #include <jni.h>
28 
29 #include "jtie_tconv_ptrbybb.hpp"
30 #include "jtie_stdint.h"
31 #include "jtie_tconv_impl.hpp"
32 #include "jtie_tconv_idcache_impl.hpp"
33 #include "jtie_tconv_utils_impl.hpp"
34 #include "helpers.hpp"
35 
36 // ---------------------------------------------------------------------------
37 // ByteBufferPtrParam, ByteBufferPtrResult
38 // ---------------------------------------------------------------------------
39 
40 // Defines the method info type for ByteBuffer.isReadOnly().
41 JTIE_DEFINE_METHOD_MEMBER_INFO(_ByteBuffer_isReadOnly)
42 
43 // Provides a (cached) access to method Id of ByteBuffer.isReadOnly().
44 //typedef JniMemberId< NO_CACHING, _ByteBuffer_isReadOnly >
45 typedef JniMemberId< WEAK_CACHING, _ByteBuffer_isReadOnly >
46  ByteBuffer_isReadOnly;
47 
48 // ---------------------------------------------------------------------------
49 
50 // Defines the method info type for ByteBuffer.asReadOnlyBuffer().
51 JTIE_DEFINE_METHOD_MEMBER_INFO(_ByteBuffer_asReadOnlyBuffer)
52 
53 // Provides a (cached) access to method Id of ByteBuffer.asReadOnlyBuffer().
54 //typedef JniMemberId< NO_CACHING, _ByteBuffer_asReadOnlyBuffer >
55 typedef JniMemberId< WEAK_CACHING, _ByteBuffer_asReadOnlyBuffer >
56  ByteBuffer_asReadOnlyBuffer;
57 
58 // ---------------------------------------------------------------------------
59 
60 // Defines the method info type for ByteBuffer.remaining().
61 JTIE_DEFINE_METHOD_MEMBER_INFO(_ByteBuffer_remaining)
62 
63 // Provides a (cached) access to method Id of ByteBuffer.remaining().
64 //typedef JniMemberId< NO_CACHING, _ByteBuffer_remaining >
65 typedef JniMemberId< WEAK_CACHING, _ByteBuffer_remaining >
66  ByteBuffer_remaining;
67 
68 // ---------------------------------------------------------------------------
69 
70 // Defines the method info type for ByteBuffer.position().
71 JTIE_DEFINE_METHOD_MEMBER_INFO(_ByteBuffer_position)
72 
73 // Provides a (cached) access to method Id of ByteBuffer.position().
74 //typedef JniMemberId< NO_CACHING, _ByteBuffer_position >
75 typedef JniMemberId< WEAK_CACHING, _ByteBuffer_position >
76  ByteBuffer_position;
77 
78 // ---------------------------------------------------------------------------
79 
80 // helper functions
81 
82 inline cstatus
83 ensureMutableBuffer(jtie_j_n_ByteBuffer jbb, JNIEnv * env);
84 
85 template< jlong N >
86 inline cstatus
87 ensureMinBufferSize(jtie_j_n_ByteBuffer jbb, JNIEnv * env);
88 
89 inline int32_t
90 getBufferPosition(jtie_j_n_ByteBuffer jbb, JNIEnv * env);
91 
92 inline void *
93 getByteBufferAddress(jtie_j_n_ByteBuffer jbb, JNIEnv * env);
94 
95 template< typename J >
96 inline J *
97 wrapAddressAsByteBuffer(const void * c, JNIEnv * env);
98 
99 template< typename J >
100 inline J *
101 wrapByteBufferAsReadOnly(J * jbb, JNIEnv * env);
102 
103 // ---------------------------------------------------------------------------
104 
105 // Implements the mapping of ByteBuffers to pointer parameters.
106 template< typename J, typename C >
108 
109  static C *
110  convert(cstatus & s, jtie_j_n_ByteBuffer j, JNIEnv * env) {
111  TRACE("C * ByteBufferPtrParam.convert(cstatus &, jtie_j_n_ByteBuffer, JNIEnv *)");
112 
113  // init return value and status to error
114  s = -1;
115  C * c = NULL;
116 
117  if (j == NULL) {
118  // ok
119  s = 0;
120  } else {
122  && (ensureMutableBuffer(j, env) != 0)) {
123  // exception pending
124  } else {
125  if (ensureMinBufferSize< J::capacity >(j, env) != 0) {
126  // exception pending
127  } else {
128  assert(env->GetDirectBufferCapacity(j) >= J::capacity);
129  void * a = getByteBufferAddress(j, env);
130  if (a == NULL) {
131  // exception pending
132  } else {
133  // ok
134  s = 0;
135  c = static_cast< C * >(a);
136  }
137  }
138  }
139  }
140  return c;
141  }
142 
143  static void
144  release(C * c, jtie_j_n_ByteBuffer j, JNIEnv * env) {
145  TRACE("void ByteBufferPtrParam.release(C *, jtie_j_n_ByteBuffer, JNIEnv *)");
146  (void)c; (void)j; (void)env;
147  }
148 };
149 
150 // Implements the mapping of ByteBuffers to pointer results.
151 template< typename J, typename C >
153  static J *
154  convert(C * c, JNIEnv * env) {
155  TRACE("J * ByteBufferPtrResult.convert(C *, JNIEnv *)");
156 
157  // init return value to error
158  J * j = NULL;
159 
160  if (c == NULL) {
161  // ok
162  } else {
163  J * jbb = wrapAddressAsByteBuffer< J >(c, env);
164  if (jbb == NULL) {
165  // exception pending
166  } else {
167  assert(env->GetDirectBufferCapacity(jbb) == J::capacity);
168  if (TypeInfo< C >::isMutable()) {
169  // ok
170  j = jbb;
171  } else {
172  J * jrobb = wrapByteBufferAsReadOnly(jbb, env);
173  if (jrobb == NULL) {
174  // exception pending
175  } else {
176  // ok
177  j = jrobb;
178  }
179  env->DeleteLocalRef(jbb);
180  }
181  }
182  }
183  return j;
184  }
185 };
186 
187 // ---------------------------------------------------------------------------
188 // Helper functions
189 // ---------------------------------------------------------------------------
190 
191 // Returns zero if a buffer is read-only; otherwise, an exception is pending.
192 inline cstatus
193 ensureMutableBuffer(jtie_j_n_ByteBuffer jbb, JNIEnv * env) {
194  // init return value to error
195  cstatus s = -1;
196 
197  // get a (local or global) class object reference
198  jclass cls = ByteBuffer_isReadOnly::getClass(env);
199  if (cls == NULL) {
200  // exception pending
201  } else {
202  // get the method ID valid along with the class object reference
203  jmethodID mid = ByteBuffer_isReadOnly::getId(env, cls);
204  if (mid == NULL) {
205  // exception pending
206  } else {
207  jboolean ro = env->CallBooleanMethod(jbb, mid);
208  if (env->ExceptionCheck() != JNI_OK) {
209  // exception pending
210  } else {
211  if (ro) {
212  const char * c = "java/nio/ReadOnlyBufferException";
213  // this exception's c'tor does not take messages
214  const char * m = NULL;
215  //const char * m = ("JTie: java.nio.ByteBuffer must"
216  // " not be read-only when mapped to a"
217  // " non-const object reference type");
218  registerException(env, c, m);
219  } else {
220  // ok
221  s = 0;
222  }
223  }
224  }
225  // release reference (if needed)
226  ByteBuffer_isReadOnly::releaseRef(env, cls);
227  }
228  return s;
229 }
230 
231 // Returns zero if a buffer has a min size; otherwise, an exception is pending.
232 template< jlong N >
233 inline cstatus
234 ensureMinBufferSize(jtie_j_n_ByteBuffer jbb, JNIEnv * env) {
235  // init return value to error
236  cstatus s = -1;
237 
238  // check the ByteBuffer's capacity
239  jlong bc = env->GetDirectBufferCapacity(jbb);
240  if (bc < N) {
241  // crashes with gcc & operator<<(ostream &, jlong/jint)
242  char m[256];
243  const long long n = N;
244  const long long BC = bc;
245  if (bc < 0) {
246  sprintf(m, "JTie: failed to retrieve java.nio.ByteBuffer's"
247  " capacity (perhaps, a direct buffer or an unaligned"
248  " view buffer)");
249  } else {
250  sprintf(m, "JTie: java.nio.ByteBuffer's capacity is too small"
251  " for the mapped parameter;"
252  " required: %lld, found: %lld.", n, BC);
253  }
254  const char * c = "java/lang/IllegalArgumentException";
255  registerException(env, c, m);
256  } else {
257 #ifndef NDEBUG
258  // get a (local or global) class object reference
259  jclass cls = ByteBuffer_remaining::getClass(env);
260  if (cls == NULL) {
261  // exception pending
262  } else {
263  // get the method ID valid along with the class object reference
264  jmethodID mid = ByteBuffer_remaining::getId(env, cls);
265  if (mid == NULL) {
266  // exception pending
267  } else {
268  jint r = env->CallIntMethod(jbb, mid);
269  if (env->ExceptionCheck() != JNI_OK) {
270  // exception pending
271  } else {
272  if (r < N) {
273  // crashes with gcc & operator<<(ostream &, jlong/jint)
274  char m[256];
275  const long long n = N;
276  const long long R = r;
277  sprintf(m, "JTie: too few remaining elements of"
278  " java.nio.ByteBuffer for mapped parameter;"
279  " required: %lld, found: %lld", n, R);
280  const char * c = "java/lang/IllegalArgumentException";
281  registerException(env, c, m);
282  } else {
283  // ok
284  s = 0;
285  }
286  }
287  }
288  // release reference (if needed)
289  ByteBuffer_remaining::releaseRef(env, cls);
290  }
291 #else
292  // ok
293  s = 0;
294 #endif // NDEBUG
295  }
296  return s;
297 }
298 
299 // Returns the buffer's position; if the position cannot be accessed for any
300 // reason, a negative value is returned and an exception is pending.
301 inline int32_t
302 getBufferPosition(jtie_j_n_ByteBuffer jbb, JNIEnv * env) {
303  // init return value to error
304  jint pos = -1;
305 
306  // get a (local or global) class object reference
307  jclass cls = ByteBuffer_position::getClass(env);
308  if (cls == NULL) {
309  // exception pending
310  } else {
311  // get the method ID valid along with the class object reference
312  jmethodID mid = ByteBuffer_position::getId(env, cls);
313  if (mid == NULL) {
314  // exception pending
315  } else {
316  jint p = env->CallIntMethod(jbb, mid);
317  if (env->ExceptionCheck() != JNI_OK) {
318  // exception pending
319  } else {
320  // ok
321  pos = p;
322  }
323  }
324  // release reference (if needed)
325  ByteBuffer_position::releaseRef(env, cls);
326  }
327  return pos;
328 }
329 
330 
331 // Returns the buffer address of a direct ByteBuffer; if the address cannot
332 // be accessed for any reason, NULL is returned and an exception is pending.
333 inline void *
334 getByteBufferAddress(jtie_j_n_ByteBuffer jbb, JNIEnv * env) {
335  // get the internal buffer address of direct ByteBuffer
336  char * a = static_cast< char * >(env->GetDirectBufferAddress(jbb));
337  if (a == NULL) {
338 #ifndef JTIE_BYTEBUFFER_NO_ZERO_CAPACITY_MAPPING
339  // check for direct ByteBuffer of zero-capacity
340  if (env->GetDirectBufferCapacity(jbb) != 0) {
341 #endif // JTIE_BYTEBUFFER_NO_ZERO_CAPACITY_MAPPING
342  // raise exception
343  const char * m = ("JTie: cannot get the java.nio.ByteBuffer's"
344  " internal address (perhaps, not a direct buffer"
345  " or its memory region is undefined)");
346  const char * c = "java/lang/IllegalArgumentException";
347  registerException(env, c, m);
348 #ifndef JTIE_BYTEBUFFER_NO_ZERO_CAPACITY_MAPPING
349  } else {
350  // ok
351  assert(a == NULL);
352  }
353 #endif // JTIE_BYTEBUFFER_NO_ZERO_CAPACITY_MAPPING
354  } else {
355 #ifndef JTIE_BYTEBUFFER_MAPS_TO_BASE_ADDRESS
356  int32_t p = getBufferPosition(jbb, env);
357  if (p < 0) {
358  // exception pending
359  } else {
360  // ok
361  a += p;
362  }
363 #endif // JTIE_BYTEBUFFER_MAPS_TO_BASE_ADDRESS
364  }
365  return a;
366 }
367 
368 // Constructs a fixed-length, direct ByteBuffer wrapping an address.
369 template< typename J >
370 inline J *
371 wrapAddressAsByteBuffer(const void * c, JNIEnv * env) {
372  // ok to strip const here, will be wrapped as read-only buffer then
373  void * mc = const_cast< void * >(c);
374  jobject jo = env->NewDirectByteBuffer(mc, J::capacity);
375  return static_cast< J * >(jo);
376 }
377 
378 // Constructs a read-only ByteBuffer wrapping a buffer.
379 template< typename J >
380 inline J *
381 wrapByteBufferAsReadOnly(J * jbb, JNIEnv * env) {
382  // init return value to error
383  J * j = NULL;
384 
385  // get a (local or global) class object reference
386  jclass cls = ByteBuffer_asReadOnlyBuffer::getClass(env);
387  if (cls == NULL) {
388  // exception pending
389  } else {
390  // get the method ID valid along with the class object reference
391  jmethodID mid = ByteBuffer_asReadOnlyBuffer::getId(env, cls);
392  if (mid == NULL) {
393  // exception pending
394  } else {
395  // get a read-only copy from the ByteBuffer object
396  jobject jo = env->CallObjectMethod(jbb, mid);
397  if (env->ExceptionCheck() != JNI_OK) {
398  // exception pending
399  } else {
400  if (jo == NULL) {
401  const char * m
402  = ("JTie: invalid NULL return from"
403  " java.nio.ByteBuffer.asReadOnlyBuffer()");
404  const char * c = "java/lang/AssertionError";
405  registerException(env, c, m);
406  } else {
407  j = static_cast< J * >(jo);
408  }
409  }
410  }
411  // release reference (if needed)
412  ByteBuffer_asReadOnlyBuffer::releaseRef(env, cls);
413  }
414  return j;
415 }
416 
417 // ---------------------------------------------------------------------------
418 // Specializations for ByteBuffer type conversions
419 // ---------------------------------------------------------------------------
420 
421 // extend ByteBuffer specializations to const pointers
422 template< typename C >
423 struct Param< jtie_j_n_ByteBuffer, C * const >
425 template< typename C >
426 struct Result< jtie_j_n_ByteBuffer, C * const >
428 template< typename J, typename C >
429 struct Param< _jtie_j_n_ByteBufferMapper< J > *, C * const >
431 template< typename J, typename C >
432 struct Result< _jtie_j_n_ByteBufferMapper< J > *, C * const >
434 
435 // specialize BoundedByteBuffers mapped to pointers/arrays:
436 // - params: require a minimum buffer capacity given by the
437 // BoundedByteBuffer's static data member
438 // - results: allocate buffer with a capacity given by the
439 // BoundedByteBuffer's static data member
440 template< typename J, typename C >
441 struct Param< _jtie_j_n_ByteBufferMapper< J > *, C * >
443 template< typename J, typename C >
444 struct Result< _jtie_j_n_ByteBufferMapper< J > *, C * >
446 
447 // specialize ByteBuffers mapped to pointers/arrays:
448 // - params: do not require a minimum buffer capacity, for size may be zero
449 // when just passing an address
450 // - results: allocate buffer with a capacity of zero, since the size is
451 // unknown (i.e., just returning an address)
452 template< typename C >
455 template< typename C >
458 
459 // ---------------------------------------------------------------------------
460 
461 #endif // jtie_tconv_ptrbybb_impl_hpp