react / wstein / node_modules / jest-cli / node_modules / jsdom / node_modules / contextify / node_modules / nan / nan_string_bytes.h
81145 views// Copyright Joyent, Inc. and other Node contributors.1//2// Permission is hereby granted, free of charge, to any person obtaining a3// copy of this software and associated documentation files (the4// "Software"), to deal in the Software without restriction, including5// without limitation the rights to use, copy, modify, merge, publish,6// distribute, sublicense, and/or sell copies of the Software, and to permit7// persons to whom the Software is furnished to do so, subject to the8// following conditions:9//10// The above copyright notice and this permission notice shall be included11// in all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF15// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN16// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,17// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19// USE OR OTHER DEALINGS IN THE SOFTWARE.2021#ifndef NAN_STRING_BYTES_H_22#define NAN_STRING_BYTES_H_2324// Decodes a v8::Handle<v8::String> or Buffer to a raw char*2526#include <node.h>27#include <node_buffer.h>28#include <assert.h>29#include <string.h> // memcpy30#include <limits.h>3132namespace NanIntern {3334using v8::Local;35using v8::Handle;36using v8::Object;37using v8::String;38using v8::Value;394041//// Base 64 ////4243#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4)44454647//// Nan::HEX ////4849static bool contains_non_ascii_slow(const char* buf, size_t len) {50for (size_t i = 0; i < len; ++i) {51if (buf[i] & 0x80) return true;52}53return false;54}555657static bool contains_non_ascii(const char* src, size_t len) {58if (len < 16) {59return contains_non_ascii_slow(src, len);60}6162const unsigned bytes_per_word = sizeof(void*);63const unsigned align_mask = bytes_per_word - 1;64const unsigned unaligned = reinterpret_cast<uintptr_t>(src) & align_mask;6566if (unaligned > 0) {67const unsigned n = bytes_per_word - unaligned;68if (contains_non_ascii_slow(src, n)) return true;69src += n;70len -= n;71}727374#if defined(__x86_64__) || defined(_WIN64)75const uintptr_t mask = 0x8080808080808080ll;76#else77const uintptr_t mask = 0x80808080l;78#endif7980const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);8182for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {83if (srcw[i] & mask) return true;84}8586const unsigned remainder = len & align_mask;87if (remainder > 0) {88const size_t offset = len - remainder;89if (contains_non_ascii_slow(src + offset, remainder)) return true;90}9192return false;93}949596static void force_ascii_slow(const char* src, char* dst, size_t len) {97for (size_t i = 0; i < len; ++i) {98dst[i] = src[i] & 0x7f;99}100}101102103static void force_ascii(const char* src, char* dst, size_t len) {104if (len < 16) {105force_ascii_slow(src, dst, len);106return;107}108109const unsigned bytes_per_word = sizeof(void*);110const unsigned align_mask = bytes_per_word - 1;111const unsigned src_unalign = reinterpret_cast<uintptr_t>(src) & align_mask;112const unsigned dst_unalign = reinterpret_cast<uintptr_t>(dst) & align_mask;113114if (src_unalign > 0) {115if (src_unalign == dst_unalign) {116const unsigned unalign = bytes_per_word - src_unalign;117force_ascii_slow(src, dst, unalign);118src += unalign;119dst += unalign;120len -= src_unalign;121} else {122force_ascii_slow(src, dst, len);123return;124}125}126127#if defined(__x86_64__) || defined(_WIN64)128const uintptr_t mask = ~0x8080808080808080ll;129#else130const uintptr_t mask = ~0x80808080l;131#endif132133const uintptr_t* srcw = reinterpret_cast<const uintptr_t*>(src);134uintptr_t* dstw = reinterpret_cast<uintptr_t*>(dst);135136for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) {137dstw[i] = srcw[i] & mask;138}139140const unsigned remainder = len & align_mask;141if (remainder > 0) {142const size_t offset = len - remainder;143force_ascii_slow(src + offset, dst + offset, remainder);144}145}146147148static size_t base64_encode(const char* src,149size_t slen,150char* dst,151size_t dlen) {152// We know how much we'll write, just make sure that there's space.153assert(dlen >= base64_encoded_size(slen) &&154"not enough space provided for base64 encode");155156dlen = base64_encoded_size(slen);157158unsigned a;159unsigned b;160unsigned c;161unsigned i;162unsigned k;163unsigned n;164165static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"166"abcdefghijklmnopqrstuvwxyz"167"0123456789+/";168169i = 0;170k = 0;171n = slen / 3 * 3;172173while (i < n) {174a = src[i + 0] & 0xff;175b = src[i + 1] & 0xff;176c = src[i + 2] & 0xff;177178dst[k + 0] = table[a >> 2];179dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];180dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)];181dst[k + 3] = table[c & 0x3f];182183i += 3;184k += 4;185}186187if (n != slen) {188switch (slen - n) {189case 1:190a = src[i + 0] & 0xff;191dst[k + 0] = table[a >> 2];192dst[k + 1] = table[(a & 3) << 4];193dst[k + 2] = '=';194dst[k + 3] = '=';195break;196197case 2:198a = src[i + 0] & 0xff;199b = src[i + 1] & 0xff;200dst[k + 0] = table[a >> 2];201dst[k + 1] = table[((a & 3) << 4) | (b >> 4)];202dst[k + 2] = table[(b & 0x0f) << 2];203dst[k + 3] = '=';204break;205}206}207208return dlen;209}210211212static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) {213// We know how much we'll write, just make sure that there's space.214assert(dlen >= slen * 2 &&215"not enough space provided for hex encode");216217dlen = slen * 2;218for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) {219static const char hex[] = "0123456789abcdef";220uint8_t val = static_cast<uint8_t>(src[i]);221dst[k + 0] = hex[val >> 4];222dst[k + 1] = hex[val & 15];223}224225return dlen;226}227228229230static Local<Value> Encode(const char* buf,231size_t buflen,232enum Nan::Encoding encoding) {233assert(buflen <= node::Buffer::kMaxLength);234if (!buflen && encoding != Nan::BUFFER)235return NanNew("");236237Local<String> val;238switch (encoding) {239case Nan::BUFFER:240return NanNewBufferHandle(buf, buflen);241242case Nan::ASCII:243if (contains_non_ascii(buf, buflen)) {244char* out = new char[buflen];245force_ascii(buf, out, buflen);246val = NanNew<String>(out, buflen);247delete[] out;248} else {249val = NanNew<String>(buf, buflen);250}251break;252253case Nan::UTF8:254val = NanNew<String>(buf, buflen);255break;256257case Nan::BINARY: {258// TODO(isaacs) use ExternalTwoByteString?259const unsigned char *cbuf = reinterpret_cast<const unsigned char*>(buf);260uint16_t * twobytebuf = new uint16_t[buflen];261for (size_t i = 0; i < buflen; i++) {262// XXX is the following line platform independent?263twobytebuf[i] = cbuf[i];264}265val = NanNew<String>(twobytebuf, buflen);266delete[] twobytebuf;267break;268}269270case Nan::BASE64: {271size_t dlen = base64_encoded_size(buflen);272char* dst = new char[dlen];273274size_t written = base64_encode(buf, buflen, dst, dlen);275assert(written == dlen);276277val = NanNew<String>(dst, dlen);278delete[] dst;279break;280}281282case Nan::UCS2: {283const uint16_t* data = reinterpret_cast<const uint16_t*>(buf);284val = NanNew<String>(data, buflen / 2);285break;286}287288case Nan::HEX: {289size_t dlen = buflen * 2;290char* dst = new char[dlen];291size_t written = hex_encode(buf, buflen, dst, dlen);292assert(written == dlen);293294val = NanNew<String>(dst, dlen);295delete[] dst;296break;297}298299default:300assert(0 && "unknown encoding");301break;302}303304return val;305}306307#undef base64_encoded_size308309} // namespace NanIntern310311#endif // NAN_STRING_BYTES_H_312313314