mirror of https://github.com/nodejs/node.git
n-api: add string api for latin1 encoding
PR-URL: https://github.com/nodejs/node/pull/12368 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jason Ginchereau <jasongin@microsoft.com>pull/12313/merge
parent
47c255ef68
commit
ad5f987558
|
@ -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,9 +1733,46 @@ 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 (excluding the null terminator) copied into buf.
|
||||
// A sufficient buffer size should be greater than the length of string,
|
||||
// reserving space for null terminator.
|
||||
// If bufsize is insufficient, the string will be truncated and null terminated.
|
||||
// If buf is NULL, this method returns the length of the string (in bytes)
|
||||
// via the result parameter.
|
||||
// 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.
|
||||
// number of bytes (excluding the null terminator) copied into buf.
|
||||
// A sufficient buffer size should be greater than the length of string,
|
||||
// reserving space for null terminator.
|
||||
// If bufsize is insufficient, the string will be truncated and null terminated.
|
||||
// If buf is NULL, this method returns the length of the string (in bytes)
|
||||
// via the result parameter.
|
||||
// The result argument is optional unless buf is NULL.
|
||||
|
@ -1735,8 +1791,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;
|
||||
}
|
||||
|
@ -1746,10 +1804,12 @@ napi_status napi_get_value_string_utf8(napi_env env,
|
|||
}
|
||||
|
||||
// Copies a JavaScript string into a UTF-16 string buffer. The result is the
|
||||
// number of 2-byte code units 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 2-byte code units) via the result parameter.
|
||||
// number of 2-byte code units (excluding the null terminator) copied into buf.
|
||||
// A sufficient buffer size should be greater than the length of string,
|
||||
// reserving space for null terminator.
|
||||
// If bufsize is insufficient, the string will be truncated and null terminated.
|
||||
// If buf is NULL, this method returns the length of the string (in 2-byte
|
||||
// code units) via the result parameter.
|
||||
// The result argument is optional unless buf is NULL.
|
||||
napi_status napi_get_value_string_utf16(napi_env env,
|
||||
napi_value value,
|
||||
|
@ -1767,8 +1827,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;
|
||||
}
|
||||
|
|
|
@ -121,6 +121,10 @@ NAPI_EXTERN napi_status napi_create_array_with_length(napi_env env,
|
|||
NAPI_EXTERN napi_status napi_create_number(napi_env env,
|
||||
double value,
|
||||
napi_value* result);
|
||||
NAPI_EXTERN napi_status napi_create_string_latin1(napi_env env,
|
||||
const char* str,
|
||||
size_t length,
|
||||
napi_value* result);
|
||||
NAPI_EXTERN napi_status napi_create_string_utf8(napi_env env,
|
||||
const char* str,
|
||||
size_t length,
|
||||
|
@ -172,6 +176,13 @@ NAPI_EXTERN napi_status napi_get_value_string_length(napi_env env,
|
|||
napi_value value,
|
||||
size_t* result);
|
||||
|
||||
// Copies LATIN-1 encoded bytes from a string into a buffer.
|
||||
NAPI_EXTERN napi_status napi_get_value_string_latin1(napi_env env,
|
||||
napi_value value,
|
||||
char* buf,
|
||||
size_t bufsize,
|
||||
size_t* result);
|
||||
|
||||
// Copies UTF-8 encoded bytes from a string into a buffer.
|
||||
NAPI_EXTERN napi_status napi_get_value_string_utf8(napi_env env,
|
||||
napi_value value,
|
||||
|
|
|
@ -5,22 +5,67 @@ 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 = '¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿';
|
||||
assert.strictEqual(test_string.TestLatin1(str4), str4);
|
||||
assert.strictEqual(test_string.TestUtf8(str4), str4);
|
||||
assert.strictEqual(test_string.TestUtf16(str4), str4);
|
||||
assert.strictEqual(test_string.TestLatin1Insufficient(str4), str4.slice(0, 3));
|
||||
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), 31);
|
||||
assert.strictEqual(test_string.Utf8Length(str4), 62);
|
||||
|
||||
const str5 = 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ';
|
||||
assert.strictEqual(test_string.TestLatin1(str5), str5);
|
||||
assert.strictEqual(test_string.TestUtf8(str5), str5);
|
||||
assert.strictEqual(test_string.TestUtf16(str5), str5);
|
||||
assert.strictEqual(test_string.TestLatin1Insufficient(str5), str5.slice(0, 3));
|
||||
assert.strictEqual(test_string.TestUtf8Insufficient(str5), str5.slice(0, 1));
|
||||
assert.strictEqual(test_string.TestUtf16Insufficient(str5), str5.slice(0, 3));
|
||||
assert.strictEqual(test_string.Length(str5), 63);
|
||||
assert.strictEqual(test_string.Utf8Length(str5), 126);
|
||||
|
||||
const str6 = '\u{2003}\u{2101}\u{2001}\u{202}\u{2011}';
|
||||
assert.strictEqual(test_string.TestUtf8(str6), str6);
|
||||
assert.strictEqual(test_string.TestUtf16(str6), str6);
|
||||
assert.strictEqual(test_string.TestUtf8Insufficient(str6), str6.slice(0, 1));
|
||||
assert.strictEqual(test_string.TestUtf16Insufficient(str6), str6.slice(0, 3));
|
||||
assert.strictEqual(test_string.Length(str6), 5);
|
||||
assert.strictEqual(test_string.Utf8Length(str6), 14);
|
||||
|
|
|
@ -1,7 +1,33 @@
|
|||
#include <node_api.h>
|
||||
#include "../common.h"
|
||||
|
||||
napi_value Copy(napi_env env, napi_callback_info info) {
|
||||
napi_value TestLatin1(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
|
||||
|
||||
NAPI_ASSERT(env, valuetype == napi_string,
|
||||
"Wrong type of argment. Expects a string.");
|
||||
|
||||
char buffer[128];
|
||||
size_t buffer_size = 128;
|
||||
size_t copied;
|
||||
|
||||
NAPI_CALL(env,
|
||||
napi_get_value_string_latin1(env, args[0], buffer, buffer_size, &copied));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_string_latin1(env, buffer, copied, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
napi_value TestUtf8(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
@ -22,7 +48,111 @@ napi_value Copy(napi_env env, napi_callback_info info) {
|
|||
napi_get_value_string_utf8(env, args[0], buffer, buffer_size, &copied));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_string_utf8(env, buffer, copied-1, &output));
|
||||
NAPI_CALL(env, napi_create_string_utf8(env, buffer, copied, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
napi_value TestUtf16(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
|
||||
|
||||
NAPI_ASSERT(env, valuetype == napi_string,
|
||||
"Wrong type of argment. Expects a string.");
|
||||
|
||||
char16_t buffer[128];
|
||||
size_t buffer_size = 128;
|
||||
size_t copied;
|
||||
|
||||
NAPI_CALL(env,
|
||||
napi_get_value_string_utf16(env, args[0], buffer, buffer_size, &copied));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_string_utf16(env, buffer, copied, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
napi_value TestLatin1Insufficient(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
|
||||
|
||||
NAPI_ASSERT(env, valuetype == napi_string,
|
||||
"Wrong type of argment. Expects a string.");
|
||||
|
||||
char buffer[4];
|
||||
size_t buffer_size = 4;
|
||||
size_t copied;
|
||||
|
||||
NAPI_CALL(env,
|
||||
napi_get_value_string_latin1(env, args[0], buffer, buffer_size, &copied));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_string_latin1(env, buffer, copied, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
napi_value TestUtf8Insufficient(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
|
||||
|
||||
NAPI_ASSERT(env, valuetype == napi_string,
|
||||
"Wrong type of argment. Expects a string.");
|
||||
|
||||
char buffer[4];
|
||||
size_t buffer_size = 4;
|
||||
size_t copied;
|
||||
|
||||
NAPI_CALL(env,
|
||||
napi_get_value_string_utf8(env, args[0], buffer, buffer_size, &copied));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_string_utf8(env, buffer, copied, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
napi_value TestUtf16Insufficient(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
|
||||
|
||||
NAPI_ASSERT(env, valuetype == napi_string,
|
||||
"Wrong type of argment. Expects a string.");
|
||||
|
||||
char16_t buffer[4];
|
||||
size_t buffer_size = 4;
|
||||
size_t copied;
|
||||
|
||||
NAPI_CALL(env,
|
||||
napi_get_value_string_utf16(env, args[0], buffer, buffer_size, &copied));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_string_utf16(env, buffer, copied, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -73,7 +203,12 @@ napi_value Utf8Length(napi_env env, napi_callback_info info) {
|
|||
|
||||
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
|
||||
napi_property_descriptor properties[] = {
|
||||
DECLARE_NAPI_PROPERTY("Copy", Copy),
|
||||
DECLARE_NAPI_PROPERTY("TestLatin1", TestLatin1),
|
||||
DECLARE_NAPI_PROPERTY("TestLatin1Insufficient", TestLatin1Insufficient),
|
||||
DECLARE_NAPI_PROPERTY("TestUtf8", TestUtf8),
|
||||
DECLARE_NAPI_PROPERTY("TestUtf8Insufficient", TestUtf8Insufficient),
|
||||
DECLARE_NAPI_PROPERTY("TestUtf16", TestUtf16),
|
||||
DECLARE_NAPI_PROPERTY("TestUtf16Insufficient", TestUtf16Insufficient),
|
||||
DECLARE_NAPI_PROPERTY("Length", Length),
|
||||
DECLARE_NAPI_PROPERTY("Utf8Length", Utf8Length),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue