C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
util.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "../abi/string.hpp"
26#include "../abi/vector.hpp"
27#include "../boolean.hpp"
28#include "../compat.hpp"
29#include "../functional.hpp"
30#include "../zstring_view.hpp"
31#include "common_types.hpp"
32#include "global_ref.hpp"
33#include "iterator.hpp"
34#include "local_ref.hpp"
35
36#include <concepts>
37#include <cstddef>
38#include <cstdint>
39#include <new>
40#include <ranges>
41#include <span>
42#include <string_view>
43#include <type_traits>
44#include <utility>
45
46#include <jni.h>
47
48namespace essence::jni {
49 using jobject_bit_transformer_type = std::function<local_ref(const std::byte* source)>;
50
51 template <typename T>
53
54 template <typename T>
56 std::ranges::contiguous_range<T> && std::convertible_to<std::ranges::range_value_t<T>, std::string_view>;
57
58 ES_API(JNISUPPORT) global_ref_ex<jclass> get_jstring_class();
59 ES_API(JNISUPPORT) global_ref_ex<jclass> get_exception_class();
60
61 ES_API(JNISUPPORT) abi::string from_string(jstring str);
62 ES_API(JNISUPPORT) abi::vector<jboolean> from_array(jbooleanArray array);
63 ES_API(JNISUPPORT) abi::vector<jbyte> from_array(jbyteArray array);
64 ES_API(JNISUPPORT) abi::vector<jshort> from_array(jshortArray array);
65 ES_API(JNISUPPORT) abi::vector<jint> from_array(jintArray array);
66 ES_API(JNISUPPORT) abi::vector<jlong> from_array(jlongArray array);
67 ES_API(JNISUPPORT) abi::vector<jchar> from_array(jcharArray array);
68 ES_API(JNISUPPORT) abi::vector<float> from_array(jfloatArray array);
69 ES_API(JNISUPPORT) abi::vector<double> from_array(jdoubleArray array);
70 ES_API(JNISUPPORT) abi::vector<local_ref> from_array(jobjectArray array);
71 ES_API(JNISUPPORT) abi::vector<abi::string> from_string_array(jobjectArray array);
72
73 template <std::invocable<const local_ref&> Transformer>
74 requires(!std::is_void_v<typename function_traits<Transformer>::return_type>)
75 auto from_array(jobjectArray array, Transformer&& transformer) {
76 using result_type = abi::vector<typename function_traits<Transformer>::return_type>;
77
78 if (convert_to_boolean(transformer)) {
79 jobject_array_proxy proxy{array};
80 auto intermediate = proxy | std::views::transform(std::forward<Transformer>(transformer));
81
82 return result_type{intermediate.begin(), intermediate.end()};
83 }
84
85 return result_type{};
86 }
87
88 ES_API(JNISUPPORT) jstring make_string(std::string_view str);
89 ES_API(JNISUPPORT) jbooleanArray make_array(std::span<const bool> buffer);
90 ES_API(JNISUPPORT) jbyteArray make_array(std::span<const std::byte> buffer);
91 ES_API(JNISUPPORT) jbyteArray make_array(std::span<const std::int8_t> buffer);
92 ES_API(JNISUPPORT) jshortArray make_array(std::span<const std::int16_t> buffer);
93 ES_API(JNISUPPORT) jintArray make_array(std::span<const std::int32_t> buffer);
94 ES_API(JNISUPPORT) jlongArray make_array(std::span<const std::int64_t> buffer);
95 ES_API(JNISUPPORT) jbyteArray make_array(std::span<const std::uint8_t> buffer);
96 ES_API(JNISUPPORT) jcharArray make_array(std::span<const std::uint16_t> buffer);
97 ES_API(JNISUPPORT) jfloatArray make_array(std::span<const float> buffer);
98 ES_API(JNISUPPORT) jdoubleArray make_array(std::span<const double> buffer);
99#ifdef _MSC_VER
100 ES_API(JNISUPPORT) jintArray make_array(std::span<const long> buffer);
101#endif
102 ES_API(JNISUPPORT)
103 jobjectArray make_array(jclass class_id, std::span<const std::byte> buffer, std::size_t unit_size,
104 const jobject_bit_transformer_type& transformer);
105 ES_API(JNISUPPORT)
106 jobject make_object_unsafe(jclass class_id, jmethodID ctor, ...);
107
108 template <std::ranges::contiguous_range Range, typename Transformer>
109 requires std::is_invocable_r_v<local_ref, Transformer, const std::ranges::range_reference_t<Range>>
110 jobjectArray make_array(jclass class_id, Range&& range, Transformer&& transformer) {
111 if (!convert_to_boolean(transformer)) {
112 return nullptr;
113 }
114
115 return make_array(class_id, std::as_bytes(std::span{range}), sizeof(std::ranges::range_value_t<Range>),
116 [&](const std::byte* source) {
117 return std::forward<Transformer>(transformer)(
118 *std::launder(reinterpret_cast<const std::ranges::range_value_t<Range>*>(source)));
119 });
120 }
121
122 template <jni_arg_with_scoped... Args>
123 jobject make_object(jclass class_id, jmethodID ctor, Args&&... args) {
124 static constexpr auto parse_arg = []<jni_arg_with_scoped T>(T&& arg) -> decltype(auto) {
125 if constexpr (local_ref_like<T>) {
126 return static_cast<const local_ref&>(std::forward<T>(arg)).get();
127 } else if constexpr (global_ref_like<T>) {
128 return static_cast<const global_ref&>(std::forward<T>(arg)).get();
129 } else {
130 return std::forward<T>(arg);
131 }
132 };
133
134 return make_object_unsafe(class_id, ctor, parse_arg(std::forward<Args>(args))...);
135 }
136
137 ES_API(JNISUPPORT) jint throw_exception(const std::exception& ex);
138 ES_API(JNISUPPORT) jint throw_exception(jclass exception_type, zstring_view message);
139
140 template <std::default_initializable T>
141 T throw_exception(jclass exception_type, zstring_view message, T value = {}) {
142 static_assert(sizeof(T) <= 32);
143 static_cast<void>(throw_exception(exception_type, message));
144
145 return std::move(value);
146 }
147
148 template <std::default_initializable T>
149 T throw_exception(const std::exception& ex, T value = {}) {
150 static_assert(sizeof(T) <= 32);
151 static_cast<void>(throw_exception(ex));
152
153 return std::move(value);
154 }
155} // namespace essence::jni
156
157namespace essence::jni::scoped {
158 ES_API(JNISUPPORT) local_ref_ex<jstring> make_string(std::string_view str);
159 ES_API(JNISUPPORT) local_ref_ex<jbooleanArray> make_array(std::span<const bool> buffer);
160 ES_API(JNISUPPORT) local_ref_ex<jbyteArray> make_array(std::span<const std::byte> buffer);
161 ES_API(JNISUPPORT) local_ref_ex<jbyteArray> make_array(std::span<const std::int8_t> buffer);
162 ES_API(JNISUPPORT) local_ref_ex<jshortArray> make_array(std::span<const std::int16_t> buffer);
163 ES_API(JNISUPPORT) local_ref_ex<jintArray> make_array(std::span<const std::int32_t> buffer);
164 ES_API(JNISUPPORT) local_ref_ex<jlongArray> make_array(std::span<const std::int64_t> buffer);
165 ES_API(JNISUPPORT) local_ref_ex<jbyteArray> make_array(std::span<const std::uint8_t> buffer);
166 ES_API(JNISUPPORT) local_ref_ex<jcharArray> make_array(std::span<const std::uint16_t> buffer);
167 ES_API(JNISUPPORT) local_ref_ex<jfloatArray> make_array(std::span<const float> buffer);
168 ES_API(JNISUPPORT) local_ref_ex<jdoubleArray> make_array(std::span<const double> buffer);
169#ifdef _MSC_VER
170 ES_API(JNISUPPORT) local_ref_ex<jintArray> make_array(std::span<const long> buffer);
171#endif
172 ES_API(JNISUPPORT)
173 local_ref_ex<jobjectArray> make_array(jclass class_id, std::span<const std::byte> buffer, std::size_t unit_size,
174 const jobject_bit_transformer_type& transformer);
175
176 template <std::ranges::contiguous_range Range, typename Transformer>
177 requires std::is_invocable_r_v<local_ref, Transformer, const std::ranges::range_reference_t<Range>>
178 local_ref_ex<jobjectArray> make_array(jclass class_id, Range&& range, Transformer&& transformer) {
179 return local_ref_ex<jobjectArray>{
180 jni::make_array(class_id, range, std::forward<Transformer>(transformer)), true};
181 }
182
183 template <jni_arg_with_scoped... Args>
184 local_ref make_object(jclass class_id, jmethodID ctor, Args&&... args) {
185 return local_ref{jni::make_object(class_id, ctor, std::forward<Args>(args)...), true};
186 }
187} // namespace essence::jni::scoped
188
189namespace essence::jni {
190 template <string_view_able_range Range>
191 jobjectArray make_array(Range&& range) {
192 return make_array(
193 get_jstring_class().get(), range, [](std::string_view inner) { return scoped::make_string(inner); });
194 }
195} // namespace essence::jni
196
197namespace essence::jni::scoped {
198 template <string_view_able_range Range>
199 local_ref_ex<jobjectArray> make_array(Range&& range) {
200 return local_ref_ex<jobjectArray>{jni::make_array(range), true};
201 }
202} // namespace essence::jni::scoped
Definition global_ref.hpp:54
Definition util.hpp:52
Definition common_types.hpp:53
Definition local_ref.hpp:54