0
0
Fork 0
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:
Jason Volk 2016-10-19 17:05:58 -07:00
parent 0b9efe06a1
commit 4872883860
3 changed files with 143 additions and 47 deletions

View file

@ -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

View file

@ -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

View file

@ -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));
}
///////////////////////////////////////////////////////////////////////////////