#include "stream_encode.h"
#include "stream_encode_worker.h"
using namespace v8;
StreamEncode::StreamEncode(bool isAsync, Local<Object> params): isAsync(isAsync) {
state = BrotliEncoderCreateInstance(Allocator::Alloc, Allocator::Free, &alloc);
Local<String> key;
Local<Value> localVal;
uint32_t val;
key = Nan::New<String>("mode").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_MODE, val);
}
key = Nan::New<String>("quality").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, val);
}
key = Nan::New<String>("lgwin").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN, val);
}
key = Nan::New<String>("lgblock").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_LGBLOCK, val);
}
key = Nan::New<String>("disable_literal_context_modeling").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, val);
}
key = Nan::New<String>("size_hint").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_SIZE_HINT, val);
}
key = Nan::New<String>("large_window").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW, val);
}
key = Nan::New<String>("npostfix").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_NPOSTFIX, val);
}
key = Nan::New<String>("ndirect").ToLocalChecked();
if (Nan::Has(params, key).FromJust()) {
localVal = Nan::Get(params, key).ToLocalChecked();
val = Nan::To<uint32_t>(localVal).FromJust();
BrotliEncoderSetParameter(state, BROTLI_PARAM_NDIRECT, val);
}
}
StreamEncode::~StreamEncode() {
BrotliEncoderDestroyInstance(state);
}
void StreamEncode::Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("StreamEncode").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Nan::SetPrototypeMethod(tpl, "transform", Transform);
Nan::SetPrototypeMethod(tpl, "flush", Flush);
constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
Nan::Set(target, Nan::New("StreamEncode").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
NAN_METHOD(StreamEncode::New) {
StreamEncode* obj = new StreamEncode(
Nan::To<bool>(info[0]).FromJust(),
Nan::To<Object>(info[1]).ToLocalChecked()
);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(StreamEncode::Transform) {
StreamEncode* obj = ObjectWrap::Unwrap<StreamEncode>(info.Holder());
Local<Object> buffer = Nan::To<Object>(info[0]).ToLocalChecked();
obj->next_in = (const uint8_t*) node::Buffer::Data(buffer);
obj->available_in = node::Buffer::Length(buffer);
Nan::Callback *callback = new Nan::Callback(info[1].As<Function>());
StreamEncodeWorker *worker = new StreamEncodeWorker(callback, obj, BROTLI_OPERATION_PROCESS);
if (obj->isAsync) {
Nan::AsyncQueueWorker(worker);
} else {
worker->Execute();
worker->WorkComplete();
worker->Destroy();
}
}
NAN_METHOD(StreamEncode::Flush) {
StreamEncode* obj = ObjectWrap::Unwrap<StreamEncode>(info.Holder());
Nan::Callback *callback = new Nan::Callback(info[1].As<Function>());
BrotliEncoderOperation op = Nan::To<bool>(info[0]).FromJust()
? BROTLI_OPERATION_FINISH
: BROTLI_OPERATION_FLUSH;
obj->next_in = nullptr;
obj->available_in = 0;
StreamEncodeWorker *worker = new StreamEncodeWorker(callback, obj, op);
if (obj->isAsync) {
Nan::AsyncQueueWorker(worker);
} else {
worker->Execute();
worker->WorkComplete();
worker->Destroy();
}
}
Nan::Persistent<Function> StreamEncode::constructor;