WPILibC++  2018.4.1-20180729040223-1137-g011f0ff
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
jni_util.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #ifndef WPIUTIL_WPI_JNI_UTIL_H_
9 #define WPIUTIL_WPI_JNI_UTIL_H_
10 
11 #include <jni.h>
12 
13 #include <queue>
14 #include <string>
15 #include <type_traits>
16 #include <utility>
17 #include <vector>
18 
19 #include "wpi/ArrayRef.h"
20 #include "wpi/ConvertUTF.h"
21 #include "wpi/SafeThread.h"
22 #include "wpi/SmallString.h"
23 #include "wpi/SmallVector.h"
24 #include "wpi/StringRef.h"
25 #include "wpi/deprecated.h"
26 #include "wpi/mutex.h"
27 #include "wpi/raw_ostream.h"
28 
29 namespace wpi {
30 namespace java {
31 
32 // Gets a Java stack trace. Also provides the last function
33 // in the stack trace not starting with excludeFuncPrefix (useful for e.g.
34 // finding the first user call to a series of library functions).
35 std::string GetJavaStackTrace(JNIEnv* env, std::string* func = nullptr,
36  StringRef excludeFuncPrefix = StringRef());
37 
38 // Shim for backwards compatibility
39 template <const char* excludeFuncPrefix>
40 WPI_DEPRECATED("use StringRef function instead")
41 std::string GetJavaStackTrace(JNIEnv* env, std::string* func) {
42  return GetJavaStackTrace(
43  env, func,
44  excludeFuncPrefix == nullptr ? StringRef() : excludeFuncPrefix);
45 }
46 
47 // Finds a class and keep it as a global reference.
48 // Use with caution, as the destructor does NOT call DeleteGlobalRef due
49 // to potential shutdown issues with doing so.
50 class JClass {
51  public:
52  JClass() = default;
53 
54  JClass(JNIEnv* env, const char* name) {
55  jclass local = env->FindClass(name);
56  if (!local) return;
57  m_cls = static_cast<jclass>(env->NewGlobalRef(local));
58  env->DeleteLocalRef(local);
59  }
60 
61  void free(JNIEnv* env) {
62  if (m_cls) env->DeleteGlobalRef(m_cls);
63  m_cls = nullptr;
64  }
65 
66  explicit operator bool() const { return m_cls; }
67 
68  operator jclass() const { return m_cls; }
69 
70  protected:
71  jclass m_cls = nullptr;
72 };
73 
74 struct JClassInit {
75  const char* name;
76  JClass* cls;
77 };
78 
79 template <typename T>
80 class JGlobal {
81  public:
82  JGlobal() = default;
83 
84  JGlobal(JNIEnv* env, T obj) {
85  m_cls = static_cast<T>(env->NewGlobalRef(obj));
86  }
87 
88  void free(JNIEnv* env) {
89  if (m_cls) env->DeleteGlobalRef(m_cls);
90  m_cls = nullptr;
91  }
92 
93  explicit operator bool() const { return m_cls; }
94 
95  operator T() const { return m_cls; }
96 
97  protected:
98  T m_cls = nullptr;
99 };
100 
101 // Container class for cleaning up Java local references.
102 // The destructor calls DeleteLocalRef.
103 template <typename T>
104 class JLocal {
105  public:
106  JLocal(JNIEnv* env, T obj) : m_env(env), m_obj(obj) {}
107  JLocal(const JLocal&) = delete;
108  JLocal(JLocal&& oth) : m_env(oth.m_env), m_obj(oth.m_obj) {
109  oth.m_obj = nullptr;
110  }
111  JLocal& operator=(const JLocal&) = delete;
112  JLocal& operator=(JLocal&& oth) {
113  m_env = oth.m_env;
114  m_obj = oth.m_obj;
115  oth.m_obj = nullptr;
116  return *this;
117  }
118  ~JLocal() {
119  if (m_obj) m_env->DeleteLocalRef(m_obj);
120  }
121  operator T() { return m_obj; }
122  T obj() { return m_obj; }
123 
124  private:
125  JNIEnv* m_env;
126  T m_obj;
127 };
128 
129 //
130 // Conversions from Java objects to C++
131 //
132 
133 // Java string (jstring) reference. The string is provided as UTF8.
134 // This is not actually a reference, as it makes a copy of the string
135 // characters, but it's named this way for consistency.
136 class JStringRef {
137  public:
138  JStringRef(JNIEnv* env, jstring str) {
139  if (str) {
140  jsize size = env->GetStringLength(str);
141  const jchar* chars = env->GetStringCritical(str, nullptr);
142  if (chars) {
143  convertUTF16ToUTF8String(makeArrayRef(chars, size), m_str);
144  env->ReleaseStringCritical(str, chars);
145  }
146  } else {
147  errs() << "JStringRef was passed a null pointer at \n"
148  << GetJavaStackTrace(env);
149  }
150  // Ensure str is null-terminated.
151  m_str.push_back('\0');
152  m_str.pop_back();
153  }
154 
155  operator StringRef() const { return m_str; }
156  StringRef str() const { return m_str; }
157  const char* c_str() const { return m_str.data(); }
158  size_t size() const { return m_str.size(); }
159 
160  private:
161  SmallString<128> m_str;
162 };
163 
164 // Details for J*ArrayRef and CriticalJ*ArrayRef
165 namespace detail {
166 
167 template <typename C, typename T>
168 class JArrayRefInner {};
169 
170 // Specialization of JArrayRefBase to provide StringRef conversion.
171 template <typename C>
172 class JArrayRefInner<C, jbyte> {
173  public:
174  operator StringRef() const { return str(); }
175 
176  StringRef str() const {
177  auto arr = static_cast<const C*>(this)->array();
178  if (arr.empty()) return StringRef{};
179  return StringRef{reinterpret_cast<const char*>(arr.data()), arr.size()};
180  }
181 };
182 
183 // Base class for J*ArrayRef and CriticalJ*ArrayRef
184 template <typename T>
185 class JArrayRefBase : public JArrayRefInner<JArrayRefBase<T>, T> {
186  public:
187  explicit operator bool() const { return this->m_elements != nullptr; }
188 
189  operator ArrayRef<T>() const { return array(); }
190 
191  ArrayRef<T> array() const {
192  if (!this->m_elements) return ArrayRef<T>{};
193  return ArrayRef<T>{this->m_elements, this->m_size};
194  }
195 
196  JArrayRefBase(const JArrayRefBase&) = delete;
197  JArrayRefBase& operator=(const JArrayRefBase&) = delete;
198 
200  : m_env(oth.m_env),
201  m_jarr(oth.m_jarr),
202  m_size(oth.m_size),
203  m_elements(oth.m_elements) {
204  oth.m_jarr = nullptr;
205  oth.m_elements = nullptr;
206  }
207 
208  JArrayRefBase& operator=(JArrayRefBase&& oth) {
209  this->m_env = oth.m_env;
210  this->m_jarr = oth.m_jarr;
211  this->m_size = oth.m_size;
212  this->m_elements = oth.m_elements;
213  oth.m_jarr = nullptr;
214  oth.m_elements = nullptr;
215  return *this;
216  }
217 
218  protected:
219  JArrayRefBase(JNIEnv* env, T* elements, size_t size) {
220  this->m_env = env;
221  this->m_jarr = nullptr;
222  this->m_size = size;
223  this->m_elements = elements;
224  }
225 
226  JArrayRefBase(JNIEnv* env, jarray jarr, size_t size) {
227  this->m_env = env;
228  this->m_jarr = jarr;
229  this->m_size = size;
230  this->m_elements = nullptr;
231  }
232 
233  JArrayRefBase(JNIEnv* env, jarray jarr)
234  : JArrayRefBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
235 
236  JNIEnv* m_env;
237  jarray m_jarr = nullptr;
238  size_t m_size;
239  T* m_elements;
240 };
241 
242 } // namespace detail
243 
244 // Java array / DirectBuffer reference.
245 
246 #define WPI_JNI_JARRAYREF(T, F) \
247  class J##F##ArrayRef : public detail::JArrayRefBase<T> { \
248  public: \
249  J##F##ArrayRef(JNIEnv* env, jobject bb, int len) \
250  : detail::JArrayRefBase<T>( \
251  env, \
252  static_cast<T*>(bb ? env->GetDirectBufferAddress(bb) : nullptr), \
253  len) { \
254  if (!bb) \
255  errs() << "JArrayRef was passed a null pointer at \n" \
256  << GetJavaStackTrace(env); \
257  } \
258  J##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
259  : detail::JArrayRefBase<T>(env, jarr, len) { \
260  if (jarr) \
261  m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
262  else \
263  errs() << "JArrayRef was passed a null pointer at \n" \
264  << GetJavaStackTrace(env); \
265  } \
266  J##F##ArrayRef(JNIEnv* env, T##Array jarr) \
267  : detail::JArrayRefBase<T>(env, jarr) { \
268  if (jarr) \
269  m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
270  else \
271  errs() << "JArrayRef was passed a null pointer at \n" \
272  << GetJavaStackTrace(env); \
273  } \
274  ~J##F##ArrayRef() { \
275  if (m_jarr && m_elements) \
276  m_env->Release##F##ArrayElements(static_cast<T##Array>(m_jarr), \
277  m_elements, JNI_ABORT); \
278  } \
279  }; \
280  \
281  class CriticalJ##F##ArrayRef : public detail::JArrayRefBase<T> { \
282  public: \
283  CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
284  : detail::JArrayRefBase<T>(env, jarr, len) { \
285  if (jarr) \
286  m_elements = \
287  static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
288  else \
289  errs() << "JArrayRef was passed a null pointer at \n" \
290  << GetJavaStackTrace(env); \
291  } \
292  CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr) \
293  : detail::JArrayRefBase<T>(env, jarr) { \
294  if (jarr) \
295  m_elements = \
296  static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
297  else \
298  errs() << "JArrayRef was passed a null pointer at \n" \
299  << GetJavaStackTrace(env); \
300  } \
301  ~CriticalJ##F##ArrayRef() { \
302  if (m_jarr && m_elements) \
303  m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, JNI_ABORT); \
304  } \
305  };
306 
307 WPI_JNI_JARRAYREF(jboolean, Boolean)
308 WPI_JNI_JARRAYREF(jbyte, Byte)
309 WPI_JNI_JARRAYREF(jshort, Short)
310 WPI_JNI_JARRAYREF(jint, Int)
311 WPI_JNI_JARRAYREF(jlong, Long)
312 WPI_JNI_JARRAYREF(jfloat, Float)
313 WPI_JNI_JARRAYREF(jdouble, Double)
314 
315 #undef WPI_JNI_JARRAYREF
316 
317 //
318 // Conversions from C++ to Java objects
319 //
320 
321 // Convert a UTF8 string into a jstring.
322 inline jstring MakeJString(JNIEnv* env, StringRef str) {
324  convertUTF8ToUTF16String(str, chars);
325  return env->NewString(chars.begin(), chars.size());
326 }
327 
328 // details for MakeJIntArray
329 namespace detail {
330 
331 // Slow path (get primitive array and set individual elements). This
332 // is used if the input type is not an integer of the same size (note
333 // signed/unsigned is ignored).
334 template <typename T,
335  bool = (std::is_integral<T>::value && sizeof(jint) == sizeof(T))>
337  static jintArray ToJava(JNIEnv* env, ArrayRef<T> arr) {
338  jintArray jarr = env->NewIntArray(arr.size());
339  if (!jarr) return nullptr;
340  jint* elements =
341  static_cast<jint*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
342  if (!elements) return nullptr;
343  for (size_t i = 0; i < arr.size(); ++i)
344  elements[i] = static_cast<jint>(arr[i]);
345  env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
346  return jarr;
347  }
348 };
349 
350 // Fast path (use SetIntArrayRegion)
351 template <typename T>
353  static jintArray ToJava(JNIEnv* env, ArrayRef<T> arr) {
354  jintArray jarr = env->NewIntArray(arr.size());
355  if (!jarr) return nullptr;
356  env->SetIntArrayRegion(jarr, 0, arr.size(),
357  reinterpret_cast<const jint*>(arr.data()));
358  return jarr;
359  }
360 };
361 
362 } // namespace detail
363 
364 // Convert an ArrayRef to a jintArray.
365 template <typename T>
366 inline jintArray MakeJIntArray(JNIEnv* env, ArrayRef<T> arr) {
367  return detail::ConvertIntArray<T>::ToJava(env, arr);
368 }
369 
370 // Convert a SmallVector to a jintArray. This is required in addition to
371 // ArrayRef because template resolution occurs prior to implicit conversions.
372 template <typename T>
373 inline jintArray MakeJIntArray(JNIEnv* env, const SmallVectorImpl<T>& arr) {
374  return detail::ConvertIntArray<T>::ToJava(env, arr);
375 }
376 
377 // Convert a std::vector to a jintArray. This is required in addition to
378 // ArrayRef because template resolution occurs prior to implicit conversions.
379 template <typename T>
380 inline jintArray MakeJIntArray(JNIEnv* env, const std::vector<T>& arr) {
381  return detail::ConvertIntArray<T>::ToJava(env, arr);
382 }
383 
384 // Convert a StringRef into a jbyteArray.
385 inline jbyteArray MakeJByteArray(JNIEnv* env, StringRef str) {
386  jbyteArray jarr = env->NewByteArray(str.size());
387  if (!jarr) return nullptr;
388  env->SetByteArrayRegion(jarr, 0, str.size(),
389  reinterpret_cast<const jbyte*>(str.data()));
390  return jarr;
391 }
392 
393 // Convert an array of integers into a jbooleanArray.
394 inline jbooleanArray MakeJBooleanArray(JNIEnv* env, ArrayRef<int> arr) {
395  jbooleanArray jarr = env->NewBooleanArray(arr.size());
396  if (!jarr) return nullptr;
397  jboolean* elements =
398  static_cast<jboolean*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
399  if (!elements) return nullptr;
400  for (size_t i = 0; i < arr.size(); ++i)
401  elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
402  env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
403  return jarr;
404 }
405 
406 // Convert an array of booleans into a jbooleanArray.
407 inline jbooleanArray MakeJBooleanArray(JNIEnv* env, ArrayRef<bool> arr) {
408  jbooleanArray jarr = env->NewBooleanArray(arr.size());
409  if (!jarr) return nullptr;
410  jboolean* elements =
411  static_cast<jboolean*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
412  if (!elements) return nullptr;
413  for (size_t i = 0; i < arr.size(); ++i)
414  elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
415  env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
416  return jarr;
417 }
418 
419  // Other MakeJ*Array conversions.
420 
421 #define WPI_JNI_MAKEJARRAY(T, F) \
422  inline T##Array MakeJ##F##Array(JNIEnv* env, ArrayRef<T> arr) { \
423  T##Array jarr = env->New##F##Array(arr.size()); \
424  if (!jarr) return nullptr; \
425  env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data()); \
426  return jarr; \
427  }
428 
429 WPI_JNI_MAKEJARRAY(jboolean, Boolean)
430 WPI_JNI_MAKEJARRAY(jbyte, Byte)
431 WPI_JNI_MAKEJARRAY(jshort, Short)
432 WPI_JNI_MAKEJARRAY(jlong, Long)
433 WPI_JNI_MAKEJARRAY(jfloat, Float)
434 WPI_JNI_MAKEJARRAY(jdouble, Double)
435 
436 #undef WPI_JNI_MAKEJARRAY
437 
438 // Convert an array of std::string into a jarray of jstring.
439 inline jobjectArray MakeJStringArray(JNIEnv* env, ArrayRef<std::string> arr) {
440  static JClass stringCls{env, "java/lang/String"};
441  if (!stringCls) return nullptr;
442  jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls, nullptr);
443  if (!jarr) return nullptr;
444  for (size_t i = 0; i < arr.size(); ++i) {
445  JLocal<jstring> elem{env, MakeJString(env, arr[i])};
446  env->SetObjectArrayElement(jarr, i, elem.obj());
447  }
448  return jarr;
449 }
450 
451 // Generic callback thread implementation.
452 //
453 // JNI's AttachCurrentThread() creates a Java Thread object on every
454 // invocation, which is both time inefficient and causes issues with Eclipse
455 // (which tries to keep a thread list up-to-date and thus gets swamped).
456 //
457 // Instead, this class attaches just once. When a hardware notification
458 // occurs, a condition variable wakes up this thread and this thread actually
459 // makes the call into Java.
460 //
461 // The template parameter T is the message being passed to the callback, but
462 // also needs to provide the following functions:
463 // static JavaVM* GetJVM();
464 // static const char* GetName();
465 // void CallJava(JNIEnv *env, jobject func, jmethodID mid);
466 template <typename T>
467 class JCallbackThread : public SafeThread {
468  public:
469  void Main();
470 
471  std::queue<T> m_queue;
472  jobject m_func = nullptr;
473  jmethodID m_mid;
474 };
475 
476 template <typename T>
478  public:
479  void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
480 
481  template <typename... Args>
482  void Send(Args&&... args);
483 };
484 
485 template <typename T>
486 void JCallbackManager<T>::SetFunc(JNIEnv* env, jobject func, jmethodID mid) {
487  auto thr = this->GetThread();
488  if (!thr) return;
489  // free global reference
490  if (thr->m_func) env->DeleteGlobalRef(thr->m_func);
491  // create global reference
492  thr->m_func = env->NewGlobalRef(func);
493  thr->m_mid = mid;
494 }
495 
496 template <typename T>
497 template <typename... Args>
498 void JCallbackManager<T>::Send(Args&&... args) {
499  auto thr = this->GetThread();
500  if (!thr) return;
501  thr->m_queue.emplace(std::forward<Args>(args)...);
502  thr->m_cond.notify_one();
503 }
504 
505 template <typename T>
506 void JCallbackThread<T>::Main() {
507  JNIEnv* env;
508  JavaVMAttachArgs args;
509  args.version = JNI_VERSION_1_2;
510  args.name = const_cast<char*>(T::GetName());
511  args.group = nullptr;
512  jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
513  reinterpret_cast<void**>(&env), &args);
514  if (rs != JNI_OK) return;
515 
516  std::unique_lock<wpi::mutex> lock(m_mutex);
517  while (m_active) {
518  m_cond.wait(lock, [&] { return !(m_active && m_queue.empty()); });
519  if (!m_active) break;
520  while (!m_queue.empty()) {
521  if (!m_active) break;
522  auto item = std::move(m_queue.front());
523  m_queue.pop();
524  auto func = m_func;
525  auto mid = m_mid;
526  lock.unlock(); // don't hold mutex during callback execution
527  item.CallJava(env, func, mid);
528  if (env->ExceptionCheck()) {
529  env->ExceptionDescribe();
530  env->ExceptionClear();
531  }
532  lock.lock();
533  }
534  }
535 
536  JavaVM* jvm = T::GetJVM();
537  if (jvm) jvm->DetachCurrentThread();
538 }
539 
540 template <typename T>
542  public:
543  static JSingletonCallbackManager<T>& GetInstance() {
544  static JSingletonCallbackManager<T> instance;
545  return instance;
546  }
547 };
548 
549 inline std::string GetJavaStackTrace(JNIEnv* env, std::string* func,
550  StringRef excludeFuncPrefix) {
551  // create a throwable
552  static JClass throwableCls(env, "java/lang/Throwable");
553  if (!throwableCls) return "";
554  static jmethodID constructorId = nullptr;
555  if (!constructorId)
556  constructorId = env->GetMethodID(throwableCls, "<init>", "()V");
557  JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
558 
559  // retrieve information from the exception.
560  // get method id
561  // getStackTrace returns an array of StackTraceElement
562  static jmethodID getStackTraceId = nullptr;
563  if (!getStackTraceId)
564  getStackTraceId = env->GetMethodID(throwableCls, "getStackTrace",
565  "()[Ljava/lang/StackTraceElement;");
566 
567  // call getStackTrace
568  JLocal<jobjectArray> stackTrace(
569  env, static_cast<jobjectArray>(
570  env->CallObjectMethod(throwable, getStackTraceId)));
571 
572  if (!stackTrace) return "";
573 
574  // get length of the array
575  jsize stackTraceLength = env->GetArrayLength(stackTrace);
576 
577  // get toString methodId of StackTraceElement class
578  static JClass stackTraceElementCls(env, "java/lang/StackTraceElement");
579  if (!stackTraceElementCls) return "";
580  static jmethodID toStringId = nullptr;
581  if (!toStringId)
582  toStringId = env->GetMethodID(stackTraceElementCls, "toString",
583  "()Ljava/lang/String;");
584 
585  bool haveLoc = false;
586  std::string buf;
587  raw_string_ostream oss(buf);
588  for (jsize i = 0; i < stackTraceLength; i++) {
589  // add the result of toString method of each element in the result
590  JLocal<jobject> curStackTraceElement(
591  env, env->GetObjectArrayElement(stackTrace, i));
592 
593  // call to string on the object
594  JLocal<jstring> stackElementString(
595  env, static_cast<jstring>(
596  env->CallObjectMethod(curStackTraceElement, toStringId)));
597 
598  if (!stackElementString) return "";
599 
600  // add a line to res
601  JStringRef elem(env, stackElementString);
602  oss << elem << '\n';
603 
604  if (func) {
605  // func is caller of immediate caller (if there was one)
606  // or, if we see it, the first user function
607  if (i == 1) {
608  *func = elem.str();
609  } else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
610  !elem.str().startswith(excludeFuncPrefix)) {
611  *func = elem.str();
612  haveLoc = true;
613  }
614  }
615  }
616 
617  return oss.str();
618 }
619 
620 // Finds an exception class and keep it as a global reference.
621 // Similar to JClass, but provides Throw methods.
622 // Use with caution, as the destructor does NOT call DeleteGlobalRef due
623 // to potential shutdown issues with doing so.
624 class JException : public JClass {
625  public:
626  JException() = default;
627  JException(JNIEnv* env, const char* name) : JClass(env, name) {
628  if (m_cls)
629  m_constructor =
630  env->GetMethodID(m_cls, "<init>", "(Ljava/lang/String;)V");
631  }
632 
633  void Throw(JNIEnv* env, jstring msg) {
634  jobject exception = env->NewObject(m_cls, m_constructor, msg);
635  env->Throw(static_cast<jthrowable>(exception));
636  }
637 
638  void Throw(JNIEnv* env, StringRef msg) { Throw(env, MakeJString(env, msg)); }
639 
640  explicit operator bool() const { return m_constructor; }
641 
642  private:
643  jmethodID m_constructor = nullptr;
644 };
645 
647  const char* name;
648  JException* cls;
649 };
650 
651 } // namespace java
652 } // namespace wpi
653 
654 #endif // WPIUTIL_WPI_JNI_UTIL_H_
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: hostname.h:17
Definition: SafeThread.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:868
Definition: jni_util.h:185
Definition: jni_util.h:646
Definition: jni_util.h:168
Definition: jni_util.h:50
Definition: SmallVector.h:946
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:41
Definition: SafeThread.h:120
namespace to hold default to_json function
Definition: SmallString.h:21
Definition: jni_util.h:80
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:482
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
Definition: jni_util.h:467
bool convertUTF8ToUTF16String(StringRef SrcUTF8, SmallVectorImpl< UTF16 > &DstUTF16)
Converts a UTF-8 string into a UTF-16 string with native endianness.
Definition: jni_util.h:336
Definition: jni_util.h:541
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const noexcept
empty - Check if the string is empty.
Definition: StringRef.h:133
bool convertUTF16ToUTF8String(ArrayRef< UTF16 > SrcUTF16, SmallVectorImpl< char > &DstUTF8)
Converts a UTF-16 string into a UTF-8 string.
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:999
Definition: jni_util.h:136
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Definition: jni_util.h:74
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const noexcept
size - Get the string size.
Definition: StringRef.h:138
Definition: jni_util.h:104
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: jni_util.h:477
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:151
Definition: jni_util.h:624
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149