xref: /aosp_15_r20/external/fbjni/cxx/fbjni/ByteBuffer.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
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 
17 #include <fbjni/ByteBuffer.h>
18 
19 #include <stdexcept>
20 
21 namespace facebook {
22 namespace jni {
23 
rewind() const24 void JBuffer::rewind() const {
25   static auto meth =
26       javaClassStatic()->getMethod<alias_ref<JBuffer>()>("rewind");
27   meth(self());
28 }
29 
getDirectAddress() const30 void* JBuffer::getDirectAddress() const {
31   if (!self()) {
32     throwNewJavaException(
33         "java/lang/NullPointerException", "java.lang.NullPointerException");
34   }
35   void* addr = Environment::current()->GetDirectBufferAddress(self());
36   FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
37   if (!addr) {
38     throw std::runtime_error(
39         isDirect() ? "Attempt to get direct bytes of non-direct buffer."
40                    : "Error getting direct bytes of buffer.");
41   }
42   return addr;
43 }
44 
getDirectCapacity() const45 size_t JBuffer::getDirectCapacity() const {
46   if (!self()) {
47     throwNewJavaException(
48         "java/lang/NullPointerException", "java.lang.NullPointerException");
49   }
50   int size = Environment::current()->GetDirectBufferCapacity(self());
51   FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
52   if (size < 0) {
53     throw std::runtime_error(
54         isDirect() ? "Attempt to get direct size of non-direct buffer."
55                    : "Error getting direct size of buffer.");
56   }
57   return static_cast<size_t>(size);
58 }
59 
isDirect() const60 bool JBuffer::isDirect() const {
61   static auto meth = javaClassStatic()->getMethod<jboolean()>("isDirect");
62   return meth(self());
63 }
64 
nativeOrder()65 local_ref<JByteOrder> JByteOrder::nativeOrder() {
66   static auto meth =
67       JByteOrder::javaClassStatic()->getStaticMethod<local_ref<JByteOrder>()>(
68           "nativeOrder");
69   return meth(JByteOrder::javaClassStatic());
70 }
71 
bigEndian()72 local_ref<JByteOrder> JByteOrder::bigEndian() {
73   static auto field =
74       JByteOrder::javaClassStatic()->getStaticField<JByteOrder>("BIG_ENDIAN");
75   return JByteOrder::javaClassStatic()->getStaticFieldValue(field);
76 }
77 
littleEndian()78 local_ref<JByteOrder> JByteOrder::littleEndian() {
79   static auto field = JByteOrder::javaClassStatic()->getStaticField<JByteOrder>(
80       "LITTLE_ENDIAN");
81   return JByteOrder::javaClassStatic()->getStaticFieldValue(field);
82 }
83 
wrapBytes(uint8_t * data,size_t size)84 local_ref<JByteBuffer> JByteBuffer::wrapBytes(uint8_t* data, size_t size) {
85   // env->NewDirectByteBuffer requires that size is positive. Android's
86   // dalvik returns an invalid result and Android's art aborts if size == 0.
87   // Workaround this by using a slow path through Java in that case.
88   if (!size) {
89     return allocateDirect(0);
90   }
91   auto res = adopt_local(static_cast<javaobject>(
92       Environment::current()->NewDirectByteBuffer(data, size)));
93   FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
94   if (!res) {
95     throw std::runtime_error("Direct byte buffers are unsupported.");
96   }
97   return res;
98 }
99 
allocateDirect(jint size)100 local_ref<JByteBuffer> JByteBuffer::allocateDirect(jint size) {
101   static auto cls = JByteBuffer::javaClassStatic();
102   static auto meth = cls->getStaticMethod<JByteBuffer(int)>("allocateDirect");
103   return meth(cls, size);
104 }
105 
order(alias_ref<JByteOrder> order)106 local_ref<JByteBuffer> JByteBuffer::order(alias_ref<JByteOrder> order) {
107   static auto meth =
108       JByteBuffer::javaClassStatic()
109           ->getMethod<local_ref<JByteBuffer>(alias_ref<JByteOrder>)>("order");
110   return meth(self(), order);
111 }
112 
113 } // namespace jni
114 } // namespace facebook
115