From 718a11e80cb9232e7ab2e7326aeece365510961c Mon Sep 17 00:00:00 2001 From: Manu Evans Date: Sun, 23 Sep 2018 15:19:54 -0700 Subject: [PATCH 1/2] Added std::string_view<> --- changelog/string_view.dd | 3 + mak/COPY | 1 + mak/DOCS | 1 + mak/SRCS | 1 + src/core/stdcpp/string_view.d | 155 ++++++++++++++++++++++++++++++++++ 5 files changed, 161 insertions(+) create mode 100644 changelog/string_view.dd create mode 100644 src/core/stdcpp/string_view.d diff --git a/changelog/string_view.dd b/changelog/string_view.dd new file mode 100644 index 0000000000..81073e23f1 --- /dev/null +++ b/changelog/string_view.dd @@ -0,0 +1,3 @@ +Added `core.stdcpp.string_view`. + +Added `core.stdcpp.string_view`, which links against C++ `std::string_view` diff --git a/mak/COPY b/mak/COPY index b2c5d9dffd..1e6789e0b3 100644 --- a/mak/COPY +++ b/mak/COPY @@ -50,6 +50,7 @@ COPY=\ \ $(IMPDIR)\core\stdcpp\array.d \ $(IMPDIR)\core\stdcpp\exception.d \ + $(IMPDIR)\core\stdcpp\string_view.d \ $(IMPDIR)\core\stdcpp\typeinfo.d \ $(IMPDIR)\core\stdcpp\xutility.d \ \ diff --git a/mak/DOCS b/mak/DOCS index 5904029c10..248c5c8331 100644 --- a/mak/DOCS +++ b/mak/DOCS @@ -39,6 +39,7 @@ DOCS=\ $(DOCDIR)\core_stdc_wctype.html \ \ $(DOCDIR)\core_stdcpp_array.html \ + $(DOCDIR)\core_stdcpp_string_view.html \ $(DOCDIR)\core_stdcpp_exception.html \ $(DOCDIR)\core_stdcpp_typeinfo.html \ \ diff --git a/mak/SRCS b/mak/SRCS index 62a2226059..8ec873a016 100644 --- a/mak/SRCS +++ b/mak/SRCS @@ -47,6 +47,7 @@ SRCS=\ src\core\stdc\wchar_.d \ \ src\core\stdcpp\array.d \ + src\core\stdcpp\string_view.d \ src\core\stdcpp\xutility.d \ \ src\core\sync\barrier.d \ diff --git a/src/core/stdcpp/string_view.d b/src/core/stdcpp/string_view.d new file mode 100644 index 0000000000..de744ff69d --- /dev/null +++ b/src/core/stdcpp/string_view.d @@ -0,0 +1,155 @@ +/** + * D header file for interaction with C++ std::string_view. + * + * Copyright: Copyright (c) 2018 D Language Foundation + * License: Distributed under the + * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). + * (See accompanying file LICENSE) + * Authors: Manu Evans + * Source: $(DRUNTIMESRC core/stdcpp/string_view.d) + */ + +module core.stdcpp.string_view; + +import core.stdc.stddef : wchar_t; + +// hacks to support DMD on Win32 +version (CppRuntime_Microsoft) +{ + version = CppRuntime_Windows; // use the MS runtime ABI for win32 +} +else version (CppRuntime_DigitalMars) +{ + version = CppRuntime_Windows; // use the MS runtime ABI for win32 + pragma(msg, "std::basic_string_view not supported by DMC"); +} +version (CppRuntime_Clang) +{ + private alias AliasSeq(Args...) = Args; + private enum StdNamespace = AliasSeq!("std", "__1"); +} +else +{ + private enum StdNamespace = "std"; +} + +extern(C++, (StdNamespace)): + +/// +alias string_view = basic_string_view!char; +//alias u16string_view = basic_string_view!wchar; // TODO: can't mangle these yet either... +//alias u32string_view = basic_string_view!dchar; +//alias wstring_view = basic_string_view!wchar_t; // TODO: we can't mangle wchar_t properly (yet?) + + +/** + * Character traits classes specify character properties and provide specific + * semantics for certain operations on characters and sequences of characters. + */ +extern(C++, struct) struct char_traits(CharT) {} + + +/** +* D language counterpart to C++ std::basic_string_view. +* +* C++ reference: $(LINK2 hhttps://en.cppreference.com/w/cpp/string/basic_string_view) +*/ +extern(C++, class) struct basic_string_view(T, Traits = char_traits!T) +{ +extern(D): +pragma(inline, true): + + /// + enum size_type npos = size_type.max; + + /// + alias size_type = size_t; + /// + alias difference_type = ptrdiff_t; + /// + alias value_type = T; + /// + alias pointer = T*; + /// + alias const_pointer = const(T)*; + + /// + alias as_array this; + + /// + alias length = size; + /// + alias opDollar = length; + /// + bool empty() const nothrow @safe @nogc { return size() == 0; } + + /// + ref const(T) front() const nothrow @safe @nogc { return this[0]; } + /// + ref const(T) back() const nothrow @safe @nogc { return this[$-1]; } + + version (CppRuntime_Windows) + { + /// + this(const(T)[] str) nothrow @trusted @nogc { _Mydata = str.ptr; _Mysize = str.length; } + + /// + size_type size() const nothrow @safe @nogc { return _Mysize; } + /// + const(T)* data() const nothrow @safe @nogc { return _Mydata; } + /// + const(T)[] as_array() const inout @trusted @nogc { return _Mydata[0 .. _Mysize]; } + /// + ref const(T) at(size_type i) const nothrow @trusted @nogc { return _Mydata[0 .. _Mysize][i]; } + + version (CppRuntime_Microsoft) + { + import core.stdcpp.xutility : MSVCLinkDirectives; + mixin MSVCLinkDirectives!false; + } + + private: + const_pointer _Mydata; + size_type _Mysize; + } + else version (CppRuntime_Gcc) + { + /// + this(const(T)[] str) nothrow @trusted @nogc { _M_str = str.ptr; _M_len = str.length; } + + /// + size_type size() const nothrow @safe @nogc { return _M_len; } + /// + const(T)* data() const nothrow @safe @nogc { return _M_str; } + /// + const(T)[] as_array() const nothrow @trusted @nogc { return _M_str[0 .. _M_len]; } + /// + ref const(T) at(size_type i) const nothrow @trusted @nogc { return _M_str[0 .. _M_len][i]; } + + private: + size_t _M_len; + const(T)* _M_str; + } + else version (CppRuntime_Clang) + { + /// + this(const(T)[] str) nothrow @trusted @nogc { __data = str.ptr; __size = str.length; } + + /// + size_type size() const nothrow @safe @nogc { return __size; } + /// + const(T)* data() const nothrow @safe @nogc { return __data; } + /// + const(T)[] as_array() const nothrow @trusted @nogc { return __data[0 .. __size]; } + /// + ref const(T) at(size_type i) const nothrow @trusted @nogc { return __data[0 .. __size][i]; } + + private: + const value_type* __data; + size_type __size; + } + else + { + static assert(false, "C++ runtime not supported"); + } +} From 5c08f1ec2e7563748ff257e6c6a346c58d3d7ca3 Mon Sep 17 00:00:00 2001 From: Manu Evans Date: Sun, 23 Sep 2018 15:20:06 -0700 Subject: [PATCH 2/2] Build and tests --- mak/WINDOWS | 3 ++ test/stdcpp/src/string_view.cpp | 17 ++++++++++ test/stdcpp/src/string_view_test.d | 50 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 test/stdcpp/src/string_view.cpp create mode 100644 test/stdcpp/src/string_view_test.d diff --git a/mak/WINDOWS b/mak/WINDOWS index 7766625190..b34a277164 100644 --- a/mak/WINDOWS +++ b/mak/WINDOWS @@ -190,6 +190,9 @@ $(IMPDIR)\core\stdcpp\exception.d : src\core\stdcpp\exception.d $(IMPDIR)\core\stdcpp\array.d : src\core\stdcpp\array.d copy $** $@ +$(IMPDIR)\core\stdcpp\string_view.d : src\core\stdcpp\string_view.d + copy $** $@ + $(IMPDIR)\core\stdcpp\typeinfo.d : src\core\stdcpp\typeinfo.d copy $** $@ diff --git a/test/stdcpp/src/string_view.cpp b/test/stdcpp/src/string_view.cpp new file mode 100644 index 0000000000..b27e6dc171 --- /dev/null +++ b/test/stdcpp/src/string_view.cpp @@ -0,0 +1,17 @@ +#include + +int fromC_val(std::string_view); +int fromC_ref(const std::string_view&); + +int sumOfElements_ref(const std::string_view& str) +{ + int r = 0; + for (size_t i = 0; i < str.size(); ++i) + r += str[i]; + return r; +} + +int sumOfElements_val(std::string_view str) +{ + return sumOfElements_ref(str) + fromC_ref(str) + fromC_val(str); +} diff --git a/test/stdcpp/src/string_view_test.d b/test/stdcpp/src/string_view_test.d new file mode 100644 index 0000000000..d34ce80acf --- /dev/null +++ b/test/stdcpp/src/string_view_test.d @@ -0,0 +1,50 @@ +import core.stdcpp.string_view; + +unittest +{ + string_view str = string_view("Hello"); + + assert(str.size == 5); + assert(str.length == 5); + assert(str.empty == false); + + assert(sumOfElements_val(str) == 1500); + assert(sumOfElements_ref(str) == 500); + + string_view str2 = string_view(); + assert(str2.size == 0); + assert(str2.length == 0); + assert(str2.empty == true); + assert(str2[] == []); +} + + +extern(C++): + +// test the ABI for calls to C++ +int sumOfElements_val(string_view); +int sumOfElements_ref(ref const(string_view)); + +// test the ABI for calls from C++ +int fromC_val(string_view str) +{ + assert(str[] == "Hello"); + assert(str.front == 'H'); + assert(str.back == 'o'); + assert(str.at(2) == 'l'); + + int r; + foreach (e; str) + r += e; + + assert(r == 500); + return r; +} + +int fromC_ref(ref const(string_view) str) +{ + int r; + foreach (e; str) + r += e; + return r; +}