Skip to content

Commit

Permalink
Add getStringData and getPropNameIdData implementation for Hermes
Browse files Browse the repository at this point in the history
Summary:
Adds the Hermes implementation for `getStringData` and `getPropNameIdData`,
which leverages the underlying UTF16 encoding

Grafted from 32084e2498f2b03ade118f1483b374dea4d7e711 (D65648690)
- Grafted path xplat/static_h to xplat/hermes

Reviewed By: tmikov

Differential Revision: D67412928

fbshipit-source-id: f9fa301e2fef49e7e77126aa65aa2303b8564497
  • Loading branch information
tsaichien authored and facebook-github-bot committed Jan 9, 2025
1 parent e08fb5f commit c995d19
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
39 changes: 39 additions & 0 deletions API/hermes/hermes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,16 @@ class HermesRuntimeImpl final : public HermesRuntime,
std::u16string utf16(const jsi::String &str) override;
std::u16string utf16(const jsi::PropNameID &sym) override;

void getStringData(
const jsi::String &str,
void *ctx,
void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) override;

void getPropNameIdData(
const jsi::PropNameID &sym,
void *ctx,
void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) override;

jsi::Value createValueFromJsonUtf8(const uint8_t *json, size_t length)
override;

Expand Down Expand Up @@ -1805,6 +1815,35 @@ std::u16string HermesRuntimeImpl::utf16(const jsi::PropNameID &sym) {
return std::u16string(arrayRef.data(), arrayRef.size());
}

void HermesRuntimeImpl::getStringData(
const jsi::String &str,
void *ctx,
void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) {
auto *stringPrim = phv(str).getString();
if (stringPrim->isASCII()) {
auto arrayRef = stringPrim->getStringRef<char>();
cb(ctx, true, arrayRef.data(), arrayRef.size());
} else {
auto arrayRef = stringPrim->getStringRef<char16_t>();
cb(ctx, false, arrayRef.data(), arrayRef.size());
}
}

void HermesRuntimeImpl::getPropNameIdData(
const jsi::PropNameID &sym,
void *ctx,
void (*cb)(void *ctx, bool ascii, const void *data, size_t num)) {
vm::SymbolID id = phv(sym).getSymbol();
auto *stringPrim = runtime_.getStringPrimFromSymbolID(id);
if (stringPrim->isASCII()) {
auto arrayRef = stringPrim->getStringRef<char>();
cb(ctx, true, arrayRef.data(), arrayRef.size());
} else {
auto arrayRef = stringPrim->getStringRef<char16_t>();
cb(ctx, false, arrayRef.data(), arrayRef.size());
}
}

jsi::Value HermesRuntimeImpl::createValueFromJsonUtf8(
const uint8_t *json,
size_t length) {
Expand Down
76 changes: 76 additions & 0 deletions unittests/API/APITest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,82 @@ TEST_P(HermesRuntimeTest, UTF16Test) {
}
}

TEST_P(HermesRuntimeTest, GetStringDataTest) {
std::u16string buf;
auto cb = [&buf](bool ascii, const void *data, size_t num) {
// this callback copies the string content, but removes every 'o' character
if (ascii) {
const char *begin = (const char *)data;
const char *end = (const char *)data + num;
while (begin < end) {
char curr = begin[0];
if (curr != 'o') {
buf.push_back((char16_t)curr);
}
begin++;
}
} else {
const char16_t *begin = (const char16_t *)data;
const char16_t *end = (const char16_t *)data + num;
while (begin < end) {
char16_t curr = begin[0];
if (curr != 'o') {
buf.push_back(curr);
}
begin++;
}
}
};

String asciiString = String::createFromUtf8(*rt, "foobar");
asciiString.getStringData(*rt, cb);
EXPECT_EQ(buf, u"fbar");
buf.clear();

String utf16Str = String::createFromUtf8(*rt, "👍foobar你好");
utf16Str.getStringData(*rt, cb);
EXPECT_EQ(buf, u"👍fbar你好");
buf.clear();
}

TEST_P(HermesRuntimeTest, GetPropNameIdDataTest) {
std::u16string buf;
auto cb = [&buf](bool ascii, const void *data, size_t num) {
// this callback copies the string content, but removes every 'o' character
if (ascii) {
const char *begin = (const char *)data;
const char *end = (const char *)data + num;
while (begin < end) {
char curr = begin[0];
if (curr != 'o') {
buf.push_back((char16_t)curr);
}
begin++;
}
} else {
const char16_t *begin = (const char16_t *)data;
const char16_t *end = (const char16_t *)data + num;
while (begin < end) {
char16_t curr = begin[0];
if (curr != 'o') {
buf.push_back(curr);
}
begin++;
}
}
};

PropNameID ascii = PropNameID::forAscii(*rt, "foobar");
ascii.getPropNameIdData(*rt, cb);
EXPECT_EQ(buf, u"fbar");
buf.clear();

PropNameID utf16 = PropNameID::forUtf8(*rt, "👍foobar你好");
utf16.getPropNameIdData(*rt, cb);
EXPECT_EQ(buf, u"👍fbar你好");
buf.clear();
}

INSTANTIATE_TEST_CASE_P(
Runtimes,
HermesRuntimeTest,
Expand Down

0 comments on commit c995d19

Please sign in to comment.