diff options
Diffstat (limited to 'src/node_file.h')
-rw-r--r-- | src/node_file.h | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/src/node_file.h b/src/node_file.h index 31242e1a1b..96f8221520 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -148,6 +148,92 @@ class FSReqCallback : public FSReqBase { DISALLOW_COPY_AND_ASSIGN(FSReqCallback); }; +// Wordaround a GCC4.9 bug that C++14 N3652 was not implemented +// Refs: https://www.gnu.org/software/gcc/projects/cxx-status.html#cxx14 +// Refs: https://isocpp.org/files/papers/N3652.html +#if __cpp_constexpr < 201304 +# define constexpr inline +#endif + +template <typename NativeT, + // SFINAE limit NativeT to arithmetic types + typename = std::enable_if<std::is_arithmetic<NativeT>::value>> +constexpr NativeT ToNative(uv_timespec_t ts) { + // This template has exactly two specializations below. + static_assert(std::is_arithmetic<NativeT>::value == false, "Not implemented"); + UNREACHABLE(); +} + +template <> +constexpr double ToNative(uv_timespec_t ts) { + // We need to do a static_cast since the original FS values are ulong. + /* NOLINTNEXTLINE(runtime/int) */ + const auto u_sec = static_cast<unsigned long>(ts.tv_sec); + const double full_sec = u_sec * 1000.0; + /* NOLINTNEXTLINE(runtime/int) */ + const auto u_nsec = static_cast<unsigned long>(ts.tv_nsec); + const double full_nsec = u_nsec / 1000'000.0; + return full_sec + full_nsec; +} + +template <> +constexpr uint64_t ToNative(uv_timespec_t ts) { + // We need to do a static_cast since the original FS values are ulong. + /* NOLINTNEXTLINE(runtime/int) */ + const auto u_sec = static_cast<unsigned long>(ts.tv_sec); + const auto full_sec = static_cast<uint64_t>(u_sec) * 1000UL; + /* NOLINTNEXTLINE(runtime/int) */ + const auto u_nsec = static_cast<unsigned long>(ts.tv_nsec); + const auto full_nsec = static_cast<uint64_t>(u_nsec) / 1000'000UL; + return full_sec + full_nsec; +} + +#undef constexpr // end N3652 bug workaround + +template <typename NativeT, typename V8T> +constexpr void FillStatsArray(AliasedBuffer<NativeT, V8T>* fields, + const uv_stat_t* s, const size_t offset = 0) { + fields->SetValue(offset + 0, s->st_dev); + fields->SetValue(offset + 1, s->st_mode); + fields->SetValue(offset + 2, s->st_nlink); + fields->SetValue(offset + 3, s->st_uid); + fields->SetValue(offset + 4, s->st_gid); + fields->SetValue(offset + 5, s->st_rdev); +#if defined(__POSIX__) + fields->SetValue(offset + 6, s->st_blksize); +#else + fields->SetValue(offset + 6, 0); +#endif + fields->SetValue(offset + 7, s->st_ino); + fields->SetValue(offset + 8, s->st_size); +#if defined(__POSIX__) + fields->SetValue(offset + 9, s->st_blocks); +#else + fields->SetValue(offset + 9, 0); +#endif +// Dates. + fields->SetValue(offset + 10, ToNative<NativeT>(s->st_atim)); + fields->SetValue(offset + 11, ToNative<NativeT>(s->st_mtim)); + fields->SetValue(offset + 12, ToNative<NativeT>(s->st_ctim)); + fields->SetValue(offset + 13, ToNative<NativeT>(s->st_birthtim)); +} + +inline Local<Value> FillGlobalStatsArray(Environment* env, + const bool use_bigint, + const uv_stat_t* s, + const bool second = false) { + const ptrdiff_t offset = second ? kFsStatsFieldsNumber : 0; + if (use_bigint) { + auto* const arr = env->fs_stats_field_bigint_array(); + FillStatsArray(arr, s, offset); + return arr->GetJSArray(); + } else { + auto* const arr = env->fs_stats_field_array(); + FillStatsArray(arr, s, offset); + return arr->GetJSArray(); + } +} + template <typename NativeT = double, typename V8T = v8::Float64Array> class FSReqPromise : public FSReqBase { public: @@ -157,7 +243,7 @@ class FSReqPromise : public FSReqBase { ->NewInstance(env->context()).ToLocalChecked(), AsyncWrap::PROVIDER_FSREQPROMISE, use_bigint), - stats_field_array_(env->isolate(), env->kFsStatsFieldsLength) { + stats_field_array_(env->isolate(), kFsStatsFieldsNumber) { auto resolver = Promise::Resolver::New(env->context()).ToLocalChecked(); object()->Set(env->context(), env->promise_string(), resolver).FromJust(); @@ -191,7 +277,8 @@ class FSReqPromise : public FSReqBase { } void ResolveStat(const uv_stat_t* stat) override { - Resolve(node::FillStatsArray(&stats_field_array_, stat)); + FillStatsArray(&stats_field_array_, stat); + Resolve(stats_field_array_.GetJSArray()); } void SetReturnValue(const FunctionCallbackInfo<Value>& args) override { |