-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add std::string_view support. See #196
- Loading branch information
Showing
10 changed files
with
198 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,8 @@ Gemfile.lock | |
*.bundle | ||
README.doxygen | ||
doc/_build | ||
|
||
.vs/ | ||
cmake* | ||
pkg | ||
*.log | ||
.*.swp | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.. _std_string_view: | ||
|
||
std::string_view | ||
----------------- | ||
``std::string_view`` is a read-only reference to a sequence of `char`s. It provides a way of passing strings without the overhead of copying `std::string`. | ||
|
||
On input, Rice treats ``std::string_view`` as a Builtin type which means it copies the portion of the ``char`` sequence that a ``std::string_view`` references in C++ to Ruby. Please refer to the :ref:`_std_string_view` documentation to learn about how Rice handles encodings.my-refere | ||
|
||
On output, Rice creates a ``std::string_view`` that references a Ruby string's underlying `char` buffer. Note this is DANGEROUS. Sooner or later the Ruby string will be garbage collected or moved as part of compaction, thus invalidating the `char` buffer. So use this with caution. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef Rice__stl__string_view__hpp_ | ||
#define Rice__stl__string_view__hpp_ | ||
|
||
#include "string_view.ipp" | ||
|
||
#endif // Rice__stl__string_view__hpp_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#include <string_view> | ||
#include "../detail/ruby.hpp" | ||
#include "../detail/Type.hpp" | ||
#include "../detail/from_ruby.hpp" | ||
#include "../detail/to_ruby.hpp" | ||
|
||
namespace Rice::detail | ||
{ | ||
template<> | ||
struct Type<std::string_view> | ||
{ | ||
static bool verify() | ||
{ | ||
return true; | ||
} | ||
}; | ||
|
||
template<> | ||
class To_Ruby<std::string_view> | ||
{ | ||
public: | ||
VALUE convert(std::string_view const& x) | ||
{ | ||
return detail::protect(rb_external_str_new, x.data(), (long)x.size()); | ||
} | ||
}; | ||
|
||
template<> | ||
class To_Ruby<std::string_view&> | ||
{ | ||
public: | ||
VALUE convert(std::string_view const& x) | ||
{ | ||
return detail::protect(rb_external_str_new, x.data(), (long)x.size()); | ||
} | ||
}; | ||
|
||
template<> | ||
class From_Ruby<std::string_view> | ||
{ | ||
public: | ||
From_Ruby() = default; | ||
|
||
explicit From_Ruby(Arg* arg) : arg_(arg) | ||
{ | ||
} | ||
|
||
bool is_convertible(VALUE value) | ||
{ | ||
return rb_type(value) == RUBY_T_STRING; | ||
} | ||
|
||
std::string_view convert(VALUE value) | ||
{ | ||
if (value == Qnil && this->arg_ && this->arg_->hasDefaultValue()) | ||
{ | ||
return this->arg_->defaultValue<std::string_view>(); | ||
} | ||
else | ||
{ | ||
detail::protect(rb_check_type, value, (int)T_STRING); | ||
return std::string_view(RSTRING_PTR(value), RSTRING_LEN(value)); | ||
} | ||
} | ||
|
||
private: | ||
Arg* arg_ = nullptr; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#include "unittest.hpp" | ||
#include "embed_ruby.hpp" | ||
#include <rice/rice.hpp> | ||
#include <ruby/encoding.h> | ||
#include <rice/stl.hpp> | ||
|
||
#include <optional> | ||
|
||
using namespace Rice; | ||
|
||
TESTSUITE(StlStringView); | ||
|
||
SETUP(StlStringView) | ||
{ | ||
embed_ruby(); | ||
} | ||
|
||
TESTCASE(std_string_view_to_ruby) | ||
{ | ||
ASSERT(rb_equal(String("").value(), detail::to_ruby(std::string_view("")))); | ||
ASSERT(rb_equal(String("foo").value(), detail::to_ruby(std::string_view("foo")))); | ||
} | ||
|
||
TESTCASE(std_string_view_to_ruby_encoding) | ||
{ | ||
VALUE value = detail::to_ruby(std::string_view("Some String")); | ||
String string(value); | ||
Object encoding = string.call("encoding"); | ||
String encodingName = encoding.call("name"); | ||
std::string_view result = detail::From_Ruby<std::string_view>().convert(encodingName); | ||
if(result != "ASCII-8BIT" && result != "US-ASCII" && result != "UTF-8") { | ||
FAIL("Encoding incorrect", "ASCII-8BIT, US-ASCII, or UTF-8 (Windows)", result); | ||
} | ||
} | ||
|
||
TESTCASE(std_string_view_to_ruby_encoding_utf8) | ||
{ | ||
rb_encoding* defaultEncoding = rb_default_external_encoding(); | ||
|
||
VALUE utf8Encoding = rb_enc_from_encoding(rb_utf8_encoding()); | ||
rb_enc_set_default_external(utf8Encoding); | ||
|
||
VALUE value = detail::to_ruby(std::string_view("Some String")); | ||
Object object(value); | ||
Object encoding = object.call("encoding"); | ||
Object encodingName = encoding.call("name"); | ||
ASSERT_EQUAL("UTF-8", detail::From_Ruby<std::string_view>().convert(encodingName)); | ||
|
||
rb_enc_set_default_external(rb_enc_from_encoding(defaultEncoding)); | ||
} | ||
|
||
TESTCASE(std_string_view_from_ruby) | ||
{ | ||
ASSERT_EQUAL(std::string_view(""), detail::From_Ruby<std::string_view>().convert(rb_str_new2(""))); | ||
ASSERT_EQUAL(std::string_view("foo"), detail::From_Ruby<std::string_view>().convert(rb_str_new2("foo"))); | ||
|
||
ASSERT_EXCEPTION_CHECK( | ||
Exception, | ||
detail::From_Ruby<std::string_view>().convert(rb_float_new(15.512)), | ||
ASSERT_EQUAL("wrong argument type Float (expected String)", ex.what()) | ||
); | ||
} | ||
|
||
TESTCASE(std_string_view_to_ruby_with_binary) | ||
{ | ||
Rice::String got = detail::to_ruby(std::string_view("\000test", 5)); | ||
|
||
ASSERT_EQUAL(String(std::string_view("\000test", 5)), got); | ||
ASSERT_EQUAL(5ul, got.length()); | ||
} | ||
|
||
TESTCASE(std_string_view_from_ruby_with_binary) | ||
{ | ||
std::string_view got = detail::From_Ruby<std::string_view>().convert(rb_str_new("\000test", 5)); | ||
ASSERT_EQUAL(5ul, got.length()); | ||
ASSERT_EQUAL(std::string_view("\000test", 5), got); | ||
} | ||
|
||
TESTCASE(std_string_view_from_ruby_refefence) | ||
{ | ||
VALUE value = rb_str_new("test", 4); | ||
std::string_view view = detail::From_Ruby<std::string_view>().convert(value); | ||
ASSERT_EQUAL("test", view); | ||
|
||
String string(value); | ||
string.instance_eval("self[1] = 'a'"); | ||
ASSERT_EQUAL("tast", view); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters