From 4c62795aeb37f47830b4832b047ee13a847a8f74 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Wed, 26 Oct 2016 01:28:17 -0700 Subject: [PATCH] ircd::js: Use jsapi external string facilities for string constructions. --- include/ircd/js/js.h | 1 + include/ircd/js/native.h | 61 ++++++++++++++++++++++++++++++++++++++++ include/ircd/js/string.h | 11 +++++--- include/ircd/js/value.h | 23 ++++++++------- ircd/js.cc | 33 ++++++++++++++++++++-- 5 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 include/ircd/js/native.h diff --git a/include/ircd/js/js.h b/include/ircd/js/js.h index 0b98103a7..31104de9a 100644 --- a/include/ircd/js/js.h +++ b/include/ircd/js/js.h @@ -61,6 +61,7 @@ inline JSVersion version(const char *const &v) { return JS_StringToVersion(v); #include "compartment.h" #include "debug.h" #include "error.h" +#include "native.h" #include "value.h" #include "string.h" #include "id.h" diff --git a/include/ircd/js/native.h b/include/ircd/js/native.h new file mode 100644 index 000000000..d4ddc923e --- /dev/null +++ b/include/ircd/js/native.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once +#define HAVE_IRCD_JS_NATIVE_H + +namespace ircd { +namespace js { + +void native_external_delete(const JSStringFinalizer *, char16_t *); +extern JSStringFinalizer native_external_deleter; + +std::unique_ptr native_external_copy(const char *const &s, const size_t &len); +std::unique_ptr native_external_copy(const char *const &s); +std::unique_ptr native_external_copy(const std::string &s); + +size_t native(const JSString *const &, char *const &buf, const size_t &max); +size_t native_size(const JSString *const &); +std::string native(const JSString *const &); + +} // namespace js +} // namespace ircd + +inline std::unique_ptr +ircd::js::native_external_copy(const std::string &s) +{ + return native_external_copy(s.data(), s.size()); +} + +inline std::unique_ptr +ircd::js::native_external_copy(const char *const &s) +{ + return native_external_copy(s, strlen(s)); +} + +inline std::unique_ptr +ircd::js::native_external_copy(const char *const &s, + const size_t &len) +{ + auto buf(std::make_unique(len + 1)); + ircd::locale::convert(s, buf.get(), len + 1); + return buf; +} diff --git a/include/ircd/js/string.h b/include/ircd/js/string.h index 1e13db8e5..920bbf75d 100644 --- a/include/ircd/js/string.h +++ b/include/ircd/js/string.h @@ -118,12 +118,15 @@ string::string(const char *const &s) } inline -string::string(const char *const &s, - const size_t &len) +ircd::js::string::string(const char *const &s, + const size_t &len) :JS::Rooted { - *cx, - JS_NewStringCopyN(*cx, s, len) + *cx, [&s, &len] + { + auto buf(native_external_copy(s, len)); + return JS_NewExternalString(*cx, buf.release(), len, &native_external_deleter); + }() } { if(unlikely(!get())) diff --git a/include/ircd/js/value.h b/include/ircd/js/value.h index 48ac830a7..68561c682 100644 --- a/include/ircd/js/value.h +++ b/include/ircd/js/value.h @@ -25,12 +25,6 @@ namespace ircd { namespace js { -// Fundamental string utils. This is placed here instead of string.h so -// `struct value` can make direct conversions without depending on struct string type -size_t native_size(const JSString *const &); -size_t native(const JSString *const &, char *const &buf, const size_t &max); -std::string native(const JSString *const &); - struct value :JS::Rooted { @@ -210,8 +204,12 @@ inline value::value(const std::string &s) :JS::Rooted { - *cx, - JS::StringValue(JS_NewStringCopyN(*cx, s.data(), s.size())) + *cx, [&s] + { + auto buf(native_external_copy(s)); + const auto ret(JS_NewExternalString(*cx, buf.release(), s.size(), &native_external_deleter)); + return JS::StringValue(ret); + }() } { } @@ -220,8 +218,13 @@ inline value::value(const char *const &s) :JS::Rooted { - *cx, - !s? JS::NullValue() : JS::StringValue(JS_NewStringCopyZ(*cx, s)) + *cx, !s? JS::NullValue() : [&s] + { + const auto len(strlen(s)); + auto buf(native_external_copy(s, len)); + const auto ret(JS_NewExternalString(*cx, buf.release(), len, &native_external_deleter)); + return JS::StringValue(ret); + }() } { } diff --git a/ircd/js.cc b/ircd/js.cc index 8eac65bb4..7c011a6a8 100644 --- a/ircd/js.cc +++ b/ircd/js.cc @@ -1130,6 +1130,22 @@ const // ircd/js/value.h // +/////////////////////////////////////////////////////////////////////////////// +// +// ircd/js/native.h +// + +namespace ircd { +namespace js { + +JSStringFinalizer native_external_deleter +{ + native_external_delete +}; + +} // namespace js +} // namespace ircd + std::string ircd::js::native(const JSString *const &s) { @@ -1139,6 +1155,12 @@ ircd::js::native(const JSString *const &s) return ret; } +size_t +ircd::js::native_size(const JSString *const &s) +{ + return JS_GetStringEncodingLength(*cx, const_cast(s)); +} + size_t ircd::js::native(const JSString *const &s, char *const &buf, @@ -1154,10 +1176,15 @@ ircd::js::native(const JSString *const &s, return ret; } -size_t -ircd::js::native_size(const JSString *const &s) +void +ircd::js::native_external_delete(const JSStringFinalizer *const fin, + char16_t *const buf) { - return JS_GetStringEncodingLength(*cx, const_cast(s)); + log.debug("string delete (fin: %p buf: %p)", + (const void *)fin, + (const void *)buf); + + delete[] buf; } ///////////////////////////////////////////////////////////////////////////////