aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2021-08-27 13:39:10 -0700
committerGitHub <noreply@github.com>2021-08-27 13:39:10 -0700
commit4e0ac983992f9bb59bf2a457eb778e42582c85b4 (patch)
tree2e006139377f982ee64bc5dbdee715d8b336915f
parent800d98989532e519d422b94544e1421c9cb73006 (diff)
parent6f3f4bb7ee2e42d8bb10d3a963cd4b0b5f1733c8 (diff)
downloadcxx-4e0ac983992f9bb59bf2a457eb778e42582c85b4.tar.gz
Merge pull request #925 from dtolnay/cxxstringreserve
Expose reserve on CxxString
-rw-r--r--src/cxx.cc5
-rw-r--r--src/cxx_string.rs30
2 files changed, 35 insertions, 0 deletions
diff --git a/src/cxx.cc b/src/cxx.cc
index 2a615483..5dca531b 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -24,6 +24,11 @@ std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); }
+void cxxbridge1$cxx_string$reserve_total(std::string &s,
+ size_t new_cap) noexcept {
+ s.reserve(new_cap);
+}
+
void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
std::size_t len) noexcept {
s.append(reinterpret_cast<const char *>(ptr), len);
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index cdd77db5..626c2c85 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -21,6 +21,8 @@ extern "C" {
fn string_length(this: &CxxString) -> usize;
#[link_name = "cxxbridge1$cxx_string$clear"]
fn string_clear(this: Pin<&mut CxxString>);
+ #[link_name = "cxxbridge1$cxx_string$reserve_total"]
+ fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize);
#[link_name = "cxxbridge1$cxx_string$push"]
fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
}
@@ -161,6 +163,34 @@ impl CxxString {
unsafe { string_clear(self) }
}
+ /// Ensures that this string's capacity is at least `additional` bytes
+ /// larger than its length.
+ ///
+ /// The capacity may be increased by more than `additional` bytes if it
+ /// chooses, to amortize the cost of frequent reallocations.
+ ///
+ /// **The meaning of the argument is not the same as
+ /// [std::string::reserve][reserve] in C++.** The C++ standard library and
+ /// Rust standard library both have a `reserve` method on strings, but in
+ /// C++ code the argument always refers to total capacity, whereas in Rust
+ /// code it always refers to additional capacity. This API on `CxxString`
+ /// follows the Rust convention, the same way that for the length accessor
+ /// we use the Rust conventional `len()` naming and not C++ `size()` or
+ /// `length()`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity overflows usize.
+ ///
+ /// [reserve]: https://en.cppreference.com/w/cpp/string/basic_string/reserve
+ pub fn reserve(self: Pin<&mut Self>, additional: usize) {
+ let new_cap = self
+ .len()
+ .checked_add(additional)
+ .expect("CxxString capacity overflow");
+ unsafe { string_reserve_total(self, new_cap) }
+ }
+
/// Appends a given string slice onto the end of this C++ string.
pub fn push_str(self: Pin<&mut Self>, s: &str) {
self.push_bytes(s.as_bytes());