1 /*
2  * Copyright (C) 2010 The Android Open Source Project
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 #ifndef SCOPED_UTF_CHARS_H_
18 #define SCOPED_UTF_CHARS_H_
19 
20 #include <string.h>
21 
22 #include "jni.h"
23 #include "nativehelper_utils.h"
24 
25 // A smart pointer that provides read-only access to a Java string's UTF chars.
26 // Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
27 // passed a null jstring, and c_str will return nullptr.
28 // This makes the correct idiom very simple:
29 //
30 //   ScopedUtfChars name(env, java_name);
31 //   if (name.c_str() == nullptr) {
32 //     return nullptr;
33 //   }
34 class ScopedUtfChars {
35  public:
ScopedUtfChars(JNIEnv * env,jstring s)36   ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
37     if (s == nullptr) {
38       utf_chars_ = nullptr;
39       jniThrowNullPointerException(env, nullptr);
40     } else {
41       utf_chars_ = env->GetStringUTFChars(s, nullptr);
42     }
43   }
44 
ScopedUtfChars(ScopedUtfChars && rhs)45   ScopedUtfChars(ScopedUtfChars&& rhs) noexcept :
46       env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
47     rhs.env_ = nullptr;
48     rhs.string_ = nullptr;
49     rhs.utf_chars_ = nullptr;
50   }
51 
~ScopedUtfChars()52   ~ScopedUtfChars() {
53     if (utf_chars_) {
54       env_->ReleaseStringUTFChars(string_, utf_chars_);
55     }
56   }
57 
58   ScopedUtfChars& operator=(ScopedUtfChars&& rhs) noexcept {
59     if (this != &rhs) {
60       // Delete the currently owned UTF chars.
61       this->~ScopedUtfChars();
62 
63       // Move the rhs ScopedUtfChars and zero it out.
64       env_ = rhs.env_;
65       string_ = rhs.string_;
66       utf_chars_ = rhs.utf_chars_;
67       rhs.env_ = nullptr;
68       rhs.string_ = nullptr;
69       rhs.utf_chars_ = nullptr;
70     }
71     return *this;
72   }
73 
c_str()74   const char* c_str() const {
75     return utf_chars_;
76   }
77 
size()78   size_t size() const {
79     return strlen(utf_chars_);
80   }
81 
82   const char& operator[](size_t n) const {
83     return utf_chars_[n];
84   }
85 
86  private:
87   JNIEnv* env_;
88   jstring string_;
89   const char* utf_chars_;
90 
91   DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
92 };
93 
94 #endif  // SCOPED_UTF_CHARS_H_
95