Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ include_directories(
add_library(
${PACKAGE_NAME}
SHARED
../cpp/base64.h
../cpp/simdutf.cpp
../cpp/react-native-quick-base64.cpp
../cpp/react-native-quick-base64.h
cpp-adapter.cpp
Expand Down
318 changes: 0 additions & 318 deletions cpp/base64.h

This file was deleted.

40 changes: 36 additions & 4 deletions cpp/react-native-quick-base64.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
#include "react-native-quick-base64.h"
#include "base64.h"
#include "simdutf.h"

#include <algorithm>
#include <iostream>
#include <sstream>

using namespace facebook;

static simdutf::base64_options b64opts(bool url) noexcept {
return url ? simdutf::base64_url : simdutf::base64_default;
}

// Mirrors v8base64::decode (V8 builtins-typed-array.cc lines 513–516).
// loose lastChunkHandling: accepts inputs without '=' padding.
// decode_up_to_bad_char: mirrors V8's ArrayBufferFromBase64 (line 516).
// base64_default_or_url: accepts both standard (+/) and URL-safe (-_) alphabets.
static std::string decode(const std::string& input) {
size_t max_len = simdutf::maximal_binary_length_from_base64(input.data(), input.size());
std::string result(max_len, '\0');
size_t out_len = max_len;
auto r = simdutf::base64_to_binary_safe(
input.data(), input.size(), result.data(), out_len,
simdutf::base64_default_or_url,
simdutf::last_chunk_handling_options::loose,
/*decode_up_to_bad_char*/ true);
if (r.error != simdutf::error_code::SUCCESS) {
throw std::runtime_error("Input is not valid base64-encoded data");
}
result.resize(out_len);
return result;
}

// Returns false if the passed value is not a string or an ArrayBuffer.
bool valueToString(jsi::Runtime& runtime, const jsi::Value& value, std::string* str) {
if (value.isString()) {
Expand Down Expand Up @@ -43,7 +67,10 @@ void installBase64(jsi::Runtime& jsiRuntime) {
url = arguments[1].asBool();
}
try {
std::string strBase64 = base64_encode(str, url);
auto opts = b64opts(url);
std::string strBase64(simdutf::base64_length_from_binary(str.size(), opts), '\0');
auto outlen = simdutf::binary_to_base64(str.data(), str.size(), strBase64.data(), opts);
strBase64.resize(outlen);
return jsi::Value(jsi::String::createFromUtf8(runtime, strBase64));
} catch (const std::runtime_error& error) {
throw jsi::JSError(runtime, error.what());
Expand All @@ -69,7 +96,12 @@ void installBase64(jsi::Runtime& jsiRuntime) {
removeLinebreaks = arguments[1].asBool();
}
try {
std::string str = base64_decode(strBase64, removeLinebreaks);
if (removeLinebreaks) {
strBase64.erase(std::remove(strBase64.begin(), strBase64.end(), '\n'), strBase64.end());
} else if (strBase64.find('\n') != std::string::npos) {
throw std::runtime_error("Input is not valid base64-encoded data");
}
std::string str = decode(strBase64);
jsi::Function arrayBufferCtor = runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer");
jsi::Object o = arrayBufferCtor.callAsConstructor(runtime, (int)str.length()).getObject(runtime);
jsi::ArrayBuffer buf = o.getArrayBuffer(runtime);
Expand Down
Loading