• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "listfile_ani.h"
17 
18 #include "ani_signature.h"
19 #include "error_handler.h"
20 #include "filemgmt_libhilog.h"
21 #include "listfile_core.h"
22 #include "type_converter.h"
23 
24 namespace OHOS {
25 namespace FileManagement {
26 namespace ModuleFileIO {
27 namespace ANI {
28 
29 using namespace std;
30 using namespace OHOS::FileManagement::ModuleFileIO;
31 using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature;
32 
ParseBooleanParam(ani_env * env,ani_object obj,string tag)33 tuple<bool, bool> ParseBooleanParam(ani_env *env, ani_object obj, string tag)
34 {
35     ani_ref boolRef;
36     ani_boolean isUndefined;
37     if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &boolRef)) {
38         return { false, false };
39     }
40     env->Reference_IsUndefined(boolRef, &isUndefined);
41     if (isUndefined) {
42         return { true, false };
43     }
44     auto unboxedDesc = BoxedTypes::Boolean::unboxedDesc.c_str();
45     auto unboxedSig = BoxedTypes::Boolean::unboxedSig.c_str();
46     ani_boolean boolRef_res;
47     if (ANI_OK != env->Object_CallMethodByName_Boolean(
48         static_cast<ani_object>(boolRef), unboxedDesc, unboxedSig, &boolRef_res)) {
49         return { false, false };
50     }
51     return { true, static_cast<bool>(boolRef_res) };
52 }
53 
ParseIntParam(ani_env * env,ani_object obj,string tag)54 tuple<bool, int> ParseIntParam(ani_env *env, ani_object obj, string tag)
55 {
56     int result = 0;
57     ani_boolean isUndefined;
58     ani_ref resultRef;
59     if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &resultRef)) {
60         return { false, result };
61     }
62     env->Reference_IsUndefined(resultRef, &isUndefined);
63     if (isUndefined) {
64         return { true, result };
65     }
66     ani_int resultRefRes;
67     if (ANI_OK != env->Object_CallMethodByName_Int(
68         static_cast<ani_object>(resultRef), BasicTypesConverter::toInt.c_str(), nullptr, &resultRefRes)) {
69         result = -1;
70         return { false, result };
71     }
72     result = static_cast<int>(resultRefRes);
73     return { true, result };
74 }
75 
ParseDoubleParam(ani_env * env,ani_object obj,string tag)76 tuple<bool, optional<double>> ParseDoubleParam(ani_env *env, ani_object obj, string tag)
77 {
78     ani_boolean isUndefined;
79     ani_ref resultRef;
80     if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &resultRef)) {
81         return { false, nullopt };
82     }
83     env->Reference_IsUndefined(resultRef, &isUndefined);
84     if (isUndefined) {
85         return { true, nullopt };
86     }
87 
88     ani_double resultRefRes;
89     if (ANI_OK != env->Object_CallMethodByName_Double(
90         static_cast<ani_object>(resultRef), BasicTypesConverter::toDouble.c_str(), nullptr, &resultRefRes)) {
91         return { false, nullopt };
92     }
93     double result = static_cast<double>(resultRefRes);
94     return { true, make_optional<double>(result) };
95 }
96 
ParseArrayString(ani_env * env,ani_object obj,string tag)97 tuple<bool, optional<vector<string>>> ParseArrayString(ani_env *env, ani_object obj, string tag)
98 {
99     ani_boolean isUndefined;
100     ani_ref resultRef;
101     vector<string> strings;
102     if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &resultRef)) {
103         return { false, nullopt };
104     }
105     env->Reference_IsUndefined(resultRef, &isUndefined);
106     if (isUndefined) {
107         return { true, nullopt };
108     }
109 
110     ani_double length;
111     if (ANI_OK != env->Object_GetPropertyByName_Double(
112         static_cast<ani_object>(resultRef), "length", &length) || length == 0) {
113         return { false, nullopt };
114     }
115     auto getterDesc = BuiltInTypes::Array::getterDesc.c_str();
116     auto getterSig = BuiltInTypes::Array::objectGetterSig.c_str();
117     for (int idx = 0; idx < int(length); idx++) {
118         ani_ref stringEntryRef;
119         if (ANI_OK != env->Object_CallMethodByName_Ref(
120             static_cast<ani_object>(resultRef), getterDesc, getterSig, &stringEntryRef, (ani_int)idx)) {
121             return { false, nullopt };
122         }
123         auto [succ, tmp] = TypeConverter::ToUTF8String(env, static_cast<ani_string>(stringEntryRef));
124         if (!succ) {
125             return { false, nullopt };
126         }
127         strings.emplace_back(tmp);
128     }
129     return { true, make_optional<vector<string>>(move(strings)) };
130 }
131 
ParseFilter(ani_env * env,ani_object obj)132 tuple<bool, optional<FsFileFilter>> ParseFilter(ani_env *env, ani_object obj)
133 {
134     FsFileFilter filter;
135 
136     auto [succfileSizeOver, fileSizeOver] = ParseIntParam(env, obj, "fileSizeOver");
137     if (!succfileSizeOver) {
138         HILOGE("Illegal option.fileSizeOver parameter");
139         return { false, move(filter) };
140     }
141     filter.SetFileSizeOver(fileSizeOver);
142 
143     auto [succlastModifiedAfter, lastModifiedAfter] = ParseDoubleParam(env, obj, "lastModifiedAfter");
144     if (!succlastModifiedAfter) {
145         HILOGE("Illegal option.lastModifiedAfter parameter");
146         return { false, move(filter) };
147     }
148     filter.SetLastModifiedAfter(lastModifiedAfter);
149 
150     auto [succSuffix, suffix] = ParseArrayString(env, obj, "suffix");
151     if (!succSuffix) {
152         HILOGE("Illegal option.suffix parameter");
153         return { false, move(filter) };
154     }
155     filter.SetSuffix(move(suffix));
156 
157     auto [succDisplayName, displayName] = ParseArrayString(env, obj, "displayName");
158     if (!succDisplayName) {
159         HILOGE("Illegal option.displayName parameter");
160         return { false, move(filter) };
161     }
162     filter.SetDisplayName(move(displayName));
163 
164     return { true, move(filter) };
165 }
166 
ParseArgs(ani_env * env,ani_object obj)167 tuple<bool, optional<FsListFileOptions>> ParseArgs(ani_env *env, ani_object obj)
168 {
169     FsListFileOptions result;
170     ani_boolean isUndefined;
171     env->Reference_IsUndefined(obj, &isUndefined);
172     if (isUndefined) {
173         return { true, nullopt };
174     }
175 
176     auto [succRecursion, recursion] = ParseBooleanParam(env, obj, "recursion");
177     if (!succRecursion) {
178         HILOGE("Invalid recursion");
179         return { false, nullopt };
180     }
181     result.recursion = recursion;
182 
183     auto [succlistNum, listNumRes] = ParseIntParam(env, obj, "listNum");
184     if (!succlistNum) {
185         HILOGE("Invalid listNum");
186         return { false, nullopt };
187     }
188     result.listNum = (int)listNumRes;
189 
190     ani_ref filterRef;
191     if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, "filter", &filterRef)) {
192         HILOGE("Invalid filter");
193         return { false, nullopt };
194     }
195     env->Reference_IsUndefined(filterRef, &isUndefined);
196     if (isUndefined) {
197         return { true, make_optional<FsListFileOptions>(result) };
198     }
199     auto [succFilter, filterFilterClass] = ParseFilter(env, static_cast<ani_object>(filterRef));
200     if (!succFilter) {
201         HILOGE("Invalid filter");
202         return { false, nullopt };
203     }
204     result.filter = move(filterFilterClass);
205 
206     return { true, make_optional<FsListFileOptions>(result) };
207 }
208 
ListFileSync(ani_env * env,ani_class clazz,ani_string path,ani_object obj)209 ani_array_ref ListFileAni::ListFileSync(ani_env *env, [[maybe_unused]] ani_class clazz, ani_string path, ani_object obj)
210 {
211     auto [succPath, srcPath] = TypeConverter::ToUTF8String(env, path);
212     if (!succPath) {
213         HILOGE("Invalid path");
214         ErrorHandler::Throw(env, EINVAL);
215         return nullptr;
216     }
217 
218     auto [succOpt, opt] = ParseArgs(env, obj);
219     if (!succOpt) {
220         HILOGE("Invalid options Arguments");
221         ErrorHandler::Throw(env, EINVAL);
222         return nullptr;
223     }
224 
225     auto ret = ListFileCore::DoListFile(srcPath, opt);
226     if (!ret.IsSuccess()) {
227         HILOGE("DoListFile failed");
228         const auto &err = ret.GetError();
229         ErrorHandler::Throw(env, err);
230         return nullptr;
231     }
232 
233     auto fileList = ret.GetData().value();
234     const std::string *strArray = fileList.data();
235     auto [succ, result] = TypeConverter::ToAniStringList(env, strArray, fileList.size());
236     if (!succ) {
237         HILOGE("Convert list file result to ani string array failed");
238         ErrorHandler::Throw(env, UNKNOWN_ERR);
239         return nullptr;
240     }
241     return result;
242 }
243 
244 } // namespace ANI
245 } // namespace ModuleFileIO
246 } // namespace FileManagement
247 } // namespace OHOS