diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index 194ea2ece15dd5d9e74ab7fb548646aa7595d337..3189321612d37b7013da20a8bb7c2629109ca481 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -160,6 +160,7 @@ ohos_shared_library("fs") { include_dirs += [ "${file_api_path}/interfaces/kits/rust/include" ] sources += [ "src/mod_fs/class_randomaccessfile/randomaccessfile_n_exporter.cpp", + "src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp", "src/mod_fs/class_stream/flush.cpp", "src/mod_fs/class_stream/stream_n_exporter.cpp", "src/mod_fs/class_watcher/watcher_entity.cpp", @@ -174,6 +175,7 @@ ohos_shared_library("fs") { "src/mod_fs/properties/lseek.cpp", "src/mod_fs/properties/move.cpp", "src/mod_fs/properties/movedir.cpp", + "src/mod_fs/properties/read_lines.cpp", "src/mod_fs/properties/read_text.cpp", "src/mod_fs/properties/symlink.cpp", "src/mod_fs/properties/watcher.cpp", diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_entity.h b/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_entity.h new file mode 100644 index 0000000000000000000000000000000000000000..ff8a2c9c75f3b6a1f5f66379d13b7aa4aa109208 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_entity.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_ENTITY_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_ENTITY_H + +#include "filemgmt_libhilog.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +struct ReaderIteratorEntity { + void *iterator = nullptr; + int64_t offset = 0; +}; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_ENTITY_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7ee0c856f60799cbfbb2f0cf0fc6ce2e468b2cc --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "readeriterator_n_exporter.h" + +#include "filemgmt_libhilog.h" +#include "file_utils.h" +#include "readeriterator_entity.h" +#include "rust_file.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +napi_value ReaderIteratorNExporter::Constructor(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto readerIteratorEntity = CreateUniquePtr(); + if (readerIteratorEntity == nullptr) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), move(readerIteratorEntity))) { + HILOGE("Failed to set reader iterator entity"); + NError(UNKROWN_ERR).ThrowErr(env); + return nullptr; + } + return funcArg.GetThisVar(); +} + +napi_value ReaderIteratorNExporter::Next(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + auto readerIteratorEntity = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!readerIteratorEntity) { + HILOGE("Failed to get reader iterator entity"); + NError(UNKROWN_ERR).ThrowErr(env); + return nullptr; + } + + Str *str = NextLine(readerIteratorEntity->iterator); + if (str == nullptr && readerIteratorEntity->offset != 0) { + HILOGE("Failed to get next line, error:%{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + NVal objReaderIteratorResult = NVal::CreateObject(env); + objReaderIteratorResult.AddProp("done", NVal::CreateBool(env, (readerIteratorEntity->offset == 0)).val_); + if (str != nullptr) { + objReaderIteratorResult.AddProp("value", NVal::CreateUTF8String(env, str->str, str->len).val_); + readerIteratorEntity->offset -= str->len; + } else { + objReaderIteratorResult.AddProp("value", NVal::CreateUTF8String(env, "").val_); + (void)NClass::RemoveEntityOfFinal(env, funcArg.GetThisVar()); + } + StrFree(str); + + return objReaderIteratorResult.val_; +} + +bool ReaderIteratorNExporter::Export() +{ + vector props = { + NVal::DeclareNapiFunction("next", Next), + }; + + string className = GetClassName(); + + bool succ = false; + napi_value classValue = nullptr; + tie(succ, classValue) = NClass::DefineClass(exports_.env_, className, ReaderIteratorNExporter::Constructor, + std::move(props)); + if (!succ) { + HILOGE("Failed to define class"); + NError(UNKROWN_ERR).ThrowErr(exports_.env_); + return false; + } + succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + HILOGE("Failed to save class"); + NError(UNKROWN_ERR).ThrowErr(exports_.env_); + return false; + } + + return exports_.AddProp(className, classValue); +} + +string ReaderIteratorNExporter::GetClassName() +{ + return ReaderIteratorNExporter::className_; +} + +ReaderIteratorNExporter::ReaderIteratorNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {} + +ReaderIteratorNExporter::~ReaderIteratorNExporter() {} +} // namespace OHOS::FileManagement::ModuleFileIO \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_n_exporter.h b/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_n_exporter.h new file mode 100644 index 0000000000000000000000000000000000000000..53b79d6216b2f3c7fceb4a2a9bbb92bd9a8ed773 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_readeriterator/readeriterator_n_exporter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_N_EXPORTER_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_N_EXPORTER_H + +#include "filemgmt_libn.h" + +namespace OHOS::FileManagement::ModuleFileIO { +using namespace OHOS::FileManagement::LibN; + +class ReaderIteratorNExporter final : public NExporter { +public: + inline static const std::string className_ = "ReaderIterator"; + + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info info); + static napi_value Next(napi_env env, napi_callback_info info); + + ReaderIteratorNExporter(napi_env env, napi_value exports); + ~ReaderIteratorNExporter() override; +}; +} // namespace OHOS::FileManagement::ModuleFileIO +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_CLASS_READERITERATOR_N_EXPORTER_H \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/module.cpp b/interfaces/kits/js/src/mod_fs/module.cpp index a276ac5ac73db9af2fa9846bd7ce4bf7c51847ea..16795efec583b0f2b3dd5b955270db23773d2639 100644 --- a/interfaces/kits/js/src/mod_fs/module.cpp +++ b/interfaces/kits/js/src/mod_fs/module.cpp @@ -22,6 +22,7 @@ #include "class_stat/stat_n_exporter.h" #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) #include "class_randomaccessfile/randomaccessfile_n_exporter.h" +#include "class_readeriterator/readeriterator_n_exporter.h" #include "class_stream/stream_n_exporter.h" #include "class_watcher/watcher_n_exporter.h" #endif @@ -43,6 +44,7 @@ static napi_value Export(napi_env env, napi_value exports) products.emplace_back(make_unique(env, exports)); #if !defined(WIN_PLATFORM) && !defined(IOS_PLATFORM) products.emplace_back(make_unique(env, exports)); + products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); #endif diff --git a/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp index 160ce2e6908c4b8a97ca09e9d6907959b3a42379..44b4ca8ffaa31e613ccfac147be499c0fec1b79c 100644 --- a/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/prop_n_exporter.cpp @@ -51,6 +51,7 @@ #include "lseek.h" #include "move.h" #include "movedir.h" +#include "read_lines.h" #include "read_text.h" #include "symlink.h" #include "watcher.h" @@ -609,6 +610,8 @@ bool PropNExporter::Export() NVal::DeclareNapiFunction("moveDirSync", MoveDir::Sync), NVal::DeclareNapiFunction("moveFile", Move::Async), NVal::DeclareNapiFunction("moveFileSync", Move::Sync), + NVal::DeclareNapiFunction("readLines", ReadLines::Async), + NVal::DeclareNapiFunction("readLinesSync", ReadLines::Sync), NVal::DeclareNapiFunction("readText", ReadText::Async), NVal::DeclareNapiFunction("readTextSync", ReadText::Sync), NVal::DeclareNapiFunction("symlink", Symlink::Async), diff --git a/interfaces/kits/js/src/mod_fs/properties/read_lines.cpp b/interfaces/kits/js/src/mod_fs/properties/read_lines.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e485aa579c1155c919f5a54d7a439749a282d2f --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_lines.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "read_lines.h" + +#include + +#include "class_readeriterator/readeriterator_entity.h" +#include "class_readeriterator/readeriterator_n_exporter.h" +#include "common_func.h" +#include "file_utils.h" +#include "filemgmt_libhilog.h" +#include "rust_file.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { +using namespace std; +using namespace OHOS::FileManagement::LibN; + +static int CheckOptionArg(napi_env env, napi_value argOption) +{ + NVal option(env, argOption); + if (option.HasProp("encoding")) { + auto [succ, encoding, ignore] = option.GetProp("encoding").ToUTF8String("utf-8"); + string_view encodingStr(encoding.get()); + if (!succ || encodingStr != "utf-8") { + return EINVAL; + } + } + + return ERRNO_NOERR; +} + +static int GetFileSize(const string &path, int64_t &offset) +{ + std::unique_ptr stat_req = { + new (std::nothrow) uv_fs_t, CommonFunc::fs_req_cleanup }; + if (!stat_req) { + HILOGE("Failed to request heap memory."); + return ENOMEM; + } + + int ret = uv_fs_stat(nullptr, stat_req.get(), path.c_str(), nullptr); + if (ret < 0) { + HILOGE("Failed to get file stat by path"); + return ret; + } + + offset = static_cast(stat_req->statbuf.st_size); + return ERRNO_NOERR; +} + +static NVal InstantiateReaderIterator(napi_env env, void *iterator, int64_t offset) +{ + if (iterator == nullptr) { + HILOGE("Invalid argument iterator"); + NError(EINVAL).ThrowErr(env); + return NVal(); + } + + napi_value objReaderIterator = NClass::InstantiateClass(env, ReaderIteratorNExporter::className_, {}); + if (!objReaderIterator) { + HILOGE("Failed to instantiate class ReaderIterator"); + NError(UNKROWN_ERR).ThrowErr(env); + return NVal(); + } + + auto readerIteratorEntity = NClass::GetEntityOf(env, objReaderIterator); + if (!readerIteratorEntity) { + HILOGE("Failed to get readerIteratorEntity"); + NError(UNKROWN_ERR).ThrowErr(env); + return NVal(); + } + + readerIteratorEntity->iterator = iterator; + readerIteratorEntity->offset = offset; + return { env, objReaderIterator }; +} + +struct ReaderIteratorArg { + void *iterator = nullptr; + int64_t offset = 0; +}; + +static NError AsyncExec(ReaderIteratorArg &readerIterator, char *pathStr) +{ + readerIterator.iterator = ::ReaderIterator(pathStr); + if (readerIterator.iterator == nullptr) { + HILOGE("Failed to read lines of the file, error: %{public}d", errno); + return NError(errno); + } + int ret = GetFileSize(pathStr, readerIterator.offset); + if (ret < 0) { + HILOGE("Failed to get size of the file"); + return NError(ret); + } + + return NError(ERRNO_NOERR); +} + +napi_value ReadLines::Async(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::THREE)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succPath) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + if (funcArg.GetArgc() >= NARG_CNT::TWO) { + int ret = CheckOptionArg(env, funcArg[NARG_POS::SECOND]); + if (ret) { + HILOGE("Invalid option.encoding parameter"); + NError(ret).ThrowErr(env); + return nullptr; + } + } + + auto arg = CreateSharedPtr(); + if (arg == nullptr) { + HILOGE("Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + auto cbExec = [arg, path = path.get()]() -> NError { + return AsyncExec(*arg, path); + }; + + auto cbCompl = [arg](napi_env env, NError err) -> NVal { + if (err) { + return { env, err.GetNapiErr(env) }; + } + return InstantiateReaderIterator(env, arg->iterator, arg->offset); + }; + + NVal thisVar(env, funcArg.GetThisVar()); + if (funcArg.GetArgc() == NARG_CNT::ONE || (funcArg.GetArgc() == NARG_CNT::TWO && + !NVal(env, funcArg[NARG_POS::SECOND]).TypeIs(napi_function))) { + return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_READLINES_NAME, cbExec, cbCompl).val_; + } else { + NVal cb(env, funcArg[((funcArg.GetArgc() == NARG_CNT::TWO) ? NARG_POS::SECOND : NARG_POS::THIRD)]); + return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_READLINES_NAME, cbExec, cbCompl).val_; + } +} + +napi_value ReadLines::Sync(napi_env env, napi_callback_info info) +{ + NFuncArg funcArg(env, info); + if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) { + HILOGE("Number of arguments unmatched"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + auto [succPath, path, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succPath) { + HILOGE("Invalid path from JS first argument"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + + if (funcArg.GetArgc() == NARG_CNT::TWO) { + int ret = CheckOptionArg(env, funcArg[NARG_POS::SECOND]); + if (ret) { + HILOGE("Invalid option.encoding parameter"); + NError(ret).ThrowErr(env); + return nullptr; + } + } + + auto iterator = ::ReaderIterator(path.get()); + if (iterator == nullptr) { + HILOGE("Failed to read lines of the file, error: %{public}d", errno); + NError(errno).ThrowErr(env); + return nullptr; + } + + int64_t offset = 0; + int ret = GetFileSize(path.get(), offset); + if (ret != 0) { + HILOGE("Failed to get size of the file"); + return nullptr; + } + + return InstantiateReaderIterator(env, iterator, offset).val_; +} + +} // ModuleFileIO +} // FileManagement +} // OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/properties/read_lines.h b/interfaces/kits/js/src/mod_fs/properties/read_lines.h new file mode 100644 index 0000000000000000000000000000000000000000..244d86c852367fee075c7715596c5a75820fb50e --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/properties/read_lines.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_LINES_H +#define INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_LINES_H + +#include +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + +class ReadLines final { +public: + static napi_value Async(napi_env env, napi_callback_info info); + static napi_value Sync(napi_env env, napi_callback_info info); +}; + +const std::string PROCEDURE_READLINES_NAME = "FileIOReadLines"; +} // namespace ModuleFileIO +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_JS_SRC_MOD_FS_PROPERTIES_READ_LINES_H \ No newline at end of file