1 /* Domain-independent part of the Java interface: inline functions.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_ppl_java_common_inlines_hh
25 #define PPL_ppl_java_common_inlines_hh 1
26 
27 #include <cassert>
28 
29 namespace Parma_Polyhedra_Library {
30 
31 namespace Interfaces {
32 
33 namespace Java {
34 
35 template <typename U, typename V>
36 U
37 jtype_to_unsigned(const V& value) {
38   if (value < 0)
39     throw std::invalid_argument("not an unsigned integer.");
40 
41   if (sizeof(U) < sizeof(V)) {
42     if (value > static_cast<V>(std::numeric_limits<U>::max()))
43       throw std::invalid_argument("unsigned integer out of range.");
44   }
45 
46   return value;
47 }
48 
49 template <typename T>
50 inline void
set_ptr(JNIEnv * env,jobject ppl_object,const T * address,bool to_be_marked)51 set_ptr(JNIEnv* env, jobject ppl_object,
52         const T* address, bool to_be_marked) {
53   const T* ptr = (to_be_marked ? mark(address) : address);
54   jlong pointer_value = reinterpret_cast<jlong>(ptr);
55   assert(reinterpret_cast<const T*>(pointer_value) == ptr);
56   env->SetLongField(ppl_object, cached_FMIDs.PPL_Object_ptr_ID, pointer_value);
57 }
58 
59 inline void*
get_ptr(JNIEnv * env,jobject ppl_object)60 get_ptr(JNIEnv* env, jobject ppl_object) {
61   jlong pointer_value
62     = env->GetLongField(ppl_object, cached_FMIDs.PPL_Object_ptr_ID);
63   void* ptr = reinterpret_cast<void*>(pointer_value);
64   assert(reinterpret_cast<jlong>(ptr) == pointer_value);
65   return unmark(ptr);
66 }
67 
68 inline bool
is_java_marked(JNIEnv * env,jobject ppl_object)69 is_java_marked(JNIEnv* env, jobject ppl_object) {
70   jlong pointer_value
71     = env->GetLongField(ppl_object, cached_FMIDs.PPL_Object_ptr_ID);
72   const void* ptr = reinterpret_cast<const void*>(pointer_value);
73   assert(reinterpret_cast<jlong>(ptr) == pointer_value);
74   return marked(ptr);
75 }
76 
77 inline void
set_coefficient(JNIEnv * env,jobject dst,jobject src)78 set_coefficient(JNIEnv* env, jobject dst, jobject src) {
79   jobject src_bi
80     = env->GetObjectField(src, cached_FMIDs.Coefficient_value_ID);
81   env->SetObjectField(dst, cached_FMIDs.Coefficient_value_ID, src_bi);
82 }
83 
84 inline void
set_by_reference(JNIEnv * env,jobject by_ref_dst,jobject src)85 set_by_reference(JNIEnv* env, jobject by_ref_dst, jobject src) {
86   env->SetObjectField(by_ref_dst,
87                       cached_FMIDs.By_Reference_obj_ID,
88                       src);
89 }
90 
91 inline jobject
get_by_reference(JNIEnv * env,jobject by_reference)92 get_by_reference(JNIEnv* env, jobject by_reference) {
93   return env->GetObjectField(by_reference, cached_FMIDs.By_Reference_obj_ID);
94 }
95 
96 template <typename R>
97 jobject
build_linear_expression(JNIEnv * env,const R & r)98 build_linear_expression(JNIEnv* env, const R& r) {
99   jobject j_ret;
100   PPL_DIRTY_TEMP_COEFFICIENT(coefficient);
101   dimension_type varid = 0;
102   dimension_type space_dimension = r.space_dimension();
103   while (varid < space_dimension
104          && (coefficient = r.coefficient(Variable(varid))) == 0)
105     ++varid;
106   if (varid >= space_dimension) {
107     jobject j_coefficient_zero = build_java_coeff(env, Coefficient(0));
108     j_ret = env->NewObject(cached_classes.Linear_Expression_Coefficient,
109                            cached_FMIDs.Linear_Expression_Coefficient_init_ID,
110                            j_coefficient_zero);
111     CHECK_RESULT_THROW(env, j_ret);
112   }
113   else {
114     jmethodID coeff_var_init_ID
115       = cached_FMIDs.Linear_Expression_Times_init_from_coeff_var_ID;
116     jobject j_coefficient = build_java_coeff(env, coefficient);
117     jobject j_variable = build_java_variable(env, Variable(varid));
118     jclass j_le_times_class = cached_classes.Linear_Expression_Times;
119     jobject j_coeff_var = env->NewObject(j_le_times_class,
120                                          coeff_var_init_ID,
121                                          j_coefficient, j_variable);
122     CHECK_EXCEPTION_THROW(env);
123     j_ret = j_coeff_var;
124     while (true) {
125       ++varid;
126       while (varid < space_dimension
127              && (coefficient = r.coefficient(Variable(varid))) == 0)
128         ++varid;
129       if (varid >= space_dimension)
130         break;
131       else {
132         j_coefficient = build_java_coeff(env, coefficient);
133         j_variable = build_java_variable(env, Variable(varid));
134         j_coeff_var = env->NewObject(j_le_times_class,
135                                      coeff_var_init_ID,
136                                      j_coefficient, j_variable);
137         CHECK_EXCEPTION_THROW(env);
138         j_ret = env->CallObjectMethod(j_ret,
139                                       cached_FMIDs.Linear_Expression_sum_ID,
140                                       j_coeff_var);
141         CHECK_EXCEPTION_THROW(env);
142       }
143     }
144   }
145   return j_ret;
146 }
147 
148 inline Variable
build_cxx_variable(JNIEnv * env,jobject j_var)149 build_cxx_variable(JNIEnv* env, jobject j_var) {
150   return Variable(env->GetIntField(j_var, cached_FMIDs.Variable_varid_ID));
151 }
152 
153 inline jobject
build_java_variable(JNIEnv * env,const Variable var)154 build_java_variable(JNIEnv* env, const Variable var) {
155   jlong j_var_id = var.id();
156   jobject ret = env->NewObject(cached_classes.Variable,
157                                cached_FMIDs.Variable_init_ID,
158                                j_var_id);
159   CHECK_RESULT_THROW(env, ret);
160   return ret;
161 }
162 
163 inline Coefficient
build_cxx_coeff(JNIEnv * env,jobject j_coeff)164 build_cxx_coeff(JNIEnv* env, jobject j_coeff) {
165   jstring bi_string
166     = (jstring) env->CallObjectMethod(j_coeff,
167                                       cached_FMIDs.Coefficient_toString_ID);
168   CHECK_EXCEPTION_THROW(env);
169   const char *nativeString = env->GetStringUTFChars(bi_string, 0);
170   CHECK_RESULT_THROW(env, nativeString);
171   PPL_DIRTY_TEMP_COEFFICIENT(ppl_coeff);
172   ppl_coeff = Coefficient(nativeString);
173   env->ReleaseStringUTFChars(bi_string, nativeString);
174   return ppl_coeff;
175 }
176 
177 inline jobject
build_java_coeff(JNIEnv * env,const Coefficient & ppl_coeff)178 build_java_coeff(JNIEnv* env, const Coefficient& ppl_coeff) {
179   std::ostringstream s;
180   s << ppl_coeff;
181   std::string str = s.str();
182   jstring coeff_string = env->NewStringUTF(str.c_str());
183   CHECK_RESULT_THROW(env, coeff_string);
184   jobject ret = env->NewObject(cached_classes.Coefficient,
185                                cached_FMIDs.Coefficient_init_from_String_ID,
186                                coeff_string);
187   CHECK_RESULT_THROW(env, ret);
188   return ret;
189 }
190 
191 template <typename System, typename Elem_Builder>
192 System
193 build_cxx_system(JNIEnv* env, jobject j_iterable, Elem_Builder build_cxx_elem) {
194   // Get the iterator.
195   jobject j_iter
196     = env->CallObjectMethod(j_iterable, cached_FMIDs.System_iterator_ID);
197   CHECK_EXCEPTION_THROW(env);
198   // Get the iterator method IDs.
199   jmethodID has_next_mID = cached_FMIDs.System_Iterator_has_next_ID;
200   jmethodID next_mID = cached_FMIDs.System_Iterator_next_ID;
201   // Initialize an empty system.
202   System cxx_sys;
203   jobject j_element;
204   jboolean has_next_value = env->CallBooleanMethod(j_iter, has_next_mID);
205   CHECK_EXCEPTION_ASSERT(env);
206   while (has_next_value) {
207     j_element = env->CallObjectMethod(j_iter, next_mID);
208     CHECK_EXCEPTION_ASSERT(env);
209     cxx_sys.insert(build_cxx_elem(env, j_element));
210     has_next_value = env->CallBooleanMethod(j_iter, has_next_mID);
211     CHECK_EXCEPTION_ASSERT(env);
212   }
213   return cxx_sys;
214 }
215 
216 inline Congruence_System
build_cxx_congruence_system(JNIEnv * env,jobject j_iterable)217 build_cxx_congruence_system(JNIEnv* env, jobject j_iterable) {
218   return
219     build_cxx_system<Congruence_System>(env, j_iterable, build_cxx_congruence);
220 }
221 
222 inline Constraint_System
build_cxx_constraint_system(JNIEnv * env,jobject j_iterable)223 build_cxx_constraint_system(JNIEnv* env, jobject j_iterable) {
224   return
225     build_cxx_system<Constraint_System>(env, j_iterable, build_cxx_constraint);
226 }
227 
228 inline Generator_System
build_cxx_generator_system(JNIEnv * env,jobject j_iterable)229 build_cxx_generator_system(JNIEnv* env, jobject j_iterable) {
230   return
231     build_cxx_system<Generator_System>(env, j_iterable, build_cxx_generator);
232 }
233 
234 inline Grid_Generator_System
build_cxx_grid_generator_system(JNIEnv * env,jobject j_iterable)235 build_cxx_grid_generator_system(JNIEnv* env, jobject j_iterable) {
236   return build_cxx_system<Grid_Generator_System> (env, j_iterable,
237                                                   build_cxx_grid_generator);
238 }
239 
240 } // namespace Java
241 
242 } // namespace Interfaces
243 
244 } // namespace Parma_Polyhedra_Library
245 
246 #endif // !defined(PPL_ppl_java_common_inlines_hh)
247