Skip to content

Commit

Permalink
Merge pull request #13 from RReverser/buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
toyobayashi authored Jan 6, 2023
2 parents 339caf2 + 67dfc49 commit b2946a5
Show file tree
Hide file tree
Showing 13 changed files with 555 additions and 158 deletions.
230 changes: 115 additions & 115 deletions packages/emnapi/include/napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,16 +731,16 @@ inline bool Value::IsDataView() const {
return result;
}

// inline bool Value::IsBuffer() const {
// if (IsEmpty()) {
// return false;
// }
inline bool Value::IsBuffer() const {
if (IsEmpty()) {
return false;
}

// bool result;
// napi_status status = napi_is_buffer(_env, _value, &result);
// NAPI_THROW_IF_FAILED(_env, status, false);
// return result;
// }
bool result;
napi_status status = napi_is_buffer(_env, _value, &result);
NAPI_THROW_IF_FAILED(_env, status, false);
return result;
}

inline bool Value::IsExternal() const {
return Type() == napi_external;
Expand Down Expand Up @@ -2427,122 +2427,122 @@ inline Promise::Promise(napi_env env, napi_value value) : Object(env, value) {
// Buffer<T> class
////////////////////////////////////////////////////////////////////////////////

// template <typename T>
// inline Buffer<T> Buffer<T>::New(napi_env env, size_t length) {
// napi_value value;
// void* data;
// napi_status status = napi_create_buffer(env, length * sizeof (T), &data, &value);
// NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
// return Buffer(env, value, length, static_cast<T*>(data));
// }
template <typename T>
inline Buffer<T> Buffer<T>::New(napi_env env, size_t length) {
napi_value value;
void* data;
napi_status status = napi_create_buffer(env, length * sizeof (T), &data, &value);
NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
return Buffer(env, value, length, static_cast<T*>(data));
}

// template <typename T>
// inline Buffer<T> Buffer<T>::New(napi_env env, T* data, size_t length) {
// napi_value value;
// napi_status status = napi_create_external_buffer(
// env, length * sizeof (T), data, nullptr, nullptr, &value);
// NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
// return Buffer(env, value, length, data);
// }
template <typename T>
inline Buffer<T> Buffer<T>::New(napi_env env, T* data, size_t length) {
napi_value value;
napi_status status = napi_create_external_buffer(
env, length * sizeof (T), data, nullptr, nullptr, &value);
NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
return Buffer(env, value, length, data);
}

// template <typename T>
// template <typename Finalizer>
// inline Buffer<T> Buffer<T>::New(napi_env env,
// T* data,
// size_t length,
// Finalizer finalizeCallback) {
// napi_value value;
// details::FinalizeData<T, Finalizer>* finalizeData =
// new details::FinalizeData<T, Finalizer>(
// {std::move(finalizeCallback), nullptr});
// napi_status status = napi_create_external_buffer(
// env,
// length * sizeof (T),
// data,
// details::FinalizeData<T, Finalizer>::Wrapper,
// finalizeData,
// &value);
// if (status != napi_ok) {
// delete finalizeData;
// NAPI_THROW_IF_FAILED(env, status, Buffer());
// }
// return Buffer(env, value, length, data);
// }
template <typename T>
template <typename Finalizer>
inline Buffer<T> Buffer<T>::New(napi_env env,
T* data,
size_t length,
Finalizer finalizeCallback) {
napi_value value;
details::FinalizeData<T, Finalizer>* finalizeData =
new details::FinalizeData<T, Finalizer>(
{std::move(finalizeCallback), nullptr});
napi_status status = napi_create_external_buffer(
env,
length * sizeof (T),
data,
details::FinalizeData<T, Finalizer>::Wrapper,
finalizeData,
&value);
if (status != napi_ok) {
delete finalizeData;
NAPI_THROW_IF_FAILED(env, status, Buffer());
}
return Buffer(env, value, length, data);
}

// template <typename T>
// template <typename Finalizer, typename Hint>
// inline Buffer<T> Buffer<T>::New(napi_env env,
// T* data,
// size_t length,
// Finalizer finalizeCallback,
// Hint* finalizeHint) {
// napi_value value;
// details::FinalizeData<T, Finalizer, Hint>* finalizeData =
// new details::FinalizeData<T, Finalizer, Hint>(
// {std::move(finalizeCallback), finalizeHint});
// napi_status status = napi_create_external_buffer(
// env,
// length * sizeof (T),
// data,
// details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
// finalizeData,
// &value);
// if (status != napi_ok) {
// delete finalizeData;
// NAPI_THROW_IF_FAILED(env, status, Buffer());
// }
// return Buffer(env, value, length, data);
// }
template <typename T>
template <typename Finalizer, typename Hint>
inline Buffer<T> Buffer<T>::New(napi_env env,
T* data,
size_t length,
Finalizer finalizeCallback,
Hint* finalizeHint) {
napi_value value;
details::FinalizeData<T, Finalizer, Hint>* finalizeData =
new details::FinalizeData<T, Finalizer, Hint>(
{std::move(finalizeCallback), finalizeHint});
napi_status status = napi_create_external_buffer(
env,
length * sizeof (T),
data,
details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
finalizeData,
&value);
if (status != napi_ok) {
delete finalizeData;
NAPI_THROW_IF_FAILED(env, status, Buffer());
}
return Buffer(env, value, length, data);
}

// template <typename T>
// inline Buffer<T> Buffer<T>::Copy(napi_env env, const T* data, size_t length) {
// napi_value value;
// napi_status status = napi_create_buffer_copy(
// env, length * sizeof (T), data, nullptr, &value);
// NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
// return Buffer<T>(env, value);
// }
template <typename T>
inline Buffer<T> Buffer<T>::Copy(napi_env env, const T* data, size_t length) {
napi_value value;
napi_status status = napi_create_buffer_copy(
env, length * sizeof (T), data, nullptr, &value);
NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
return Buffer<T>(env, value);
}

// template <typename T>
// inline Buffer<T>::Buffer() : Uint8Array(), _length(0), _data(nullptr) {
// }
template <typename T>
inline Buffer<T>::Buffer() : Uint8Array(), _length(0), _data(nullptr) {
}

// template <typename T>
// inline Buffer<T>::Buffer(napi_env env, napi_value value)
// : Uint8Array(env, value), _length(0), _data(nullptr) {
// }
template <typename T>
inline Buffer<T>::Buffer(napi_env env, napi_value value)
: Uint8Array(env, value), _length(0), _data(nullptr) {
}

// template <typename T>
// inline Buffer<T>::Buffer(napi_env env, napi_value value, size_t length, T* data)
// : Uint8Array(env, value), _length(length), _data(data) {
// }
template <typename T>
inline Buffer<T>::Buffer(napi_env env, napi_value value, size_t length, T* data)
: Uint8Array(env, value), _length(length), _data(data) {
}

// template <typename T>
// inline size_t Buffer<T>::Length() const {
// EnsureInfo();
// return _length;
// }
template <typename T>
inline size_t Buffer<T>::Length() const {
EnsureInfo();
return _length;
}

// template <typename T>
// inline T* Buffer<T>::Data() const {
// EnsureInfo();
// return _data;
// }
template <typename T>
inline T* Buffer<T>::Data() const {
EnsureInfo();
return _data;
}

// template <typename T>
// inline void Buffer<T>::EnsureInfo() const {
// // The Buffer instance may have been constructed from a napi_value whose
// // length/data are not yet known. Fetch and cache these values just once,
// // since they can never change during the lifetime of the Buffer.
// if (_data == nullptr) {
// size_t byteLength;
// void* voidData;
// napi_status status = napi_get_buffer_info(_env, _value, &voidData, &byteLength);
// NAPI_THROW_IF_FAILED_VOID(_env, status);
// _length = byteLength / sizeof (T);
// _data = static_cast<T*>(voidData);
// }
// }
template <typename T>
inline void Buffer<T>::EnsureInfo() const {
// The Buffer instance may have been constructed from a napi_value whose
// length/data are not yet known. Fetch and cache these values just once,
// since they can never change during the lifetime of the Buffer.
if (_data == nullptr) {
size_t byteLength;
void* voidData;
napi_status status = napi_get_buffer_info(_env, _value, &voidData, &byteLength);
NAPI_THROW_IF_FAILED_VOID(_env, status);
_length = byteLength / sizeof (T);
_data = static_cast<T*>(voidData);
}
}

////////////////////////////////////////////////////////////////////////////////
// Error class
Expand Down
61 changes: 31 additions & 30 deletions packages/emnapi/include/napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ namespace NAPI_CPP_CUSTOM_NAMESPACE {
bool IsArray() const; ///< Tests if a value is a JavaScript array.
bool IsArrayBuffer() const; ///< Tests if a value is a JavaScript array buffer.
bool IsTypedArray() const; ///< Tests if a value is a JavaScript typed array.
bool IsBuffer() const; ///< Tests if a value is a Node buffer.
bool IsObject() const; ///< Tests if a value is a JavaScript object.
bool IsFunction() const; ///< Tests if a value is a JavaScript function.
bool IsPromise() const; ///< Tests if a value is a JavaScript promise.
Expand Down Expand Up @@ -1414,38 +1415,38 @@ namespace NAPI_CPP_CUSTOM_NAMESPACE {
Promise(napi_env env, napi_value value);
};

// template <typename T>
// class Buffer : public Uint8Array {
// public:
// static Buffer<T> New(napi_env env, size_t length);
// static Buffer<T> New(napi_env env, T* data, size_t length);

// // Finalizer must implement `void operator()(Env env, T* data)`.
// template <typename Finalizer>
// static Buffer<T> New(napi_env env, T* data,
// size_t length,
// Finalizer finalizeCallback);
// // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`.
// template <typename Finalizer, typename Hint>
// static Buffer<T> New(napi_env env, T* data,
// size_t length,
// Finalizer finalizeCallback,
// Hint* finalizeHint);

// static Buffer<T> Copy(napi_env env, const T* data, size_t length);

// Buffer();
// Buffer(napi_env env, napi_value value);
// size_t Length() const;
// T* Data() const;
template <typename T>
class Buffer : public Uint8Array {
public:
static Buffer<T> New(napi_env env, size_t length);
static Buffer<T> New(napi_env env, T* data, size_t length);

// Finalizer must implement `void operator()(Env env, T* data)`.
template <typename Finalizer>
static Buffer<T> New(napi_env env, T* data,
size_t length,
Finalizer finalizeCallback);
// Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`.
template <typename Finalizer, typename Hint>
static Buffer<T> New(napi_env env, T* data,
size_t length,
Finalizer finalizeCallback,
Hint* finalizeHint);

static Buffer<T> Copy(napi_env env, const T* data, size_t length);

Buffer();
Buffer(napi_env env, napi_value value);
size_t Length() const;
T* Data() const;

// private:
// mutable size_t _length;
// mutable T* _data;
private:
mutable size_t _length;
mutable T* _data;

// Buffer(napi_env env, napi_value value, size_t length, T* data);
// void EnsureInfo() const;
// };
Buffer(napi_env env, napi_value value, size_t length, T* data);
void EnsureInfo() const;
};

/// Holds a counted reference to a value; initially a weak reference unless otherwise specified,
/// may be changed to/from a strong reference by adjusting the refcount.
Expand Down
35 changes: 35 additions & 0 deletions packages/emnapi/include/node_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,41 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);

#endif

// Methods to provide node::Buffer functionality with napi types
NAPI_EXTERN napi_status
napi_create_buffer(napi_env env,
size_t length,
void** data,
napi_value* result);

#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
NAPI_EXTERN napi_status
napi_create_external_buffer(napi_env env,
size_t length,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result);
#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED

NAPI_EXTERN napi_status
napi_create_buffer_copy(napi_env env,
size_t length,
const void* data,
void** result_data,
napi_value* result);

NAPI_EXTERN napi_status
napi_is_buffer(napi_env env,
napi_value value,
bool* result);

NAPI_EXTERN napi_status
napi_get_buffer_info(napi_env env,
napi_value value,
void** data,
size_t* length);

#endif

EXTERN_C_END
Expand Down
12 changes: 12 additions & 0 deletions packages/emnapi/src/value-operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,17 @@ function napi_is_typedarray (env: napi_env, value: napi_value, result: Pointer<b
return envObject.clearLastError()
}

function napi_is_buffer(env: napi_env, value: napi_value, result: Pointer<bool>): napi_status {
$CHECK_ENV!(env)
const envObject = emnapiCtx.envStore.get(env)!
$CHECK_ARG!(envObject, value)
$CHECK_ARG!(envObject, result)
const h = emnapiCtx.handleStore.get(value)!
$from64('result')
HEAPU8[result] = h.isBuffer() ? 1 : 0
return envObject.clearLastError()
}

function napi_is_dataview (env: napi_env, value: napi_value, result: Pointer<bool>): napi_status {
$CHECK_ENV!(env)
const envObject = emnapiCtx.envStore.get(env)!
Expand Down Expand Up @@ -267,6 +278,7 @@ emnapiImplement('napi_is_arraybuffer', 'ippp', napi_is_arraybuffer)
emnapiImplement('napi_is_date', 'ippp', napi_is_date)
emnapiImplement('napi_is_error', 'ippp', napi_is_error)
emnapiImplement('napi_is_typedarray', 'ippp', napi_is_typedarray)
emnapiImplement('napi_is_buffer', 'ippp', napi_is_buffer)
emnapiImplement('napi_is_dataview', 'ippp', napi_is_dataview)
emnapiImplement('napi_strict_equals', 'ipppp', napi_strict_equals)
emnapiImplement('napi_detach_arraybuffer', 'ipp', napi_detach_arraybuffer, ['napi_set_last_error'])
Expand Down
Loading

0 comments on commit b2946a5

Please sign in to comment.