-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
n-api: add string api for latin1 encoding and new test cases #12368
Changes from 1 commit
b6d9eee
f506579
4f110e8
c3faab1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1267,6 +1267,25 @@ napi_status napi_create_array_with_length(napi_env env, | |
return GET_RETURN_STATUS(env); | ||
} | ||
|
||
napi_status napi_create_string_latin1(napi_env env, | ||
const char* str, | ||
size_t length, | ||
napi_value* result) { | ||
NAPI_PREAMBLE(env); | ||
CHECK_ARG(env, result); | ||
|
||
auto isolate = env->isolate; | ||
auto str_maybe = | ||
v8::String::NewFromOneByte(isolate, | ||
reinterpret_cast<const uint8_t*>(str), | ||
v8::NewStringType::kInternalized, | ||
length); | ||
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure); | ||
|
||
*result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked()); | ||
return GET_RETURN_STATUS(env); | ||
} | ||
|
||
napi_status napi_create_string_utf8(napi_env env, | ||
const char* str, | ||
size_t length, | ||
|
@@ -1714,6 +1733,39 @@ napi_status napi_get_value_string_length(napi_env env, | |
return GET_RETURN_STATUS(env); | ||
} | ||
|
||
// Copies a JavaScript string into a LATIN-1 string buffer. The result is the | ||
// number of bytes copied into buf, including the null terminator. If bufsize | ||
// is insufficient, the string will be truncated, including a null terminator. | ||
// If buf is NULL, this method returns the length of the string (in bytes) | ||
// via the result parameter. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we clarify here that the length of the string does not include space for the terminator and that you should pass in a buffer of length+1 to avoid truncation ? |
||
// The result argument is optional unless buf is NULL. | ||
napi_status napi_get_value_string_latin1(napi_env env, | ||
napi_value value, | ||
char* buf, | ||
size_t bufsize, | ||
size_t* result) { | ||
NAPI_PREAMBLE(env); | ||
|
||
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value); | ||
RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected); | ||
|
||
if (!buf) { | ||
CHECK_ARG(env, result); | ||
*result = val.As<v8::String>()->Length(); | ||
} else { | ||
int copied = val.As<v8::String>()->WriteOneByte( | ||
reinterpret_cast<uint8_t*>(buf), 0, bufsize - 1, | ||
v8::String::NO_NULL_TERMINATION); | ||
|
||
buf[copied] = '\0'; | ||
if (result != nullptr) { | ||
*result = copied; | ||
} | ||
} | ||
|
||
return GET_RETURN_STATUS(env); | ||
} | ||
|
||
// Copies a JavaScript string into a UTF-8 string buffer. The result is the | ||
// number of bytes copied into buf, including the null terminator. If bufsize | ||
// is insufficient, the string will be truncated, including a null terminator. | ||
|
@@ -1735,8 +1787,10 @@ napi_status napi_get_value_string_utf8(napi_env env, | |
*result = val.As<v8::String>()->Utf8Length(); | ||
} else { | ||
int copied = val.As<v8::String>()->WriteUtf8( | ||
buf, bufsize, nullptr, v8::String::REPLACE_INVALID_UTF8); | ||
buf, bufsize - 1, nullptr, v8::String::REPLACE_INVALID_UTF8 | | ||
v8::String::NO_NULL_TERMINATION); | ||
|
||
buf[copied] = '\0'; | ||
if (result != nullptr) { | ||
*result = copied; | ||
} | ||
|
@@ -1767,8 +1821,10 @@ napi_status napi_get_value_string_utf16(napi_env env, | |
*result = val.As<v8::String>()->Length(); | ||
} else { | ||
int copied = val.As<v8::String>()->Write( | ||
reinterpret_cast<uint16_t*>(buf), 0, bufsize, v8::String::NO_OPTIONS); | ||
reinterpret_cast<uint16_t*>(buf), 0, bufsize - 1, | ||
v8::String::NO_NULL_TERMINATION); | ||
|
||
buf[copied] = '\0'; | ||
if (result != nullptr) { | ||
*result = copied; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,22 +5,47 @@ const assert = require('assert'); | |
// testing api calls for string | ||
const test_string = require(`./build/${common.buildType}/test_string`); | ||
|
||
const empty = ''; | ||
assert.strictEqual(test_string.TestLatin1(empty), empty); | ||
assert.strictEqual(test_string.TestUtf8(empty), empty); | ||
assert.strictEqual(test_string.TestUtf16(empty), empty); | ||
assert.strictEqual(test_string.Length(empty), 0); | ||
assert.strictEqual(test_string.Utf8Length(empty), 0); | ||
|
||
const str1 = 'hello world'; | ||
assert.strictEqual(test_string.Copy(str1), str1); | ||
assert.strictEqual(test_string.TestLatin1(str1), str1); | ||
assert.strictEqual(test_string.TestUtf8(str1), str1); | ||
assert.strictEqual(test_string.TestUtf16(str1), str1); | ||
assert.strictEqual(test_string.TestLatin1Insufficient(str1), str1.slice(0, 3)); | ||
assert.strictEqual(test_string.TestUtf8Insufficient(str1), str1.slice(0, 3)); | ||
assert.strictEqual(test_string.TestUtf16Insufficient(str1), str1.slice(0, 3)); | ||
assert.strictEqual(test_string.Length(str1), 11); | ||
assert.strictEqual(test_string.Utf8Length(str1), 11); | ||
|
||
const str2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||
assert.strictEqual(test_string.Copy(str2), str2); | ||
assert.strictEqual(test_string.TestLatin1(str2), str2); | ||
assert.strictEqual(test_string.TestUtf8(str2), str2); | ||
assert.strictEqual(test_string.TestUtf16(str2), str2); | ||
assert.strictEqual(test_string.TestLatin1Insufficient(str2), str2.slice(0, 3)); | ||
assert.strictEqual(test_string.TestUtf8Insufficient(str2), str2.slice(0, 3)); | ||
assert.strictEqual(test_string.TestUtf16Insufficient(str2), str2.slice(0, 3)); | ||
assert.strictEqual(test_string.Length(str2), 62); | ||
assert.strictEqual(test_string.Utf8Length(str2), 62); | ||
|
||
const str3 = '?!@#$%^&*()_+-=[]{}/.,<>\'"\\'; | ||
assert.strictEqual(test_string.Copy(str3), str3); | ||
assert.strictEqual(test_string.TestLatin1(str3), str3); | ||
assert.strictEqual(test_string.TestUtf8(str3), str3); | ||
assert.strictEqual(test_string.TestUtf16(str3), str3); | ||
assert.strictEqual(test_string.TestLatin1Insufficient(str3), str3.slice(0, 3)); | ||
assert.strictEqual(test_string.TestUtf8Insufficient(str3), str3.slice(0, 3)); | ||
assert.strictEqual(test_string.TestUtf16Insufficient(str3), str3.slice(0, 3)); | ||
assert.strictEqual(test_string.Length(str3), 27); | ||
assert.strictEqual(test_string.Utf8Length(str3), 27); | ||
|
||
const str4 = '\u{2003}\u{2101}\u{2001}'; | ||
assert.strictEqual(test_string.Copy(str4), str4); | ||
assert.strictEqual(test_string.Length(str4), 3); | ||
assert.strictEqual(test_string.Utf8Length(str4), 9); | ||
const str4 = '\u{2003}\u{2101}\u{2001}\u{202}\u{2011}'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Latin1 is not tested here, I assume because these characters are not supported by Latin1 encoding. So then can there be another test case that tests a string with non-ASCII Latin1 characters? (That would also work with UTF8 and UTF16 encodings.) |
||
assert.strictEqual(test_string.TestUtf8(str4), str4); | ||
assert.strictEqual(test_string.TestUtf16(str4), str4); | ||
assert.strictEqual(test_string.TestUtf8Insufficient(str4), str4.slice(0, 1)); | ||
assert.strictEqual(test_string.TestUtf16Insufficient(str4), str4.slice(0, 3)); | ||
assert.strictEqual(test_string.Length(str4), 5); | ||
assert.strictEqual(test_string.Utf8Length(str4), 14); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now the null terminator is not counted in the
result
. I understand that is done for consistency with the usage that passes a null buffer just to get the string length. But then the comments need to be updated on all 3 functions.