1*65c59e02SInna Palant /*
2*65c59e02SInna Palant * Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palant *
4*65c59e02SInna Palant * Licensed under the Apache License, Version 2.0 (the "License");
5*65c59e02SInna Palant * you may not use this file except in compliance with the License.
6*65c59e02SInna Palant * You may obtain a copy of the License at
7*65c59e02SInna Palant *
8*65c59e02SInna Palant * http://www.apache.org/licenses/LICENSE-2.0
9*65c59e02SInna Palant *
10*65c59e02SInna Palant * Unless required by applicable law or agreed to in writing, software
11*65c59e02SInna Palant * distributed under the License is distributed on an "AS IS" BASIS,
12*65c59e02SInna Palant * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*65c59e02SInna Palant * See the License for the specific language governing permissions and
14*65c59e02SInna Palant * limitations under the License.
15*65c59e02SInna Palant */
16*65c59e02SInna Palant
17*65c59e02SInna Palant #include <fbjni/ByteBuffer.h>
18*65c59e02SInna Palant
19*65c59e02SInna Palant #include <stdexcept>
20*65c59e02SInna Palant
21*65c59e02SInna Palant namespace facebook {
22*65c59e02SInna Palant namespace jni {
23*65c59e02SInna Palant
rewind() const24*65c59e02SInna Palant void JBuffer::rewind() const {
25*65c59e02SInna Palant static auto meth =
26*65c59e02SInna Palant javaClassStatic()->getMethod<alias_ref<JBuffer>()>("rewind");
27*65c59e02SInna Palant meth(self());
28*65c59e02SInna Palant }
29*65c59e02SInna Palant
getDirectAddress() const30*65c59e02SInna Palant void* JBuffer::getDirectAddress() const {
31*65c59e02SInna Palant if (!self()) {
32*65c59e02SInna Palant throwNewJavaException(
33*65c59e02SInna Palant "java/lang/NullPointerException", "java.lang.NullPointerException");
34*65c59e02SInna Palant }
35*65c59e02SInna Palant void* addr = Environment::current()->GetDirectBufferAddress(self());
36*65c59e02SInna Palant FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
37*65c59e02SInna Palant if (!addr) {
38*65c59e02SInna Palant throw std::runtime_error(
39*65c59e02SInna Palant isDirect() ? "Attempt to get direct bytes of non-direct buffer."
40*65c59e02SInna Palant : "Error getting direct bytes of buffer.");
41*65c59e02SInna Palant }
42*65c59e02SInna Palant return addr;
43*65c59e02SInna Palant }
44*65c59e02SInna Palant
getDirectCapacity() const45*65c59e02SInna Palant size_t JBuffer::getDirectCapacity() const {
46*65c59e02SInna Palant if (!self()) {
47*65c59e02SInna Palant throwNewJavaException(
48*65c59e02SInna Palant "java/lang/NullPointerException", "java.lang.NullPointerException");
49*65c59e02SInna Palant }
50*65c59e02SInna Palant int size = Environment::current()->GetDirectBufferCapacity(self());
51*65c59e02SInna Palant FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
52*65c59e02SInna Palant if (size < 0) {
53*65c59e02SInna Palant throw std::runtime_error(
54*65c59e02SInna Palant isDirect() ? "Attempt to get direct size of non-direct buffer."
55*65c59e02SInna Palant : "Error getting direct size of buffer.");
56*65c59e02SInna Palant }
57*65c59e02SInna Palant return static_cast<size_t>(size);
58*65c59e02SInna Palant }
59*65c59e02SInna Palant
isDirect() const60*65c59e02SInna Palant bool JBuffer::isDirect() const {
61*65c59e02SInna Palant static auto meth = javaClassStatic()->getMethod<jboolean()>("isDirect");
62*65c59e02SInna Palant return meth(self());
63*65c59e02SInna Palant }
64*65c59e02SInna Palant
nativeOrder()65*65c59e02SInna Palant local_ref<JByteOrder> JByteOrder::nativeOrder() {
66*65c59e02SInna Palant static auto meth =
67*65c59e02SInna Palant JByteOrder::javaClassStatic()->getStaticMethod<local_ref<JByteOrder>()>(
68*65c59e02SInna Palant "nativeOrder");
69*65c59e02SInna Palant return meth(JByteOrder::javaClassStatic());
70*65c59e02SInna Palant }
71*65c59e02SInna Palant
bigEndian()72*65c59e02SInna Palant local_ref<JByteOrder> JByteOrder::bigEndian() {
73*65c59e02SInna Palant static auto field =
74*65c59e02SInna Palant JByteOrder::javaClassStatic()->getStaticField<JByteOrder>("BIG_ENDIAN");
75*65c59e02SInna Palant return JByteOrder::javaClassStatic()->getStaticFieldValue(field);
76*65c59e02SInna Palant }
77*65c59e02SInna Palant
littleEndian()78*65c59e02SInna Palant local_ref<JByteOrder> JByteOrder::littleEndian() {
79*65c59e02SInna Palant static auto field = JByteOrder::javaClassStatic()->getStaticField<JByteOrder>(
80*65c59e02SInna Palant "LITTLE_ENDIAN");
81*65c59e02SInna Palant return JByteOrder::javaClassStatic()->getStaticFieldValue(field);
82*65c59e02SInna Palant }
83*65c59e02SInna Palant
wrapBytes(uint8_t * data,size_t size)84*65c59e02SInna Palant local_ref<JByteBuffer> JByteBuffer::wrapBytes(uint8_t* data, size_t size) {
85*65c59e02SInna Palant // env->NewDirectByteBuffer requires that size is positive. Android's
86*65c59e02SInna Palant // dalvik returns an invalid result and Android's art aborts if size == 0.
87*65c59e02SInna Palant // Workaround this by using a slow path through Java in that case.
88*65c59e02SInna Palant if (!size) {
89*65c59e02SInna Palant return allocateDirect(0);
90*65c59e02SInna Palant }
91*65c59e02SInna Palant auto res = adopt_local(static_cast<javaobject>(
92*65c59e02SInna Palant Environment::current()->NewDirectByteBuffer(data, size)));
93*65c59e02SInna Palant FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
94*65c59e02SInna Palant if (!res) {
95*65c59e02SInna Palant throw std::runtime_error("Direct byte buffers are unsupported.");
96*65c59e02SInna Palant }
97*65c59e02SInna Palant return res;
98*65c59e02SInna Palant }
99*65c59e02SInna Palant
allocateDirect(jint size)100*65c59e02SInna Palant local_ref<JByteBuffer> JByteBuffer::allocateDirect(jint size) {
101*65c59e02SInna Palant static auto cls = JByteBuffer::javaClassStatic();
102*65c59e02SInna Palant static auto meth = cls->getStaticMethod<JByteBuffer(int)>("allocateDirect");
103*65c59e02SInna Palant return meth(cls, size);
104*65c59e02SInna Palant }
105*65c59e02SInna Palant
order(alias_ref<JByteOrder> order)106*65c59e02SInna Palant local_ref<JByteBuffer> JByteBuffer::order(alias_ref<JByteOrder> order) {
107*65c59e02SInna Palant static auto meth =
108*65c59e02SInna Palant JByteBuffer::javaClassStatic()
109*65c59e02SInna Palant ->getMethod<local_ref<JByteBuffer>(alias_ref<JByteOrder>)>("order");
110*65c59e02SInna Palant return meth(self(), order);
111*65c59e02SInna Palant }
112*65c59e02SInna Palant
113*65c59e02SInna Palant } // namespace jni
114*65c59e02SInna Palant } // namespace facebook
115