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 "write_ani.h"
17
18 #include <optional>
19 #include "ani_helper.h"
20 #include "ani_signature.h"
21 #include "error_handler.h"
22 #include "filemgmt_libhilog.h"
23 #include "type_converter.h"
24 #include "write_core.h"
25
26 namespace OHOS {
27 namespace FileManagement {
28 namespace ModuleFileIO {
29 namespace ANI {
30 using namespace std;
31 using namespace OHOS::FileManagement::ModuleFileIO;
32 using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature;
33
ToWriteOptions(ani_env * env,ani_object obj)34 static tuple<bool, optional<WriteOptions>> ToWriteOptions(ani_env *env, ani_object obj)
35 {
36 WriteOptions options;
37 ani_boolean isUndefined;
38 env->Reference_IsUndefined(obj, &isUndefined);
39 if (isUndefined) {
40 return { true, nullopt };
41 }
42
43 auto [succOffset, offset] = AniHelper::ParseInt64Option(env, obj, "offset");
44 if (!succOffset) {
45 HILOGE("Illegal option.offset parameter");
46 return { false, nullopt };
47 }
48 options.offset = offset;
49
50 auto [succLength, length] = AniHelper::ParseInt64Option(env, obj, "length");
51 if (!succLength) {
52 HILOGE("Illegal option.length parameter");
53 return { false, nullopt };
54 }
55 options.length = length;
56
57 auto [succEncoding, encoding] = AniHelper::ParseEncoding(env, obj);
58 if (!succEncoding) {
59 HILOGE("Illegal option.encoding parameter");
60 return { false, nullopt };
61 }
62 options.encoding = encoding;
63 return { true, make_optional<WriteOptions>(move(options)) };
64 }
65
ParseStringBuffer(ani_env * env,const ani_object & buf)66 static std::tuple<bool, ani_string> ParseStringBuffer(ani_env *env, const ani_object &buf)
67 {
68 auto classDesc = BuiltInTypes::String::classDesc.c_str();
69 ani_class cls;
70 env->FindClass(classDesc, &cls);
71
72 ani_boolean isString;
73 env->Object_InstanceOf(buf, cls, &isString);
74 if (!isString) {
75 return { false, {} };
76 }
77 auto result = static_cast<ani_string>(buf);
78
79 return { true, std::move(result) };
80 }
81
ParseArrayBuffer(ani_env * env,const ani_object & buf)82 static std::tuple<bool, ani_arraybuffer> ParseArrayBuffer(ani_env *env, const ani_object &buf)
83 {
84 auto classDesc = BuiltInTypes::ArrayBuffer::classDesc.c_str();
85 ani_class cls;
86 env->FindClass(classDesc, &cls);
87
88 ani_boolean isArrayBuffer;
89 env->Object_InstanceOf(buf, cls, &isArrayBuffer);
90 if (!isArrayBuffer) {
91 return { false, {} };
92 }
93 auto result = static_cast<ani_arraybuffer>(buf);
94
95 return { true, std::move(result) };
96 }
97
WriteSync(ani_env * env,ani_class clazz,ani_double fd,ani_object buf,ani_object options)98 ani_double WriteAni::WriteSync(
99 ani_env *env, [[maybe_unused]] ani_class clazz, ani_double fd, ani_object buf, ani_object options)
100 {
101 auto [succOp, op] = ToWriteOptions(env, options);
102 if (!succOp) {
103 HILOGE("Failed to resolve options!");
104 ErrorHandler::Throw(env, EINVAL);
105 return -1;
106 }
107
108 auto [isString, stringBuffer] = ParseStringBuffer(env, buf);
109 if (isString) {
110 auto [succBuf, buffer] = TypeConverter::ToUTF8String(env, stringBuffer);
111 if (!succBuf) {
112 HILOGE("Failed to resolve stringBuffer!");
113 ErrorHandler::Throw(env, EINVAL);
114 return -1;
115 }
116 auto ret = WriteCore::DoWrite(static_cast<int32_t>(fd), buffer, op);
117 if (!ret.IsSuccess()) {
118 HILOGE("write buffer failed!");
119 const auto &err = ret.GetError();
120 ErrorHandler::Throw(env, err);
121 return -1;
122 }
123 return static_cast<double>(ret.GetData().value());
124 }
125
126 auto [isArrayBuffer, arrayBuffer] = ParseArrayBuffer(env, buf);
127 if (isArrayBuffer) {
128 auto [succBuf, buffer] = TypeConverter::ToArrayBuffer(env, arrayBuffer);
129 if (!succBuf) {
130 HILOGE("Failed to resolve arrayBuffer!");
131 ErrorHandler::Throw(env, EINVAL);
132 return -1;
133 }
134 auto ret = WriteCore::DoWrite(static_cast<int32_t>(fd), buffer, op);
135 if (!ret.IsSuccess()) {
136 HILOGE("write buffer failed!");
137 const auto &err = ret.GetError();
138 ErrorHandler::Throw(env, err);
139 return -1;
140 }
141 return static_cast<double>(ret.GetData().value());
142 }
143
144 HILOGE("Unsupported buffer type!");
145 ErrorHandler::Throw(env, EINVAL);
146 return -1;
147 }
148 } // namespace ANI
149 } // namespace ModuleFileIO
150 } // namespace FileManagement
151 } // namespace OHOS