mirror of
https://github.com/matrix-construct/construct
synced 2025-02-18 01:30:12 +01:00
ircd::js: Improve value construction / string related.
This commit is contained in:
parent
0b9efe06a1
commit
4872883860
3 changed files with 143 additions and 47 deletions
|
@ -29,14 +29,16 @@ struct string
|
|||
:JS::Rooted<JSString *>
|
||||
{
|
||||
// SpiderMonkey may use utf-16/char16_t strings; these will help you then
|
||||
static size_t convert(const char16_t *const &, char *const &buf, const size_t &max);
|
||||
static std::string convert(const char16_t *const &);
|
||||
static std::string convert(const std::u16string &);
|
||||
static std::u16string convert(const char *const &);
|
||||
static std::u16string convert(const std::string &);
|
||||
|
||||
static constexpr size_t CBUFSZ = 1024;
|
||||
static constexpr size_t CBUFS = 8;
|
||||
static constexpr const size_t CBUFS = 8;
|
||||
static const size_t CBUFSZ;
|
||||
const char *c_str() const; // Copy into rotating buf
|
||||
size_t size() const;
|
||||
|
||||
explicit operator std::string() const;
|
||||
operator JS::Value() const;
|
||||
|
@ -118,9 +120,14 @@ inline
|
|||
string::operator std::string()
|
||||
const
|
||||
{
|
||||
std::string ret(JS_GetStringEncodingLength(*cx, const_cast<JSString *>(get())), char());
|
||||
JS_EncodeStringToBuffer(*cx, const_cast<JSString *>(get()), &ret.front(), ret.size());
|
||||
return ret;
|
||||
return native(get());
|
||||
}
|
||||
|
||||
inline size_t
|
||||
string::size()
|
||||
const
|
||||
{
|
||||
return native_size(get());
|
||||
}
|
||||
|
||||
inline
|
||||
|
|
|
@ -25,22 +25,31 @@
|
|||
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<JS::Value>
|
||||
{
|
||||
explicit operator bool() const { return JS::ToBoolean(*this); }
|
||||
explicit operator uint16_t() const;
|
||||
explicit operator int32_t() const;
|
||||
explicit operator uint32_t() const;
|
||||
explicit operator int64_t() const;
|
||||
explicit operator uint64_t() const;
|
||||
explicit operator std::string() const;
|
||||
explicit operator double() const;
|
||||
explicit operator uint64_t() const;
|
||||
explicit operator int64_t() const;
|
||||
explicit operator uint32_t() const;
|
||||
explicit operator int32_t() const;
|
||||
explicit operator uint16_t() const;
|
||||
explicit operator bool() const { return JS::ToBoolean(*this); }
|
||||
|
||||
explicit value(const bool &);
|
||||
value(const char *const &);
|
||||
explicit value(const std::string &);
|
||||
explicit value(const nullptr_t &);
|
||||
explicit value(const int32_t &);
|
||||
explicit value(const float &);
|
||||
explicit value(const double &);
|
||||
explicit value(const float &);
|
||||
explicit value(const int32_t &);
|
||||
explicit value(const bool &);
|
||||
|
||||
value(const jsid &);
|
||||
value(JSObject &);
|
||||
|
@ -137,12 +146,6 @@ value::value(const bool &b)
|
|||
{
|
||||
}
|
||||
|
||||
inline
|
||||
value::value(const nullptr_t &)
|
||||
:JS::Rooted<JS::Value>{*cx, JS::NullValue()}
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
value::value(const int32_t &val)
|
||||
:JS::Rooted<JS::Value>{*cx, JS::Int32Value(val)}
|
||||
|
@ -162,34 +165,38 @@ value::value(const double &val)
|
|||
}
|
||||
|
||||
inline
|
||||
value::operator double()
|
||||
const
|
||||
value::value(const nullptr_t &)
|
||||
:JS::Rooted<JS::Value>{*cx, JS::NullValue()}
|
||||
{
|
||||
double ret;
|
||||
if(!JS::ToNumber(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to double");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline
|
||||
value::operator int64_t()
|
||||
const
|
||||
value::value(const std::string &s)
|
||||
:JS::Rooted<JS::Value>
|
||||
{
|
||||
*cx,
|
||||
JS::StringValue(JS_NewStringCopyN(*cx, s.data(), s.size()))
|
||||
}
|
||||
{
|
||||
int64_t ret;
|
||||
if(!JS::ToInt64(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to int64_t");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline
|
||||
value::operator uint64_t()
|
||||
value::value(const char *const &s)
|
||||
:JS::Rooted<JS::Value>
|
||||
{
|
||||
*cx,
|
||||
!s? JS::NullValue() : JS::StringValue(JS_NewStringCopyZ(*cx, s))
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
value::operator uint16_t()
|
||||
const
|
||||
{
|
||||
uint64_t ret;
|
||||
if(!JS::ToUint64(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to uint64_t");
|
||||
uint16_t ret;
|
||||
if(!JS::ToUint16(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to uint16_t");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -217,15 +224,45 @@ const
|
|||
}
|
||||
|
||||
inline
|
||||
value::operator uint16_t()
|
||||
value::operator int64_t()
|
||||
const
|
||||
{
|
||||
uint16_t ret;
|
||||
if(!JS::ToUint16(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to uint16_t");
|
||||
int64_t ret;
|
||||
if(!JS::ToInt64(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to int64_t");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline
|
||||
value::operator uint64_t()
|
||||
const
|
||||
{
|
||||
uint64_t ret;
|
||||
if(!JS::ToUint64(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to uint64_t");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline
|
||||
value::operator double()
|
||||
const
|
||||
{
|
||||
double ret;
|
||||
if(!JS::ToNumber(*cx, *this, &ret))
|
||||
throw type_error("Failed cast to double");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline
|
||||
value::operator std::string()
|
||||
const
|
||||
{
|
||||
const auto s(JS::ToString(*cx, *this));
|
||||
return s? native(s) : throw type_error("Failed to cast to string");
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
} // namespace ircd
|
||||
|
|
62
ircd/js.cc
62
ircd/js.cc
|
@ -719,6 +719,11 @@ ircd::js::call(const object &obj,
|
|||
// ircd/js/string.h
|
||||
//
|
||||
|
||||
const size_t ircd::js::string::CBUFSZ
|
||||
{
|
||||
1024
|
||||
};
|
||||
|
||||
const char *
|
||||
ircd::js::string::c_str()
|
||||
const
|
||||
|
@ -727,7 +732,7 @@ const
|
|||
static thread_local size_t ctr;
|
||||
|
||||
char *const buf(cbuf[ctr]);
|
||||
JS_EncodeStringToBuffer(*cx, const_cast<JSString *>(get()), buf, CBUFSZ);
|
||||
native(get(), buf, CBUFSZ);
|
||||
ctr = (ctr + 1) % CBUFS;
|
||||
return buf;
|
||||
}
|
||||
|
@ -737,7 +742,7 @@ ircd::js::string::convert(const std::string &s)
|
|||
{
|
||||
static std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter;
|
||||
|
||||
return converter.from_bytes(s);
|
||||
return converter.from_bytes(s);
|
||||
}
|
||||
|
||||
std::u16string
|
||||
|
@ -745,7 +750,7 @@ ircd::js::string::convert(const char *const &s)
|
|||
{
|
||||
static std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter;
|
||||
|
||||
return s? converter.from_bytes(s) : std::u16string{};
|
||||
return s? converter.from_bytes(s) : std::u16string{};
|
||||
}
|
||||
|
||||
std::string
|
||||
|
@ -753,7 +758,7 @@ ircd::js::string::convert(const std::u16string &s)
|
|||
{
|
||||
static std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter;
|
||||
|
||||
return converter.to_bytes(s);
|
||||
return converter.to_bytes(s);
|
||||
}
|
||||
|
||||
std::string
|
||||
|
@ -761,7 +766,54 @@ ircd::js::string::convert(const char16_t *const &s)
|
|||
{
|
||||
static std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter;
|
||||
|
||||
return s? converter.to_bytes(s) : std::string{};
|
||||
return s? converter.to_bytes(s) : std::string{};
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::js::string::convert(const char16_t *const &str,
|
||||
char *const &buf,
|
||||
const size_t &max)
|
||||
{
|
||||
static std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter;
|
||||
|
||||
//TODO: optimize
|
||||
const auto s(converter.to_bytes(str));
|
||||
return rb_strlcpy(buf, s.c_str(), max);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ircd/js/value.h
|
||||
//
|
||||
|
||||
std::string
|
||||
ircd::js::native(const JSString *const &s)
|
||||
{
|
||||
std::string ret(native_size(s) + 1, char());
|
||||
native(s, &ret.front(), ret.size());
|
||||
ret.resize(ret.size() - 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::js::native(const JSString *const &s,
|
||||
char *const &buf,
|
||||
const size_t &max)
|
||||
{
|
||||
if(unlikely(!max))
|
||||
return 0;
|
||||
|
||||
ssize_t ret(JS_EncodeStringToBuffer(*cx, const_cast<JSString *>(s), buf, max));
|
||||
ret = std::max(ret, ssize_t(0));
|
||||
ret = std::min(ret, ssize_t(max - 1));
|
||||
buf[ret] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::js::native_size(const JSString *const &s)
|
||||
{
|
||||
return JS_GetStringEncodingLength(*cx, const_cast<JSString *>(s));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Reference in a new issue