0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 18:18:56 +02:00

ircd::js: Add string literal constructor to prevent any alloc/copy/free.

This commit is contained in:
Jason Volk 2016-10-26 07:49:57 -07:00
parent fcc9cdee74
commit 5de2622bd1
4 changed files with 42 additions and 10 deletions

View file

@ -25,8 +25,8 @@
namespace ircd {
namespace js {
void native_external_delete(const JSStringFinalizer *, char16_t *);
extern JSStringFinalizer native_external_deleter;
extern JSStringFinalizer native_external_delete; // calls `delete[]` on char16_t[]
extern JSStringFinalizer native_external_static; // no-op for static/literal or self-managed
std::unique_ptr<char16_t[]> native_external_copy(const char *const &s, const size_t &len);
std::unique_ptr<char16_t[]> native_external_copy(const char *const &s);

View file

@ -32,6 +32,7 @@ char16_t at(const JSString *const &, const size_t &);
struct string
:JS::Rooted<JSString *>
{
IRCD_OVERLOAD(literal)
using handle = JS::HandleString;
using handle_mutable = JS::MutableHandleString;
@ -47,6 +48,7 @@ struct string
char16_t operator[](const size_t &at) const;
string(literal_t, const char16_t *const &);
string(const char16_t *const &, const size_t &len);
string(const char16_t *const &);
string(const std::u16string &);
@ -145,7 +147,7 @@ string::string(const char *const &s,
*cx, [&s, &len]
{
auto buf(native_external_copy(s, len));
return JS_NewExternalString(*cx, buf.release(), len, &native_external_deleter);
return JS_NewExternalString(*cx, buf.release(), len, &native_external_delete);
}()
}
{
@ -177,7 +179,7 @@ string::string(const char16_t *const &s,
auto buf(std::make_unique<char16_t[]>(len+1));
memcpy(buf.get(), s, len * 2);
buf.get()[len] = char16_t(0);
return JS_NewExternalString(*cx, buf.release(), len, &native_external_deleter);
return JS_NewExternalString(*cx, buf.release(), len, &native_external_delete);
}()
}
{
@ -185,6 +187,19 @@ string::string(const char16_t *const &s,
throw type_error("Failed to construct string from character array");
}
inline
string::string(literal_t,
const char16_t *const &s)
:JS::Rooted<JSString *>
{
*cx,
JS_NewExternalString(*cx, s, std::char_traits<char16_t>::length(s), &native_external_static)
}
{
if(unlikely(!get()))
throw type_error("Failed to construct string from wide character literal");
}
inline
char16_t
string::operator[](const size_t &pos)

View file

@ -207,7 +207,7 @@ value::value(const std::string &s)
*cx, [&s]
{
auto buf(native_external_copy(s));
const auto ret(JS_NewExternalString(*cx, buf.release(), s.size(), &native_external_deleter));
const auto ret(JS_NewExternalString(*cx, buf.release(), s.size(), &native_external_delete));
return JS::StringValue(ret);
}()
}
@ -222,7 +222,7 @@ value::value(const char *const &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));
const auto ret(JS_NewExternalString(*cx, buf.release(), len, &native_external_delete));
return JS::StringValue(ret);
}()
}

View file

@ -1145,9 +1145,17 @@ const
namespace ircd {
namespace js {
JSStringFinalizer native_external_deleter
void native_external_noop(const JSStringFinalizer *const fin, char16_t *const buf);
void native_external_deleter(const JSStringFinalizer *const fin, char16_t *const buf);
JSStringFinalizer native_external_delete
{
native_external_delete
native_external_deleter
};
JSStringFinalizer native_external_static
{
native_external_noop
};
} // namespace js
@ -1184,8 +1192,8 @@ ircd::js::native(const JSString *const &s,
}
void
ircd::js::native_external_delete(const JSStringFinalizer *const fin,
char16_t *const buf)
ircd::js::native_external_deleter(const JSStringFinalizer *const fin,
char16_t *const buf)
{
log.debug("string delete (fin: %p buf: %p)",
(const void *)fin,
@ -1194,6 +1202,15 @@ ircd::js::native_external_delete(const JSStringFinalizer *const fin,
delete[] buf;
}
void
ircd::js::native_external_noop(const JSStringFinalizer *const fin,
char16_t *const buf)
{
log.debug("string literal release (fin: %p buf: %p)",
(const void *)fin,
(const void *)buf);
}
///////////////////////////////////////////////////////////////////////////////
//
// ircd/js/error.h