From e8eaaa772414e6193702f3933cbee919d6fcdc95 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 11 Oct 2016 14:12:31 -0700 Subject: buffer: add buffer.transcode Add buffer.transcode(source, from, to) method. Primarily uses ICU to transcode a buffer's content from one of Node.js' supported encodings to another. Originally part of a proposal to add a new unicode module. Decided to refactor the approach towrds individual PRs without a new module. Refs: https://github.com/nodejs/node/pull/8075 PR-URL: https://github.com/nodejs/node/pull/9038 Reviewed-By: Anna Henningsen --- src/node_buffer.cc | 55 +++++++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 36 deletions(-) (limited to 'src/node_buffer.cc') diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 07a4106642..540de1827f 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -22,23 +22,6 @@ if (!(r)) return env->ThrowRangeError("out of range index"); \ } while (0) -#define THROW_AND_RETURN_UNLESS_BUFFER(env, obj) \ - do { \ - if (!HasInstance(obj)) \ - return env->ThrowTypeError("argument should be a Buffer"); \ - } while (0) - -#define SPREAD_ARG(val, name) \ - CHECK((val)->IsUint8Array()); \ - Local name = (val).As(); \ - ArrayBuffer::Contents name##_c = name->Buffer()->GetContents(); \ - const size_t name##_offset = name->ByteOffset(); \ - const size_t name##_length = name->ByteLength(); \ - char* const name##_data = \ - static_cast(name##_c.Data()) + name##_offset; \ - if (name##_length > 0) \ - CHECK_NE(name##_data, nullptr); - #define SLICE_START_END(start_arg, end_arg, end_max) \ size_t start; \ size_t end; \ @@ -448,7 +431,7 @@ void StringSlice(const FunctionCallbackInfo& args) { Isolate* isolate = env->isolate(); THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); - SPREAD_ARG(args.This(), ts_obj); + SPREAD_BUFFER_ARG(args.This(), ts_obj); if (ts_obj_length == 0) return args.GetReturnValue().SetEmptyString(); @@ -465,7 +448,7 @@ void StringSlice(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); - SPREAD_ARG(args.This(), ts_obj); + SPREAD_BUFFER_ARG(args.This(), ts_obj); if (ts_obj_length == 0) return args.GetReturnValue().SetEmptyString(); @@ -543,8 +526,8 @@ void Copy(const FunctionCallbackInfo &args) { THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); Local target_obj = args[0].As(); - SPREAD_ARG(args.This(), ts_obj); - SPREAD_ARG(target_obj, target); + SPREAD_BUFFER_ARG(args.This(), ts_obj); + SPREAD_BUFFER_ARG(target_obj, target); size_t target_start; size_t source_start; @@ -577,7 +560,7 @@ void Fill(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); size_t start = args[2]->Uint32Value(); size_t end = args[3]->Uint32Value(); @@ -590,7 +573,7 @@ void Fill(const FunctionCallbackInfo& args) { // First check if Buffer has been passed. if (Buffer::HasInstance(args[1])) { - SPREAD_ARG(args[1], fill_obj); + SPREAD_BUFFER_ARG(args[1], fill_obj); str_length = fill_obj_length; memcpy(ts_obj_data + start, fill_obj_data, MIN(str_length, fill_length)); goto start_fill; @@ -669,7 +652,7 @@ void StringWrite(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); - SPREAD_ARG(args.This(), ts_obj); + SPREAD_BUFFER_ARG(args.This(), ts_obj); if (!args[0]->IsString()) return env->ThrowTypeError("Argument must be a string"); @@ -747,7 +730,7 @@ static inline void Swizzle(char* start, unsigned int len) { template void ReadFloatGeneric(const FunctionCallbackInfo& args) { THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); uint32_t offset = args[1]->Uint32Value(); CHECK_LE(offset + sizeof(T), ts_obj_length); @@ -881,8 +864,8 @@ void CompareOffset(const FunctionCallbackInfo &args) { THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); THROW_AND_RETURN_UNLESS_BUFFER(env, args[1]); - SPREAD_ARG(args[0], ts_obj); - SPREAD_ARG(args[1], target); + SPREAD_BUFFER_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[1], target); size_t target_start; size_t source_start; @@ -921,8 +904,8 @@ void Compare(const FunctionCallbackInfo &args) { THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); THROW_AND_RETURN_UNLESS_BUFFER(env, args[1]); - SPREAD_ARG(args[0], obj_a); - SPREAD_ARG(args[1], obj_b); + SPREAD_BUFFER_ARG(args[0], obj_a); + SPREAD_BUFFER_ARG(args[1], obj_b); size_t cmp_length = MIN(obj_a_length, obj_b_length); @@ -977,7 +960,7 @@ void IndexOfString(const FunctionCallbackInfo& args) { UTF8); THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); Local needle = args[1].As(); int64_t offset_i64 = args[2]->IntegerValue(); @@ -1084,8 +1067,8 @@ void IndexOfBuffer(const FunctionCallbackInfo& args) { THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]); THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[1]); - SPREAD_ARG(args[0], ts_obj); - SPREAD_ARG(args[1], buf); + SPREAD_BUFFER_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[1], buf); int64_t offset_i64 = args[2]->IntegerValue(); bool is_forward = args[4]->IsTrue(); @@ -1143,7 +1126,7 @@ void IndexOfNumber(const FunctionCallbackInfo& args) { ASSERT(args[3]->IsBoolean()); THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); uint32_t needle = args[1]->Uint32Value(); int64_t offset_i64 = args[2]->IntegerValue(); @@ -1171,7 +1154,7 @@ void IndexOfNumber(const FunctionCallbackInfo& args) { void Swap16(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); SwapBytes16(ts_obj_data, ts_obj_length); args.GetReturnValue().Set(args[0]); } @@ -1180,7 +1163,7 @@ void Swap16(const FunctionCallbackInfo& args) { void Swap32(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); SwapBytes32(ts_obj_data, ts_obj_length); args.GetReturnValue().Set(args[0]); } @@ -1189,7 +1172,7 @@ void Swap32(const FunctionCallbackInfo& args) { void Swap64(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); - SPREAD_ARG(args[0], ts_obj); + SPREAD_BUFFER_ARG(args[0], ts_obj); SwapBytes64(ts_obj_data, ts_obj_length); args.GetReturnValue().Set(args[0]); } -- cgit v1.2.3