1 /*
2 * Copyright (c) 2022 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 #include "js_util.h"
16
17 #include <endian.h>
18 #include <securec.h>
19
20 #include "logger.h"
21 #include "common_types.h"
22
23 namespace OHOS::ObjectStore {
24 constexpr int32_t STR_MAX_LENGTH = 4096;
25 constexpr size_t STR_TAIL_LENGTH = 1;
26
27 /* napi_value <-> bool */
GetValue(napi_env env,napi_value in,bool & out)28 napi_status JSUtil::GetValue(napi_env env, napi_value in, bool &out)
29 {
30 LOG_DEBUG("napi_value <- bool");
31 return napi_get_value_bool(env, in, &out);
32 }
33
SetValue(napi_env env,const bool & in,napi_value & out)34 napi_status JSUtil::SetValue(napi_env env, const bool &in, napi_value &out)
35 {
36 LOG_DEBUG("napi_value -> bool");
37 return napi_get_boolean(env, in, &out);
38 }
39
40 /* napi_value <-> double */
GetValue(napi_env env,napi_value in,double & out)41 napi_status JSUtil::GetValue(napi_env env, napi_value in, double &out)
42 {
43 LOG_DEBUG("napi_value -> double");
44 return napi_get_value_double(env, in, &out);
45 }
46
SetValue(napi_env env,const double & in,napi_value & out)47 napi_status JSUtil::SetValue(napi_env env, const double &in, napi_value &out)
48 {
49 LOG_DEBUG("napi_value <- double");
50 return napi_create_double(env, in, &out);
51 }
52
53 /* napi_value <-> int64_t */
GetValue(napi_env env,napi_value in,int64_t & out)54 napi_status JSUtil::GetValue(napi_env env, napi_value in, int64_t& out)
55 {
56 return napi_get_value_int64(env, in, &out);
57 }
58
SetValue(napi_env env,const int64_t & in,napi_value & out)59 napi_status JSUtil::SetValue(napi_env env, const int64_t& in, napi_value& out)
60 {
61 return napi_create_int64(env, in, &out);
62 }
63
64 /* napi_value <-> uint32_t */
GetValue(napi_env env,napi_value in,uint32_t & out)65 napi_status JSUtil::GetValue(napi_env env, napi_value in, uint32_t& out)
66 {
67 return napi_get_value_uint32(env, in, &out);
68 }
69
SetValue(napi_env env,const uint32_t & in,napi_value & out)70 napi_status JSUtil::SetValue(napi_env env, const uint32_t& in, napi_value& out)
71 {
72 return napi_create_uint32(env, in, &out);
73 }
74
75 /* napi_value <-> std::string */
GetValue(napi_env env,napi_value in,std::string & out)76 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::string &out)
77 {
78 size_t maxLen = STR_MAX_LENGTH;
79 napi_status status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen);
80 if (status != napi_ok || maxLen <= 0) {
81 return napi_generic_failure;
82 }
83 char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH];
84 if (buf != nullptr) {
85 size_t len = 0;
86 status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
87 if (status == napi_ok) {
88 out = std::string(buf);
89 }
90 delete[] buf;
91 } else {
92 status = napi_generic_failure;
93 }
94 return status;
95 }
96
SetValue(napi_env env,const std::string & in,napi_value & out)97 napi_status JSUtil::SetValue(napi_env env, const std::string &in, napi_value &out)
98 {
99 LOG_DEBUG("napi_value <- std::string %{public}d", (int)in.length());
100 return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
101 }
102
103 /* napi_value <-> std::vector<std::string> */
GetValue(napi_env env,napi_value in,std::vector<std::string> & out)104 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<std::string> &out)
105 {
106 LOG_DEBUG("napi_value -> std::vector<std::string>");
107 bool isArray = false;
108 napi_is_array(env, in, &isArray);
109 LOG_ERROR_RETURN(isArray, "not an array", napi_invalid_arg);
110
111 uint32_t length = 0;
112 napi_status status = napi_get_array_length(env, in, &length);
113 LOG_ERROR_RETURN((status == napi_ok) && (length > 0), "get_array failed!", napi_invalid_arg);
114 for (uint32_t i = 0; i < length; ++i) {
115 napi_value item = nullptr;
116 status = napi_get_element(env, in, i, &item);
117 LOG_ERROR_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
118 std::string value;
119 status = GetValue(env, item, value);
120 LOG_ERROR_RETURN(status == napi_ok, "not a string", napi_invalid_arg);
121 out.push_back(value);
122 }
123 return status;
124 }
125
SetValue(napi_env env,const std::vector<std::string> & in,napi_value & out)126 napi_status JSUtil::SetValue(napi_env env, const std::vector<std::string> &in, napi_value &out)
127 {
128 LOG_DEBUG("napi_value <- std::vector<std::string>");
129 napi_status status = napi_create_array_with_length(env, in.size(), &out);
130 LOG_ERROR_RETURN(status == napi_ok, "create array failed!", status);
131 int index = 0;
132 for (auto &item : in) {
133 napi_value element = nullptr;
134 SetValue(env, item, element);
135 status = napi_set_element(env, out, index++, element);
136 LOG_ERROR_RETURN((status == napi_ok), "napi_set_element failed!", status);
137 }
138 return status;
139 }
140
141 /* napi_value <-> std::vector<uint8_t> */
GetValue(napi_env env,napi_value in,std::vector<uint8_t> & out)142 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<uint8_t> &out)
143 {
144 out.clear();
145 LOG_DEBUG("napi_value -> std::vector<uint8_t> ");
146 napi_typedarray_type type = napi_biguint64_array;
147 size_t length = 0;
148 napi_value buffer = nullptr;
149 size_t offset = 0;
150 void *data = nullptr;
151 napi_status status = napi_get_typedarray_info(env, in, &type, &length, &data, &buffer, &offset);
152 LOG_DEBUG("array type=%{public}d length=%{public}d offset=%{public}d status=%{public}d", (int)type, (int)length,
153 (int)offset, status);
154 LOG_ERROR_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
155 LOG_ERROR_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg);
156 LOG_ERROR_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
157 out.assign(static_cast<uint8_t *>(data), static_cast<uint8_t *>(data) + length);
158 return status;
159 }
160
SetValue(napi_env env,const std::vector<uint8_t> & in,napi_value & out)161 napi_status JSUtil::SetValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out)
162 {
163 LOG_DEBUG("napi_value <- std::vector<uint8_t> ");
164 LOG_ERROR_RETURN(in.size() > 0, "invalid std::vector<uint8_t>", napi_invalid_arg);
165 void *data = nullptr;
166 napi_value buffer = nullptr;
167 napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer);
168 LOG_ERROR_RETURN((status == napi_ok), "create array buffer failed!", status);
169
170 if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) {
171 LOG_ERROR("memcpy_s not EOK");
172 return napi_invalid_arg;
173 }
174 status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
175 LOG_ERROR_RETURN((status == napi_ok), "napi_value <- std::vector<uint8_t> invalid value", status);
176 return status;
177 }
178
GetValue(napi_env env,napi_value in,AssetBindInfo & bindInfo)179 napi_status JSUtil::GetValue(napi_env env, napi_value in, AssetBindInfo &bindInfo)
180 {
181 napi_status status = napi_invalid_arg;
182 status = GetNamedProperty(env, in, "storeName", bindInfo.storeName);
183 LOG_ERROR_RETURN(status == napi_ok, "get store param failed", status);
184 status = GetNamedProperty(env, in, "tableName", bindInfo.tableName);
185 LOG_ERROR_RETURN(status == napi_ok, "get table param failed", status);
186 status = GetNamedProperty(env, in, "primaryKey", bindInfo.primaryKey);
187
188 LOG_ERROR_RETURN(status == napi_ok, "get primary param failed", status);
189 status = GetNamedProperty(env, in, "field", bindInfo.field);
190 LOG_ERROR_RETURN(status == napi_ok, "get field param failed", status);
191 status = GetNamedProperty(env, in, "assetName", bindInfo.assetName);
192 LOG_ERROR_RETURN(status == napi_ok, "get assetName param failed", status);
193 return status;
194 }
195
GetValue(napi_env env,napi_value in,Asset & asset)196 napi_status JSUtil::GetValue(napi_env env, napi_value in, Asset &asset)
197 {
198 napi_valuetype type;
199 napi_status status = napi_typeof(env, in, &type);
200 LOG_ERROR_RETURN((status == napi_ok) && (type == napi_object), "Asset type invalid", napi_invalid_arg);
201 status = GetNamedProperty(env, in, "name", asset.name);
202 LOG_ERROR_RETURN(status == napi_ok, "get name param failed", status);
203 status = GetNamedProperty(env, in, "uri", asset.uri);
204 LOG_ERROR_RETURN(status == napi_ok, "get uri param failed", status);
205 status = GetNamedProperty(env, in, "path", asset.path);
206 LOG_ERROR_RETURN(status == napi_ok, "get path param failed", status);
207 status = GetNamedProperty(env, in, "createTime", asset.createTime);
208 LOG_ERROR_RETURN(status == napi_ok, "get createTime param failed", status);
209 status = GetNamedProperty(env, in, "modifyTime", asset.modifyTime);
210 LOG_ERROR_RETURN(status == napi_ok, "get modifyTime param failed", status);
211 status = GetNamedProperty(env, in, "size", asset.size);
212 LOG_ERROR_RETURN(status == napi_ok, "get size param failed", status);
213 status = GetNamedProperty(env, in, "status", asset.status, true);
214 LOG_ERROR_RETURN(status == napi_ok, "get status param failed", status);
215 return status;
216 }
217
GetValue(napi_env env,napi_value in,Assets & assets)218 napi_status JSUtil::GetValue(napi_env env, napi_value in, Assets &assets)
219 {
220 assets.clear();
221 bool isArray = false;
222 napi_is_array(env, in, &isArray);
223 LOG_ERROR_RETURN(isArray, "not an array", napi_generic_failure);
224
225 uint32_t arrLen = 0;
226 napi_status status = napi_get_array_length(env, in, &arrLen);
227 LOG_ERROR_RETURN((status == napi_ok) && (arrLen > 0), "get_array failed!", status);
228 for (uint32_t i = 0; i < arrLen; ++i) {
229 napi_value item = nullptr;
230 status = napi_get_element(env, in, i, &item);
231 LOG_ERROR_RETURN((item != nullptr) && (status == napi_ok), "no element", status);
232 Asset asset;
233 status = GetValue(env, item, asset);
234 LOG_ERROR_RETURN(status == napi_ok, "not a asset object", status);
235 assets.push_back(asset);
236 }
237 return status;
238 }
239
GetValue(napi_env env,napi_value in,ValuesBucket & out)240 napi_status JSUtil::GetValue(napi_env env, napi_value in, ValuesBucket &out)
241 {
242 out.clear();
243 napi_value values = nullptr;
244 uint32_t count = 0;
245 napi_get_all_property_names(env, in, napi_key_own_only,
246 static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols),
247 napi_key_numbers_to_strings, &values);
248 napi_status status = napi_get_array_length(env, values, &count);
249 LOG_ERROR_RETURN(status == napi_ok && count > 0, "get ValuesBucket failed", napi_invalid_arg);
250 napi_value key = nullptr;
251 napi_value val = nullptr;
252 for (uint32_t index = 0; index < count; index++) {
253 status = napi_get_element(env, values, index, &key);
254 LOG_ERROR_RETURN(status == napi_ok && key != nullptr, "no element", napi_invalid_arg);
255 std::string keyStr;
256 status = GetValue(env, key, keyStr);
257 LOG_ERROR_RETURN(status == napi_ok, "get key failed", status);
258 status = napi_get_property(env, in, key, &val);
259 LOG_ERROR_RETURN(status == napi_ok && val != nullptr, "no element", napi_invalid_arg);
260 ValueObject value;
261 status = GetValue(env, val, value);
262 if (status == napi_ok) {
263 out.insert(std::pair<std::string, ValueObject>(keyStr, value));
264 } else if (status != napi_generic_failure) {
265 LOG_ERROR("The value type %{public}s is invalid: ", keyStr.c_str());
266 return status;
267 }
268 }
269 return napi_ok;
270 }
271
GetValue(napi_env env,napi_value jsValue,std::monostate & out)272 napi_status JSUtil::GetValue(napi_env env, napi_value jsValue, std::monostate &out)
273 {
274 napi_value tempValue;
275 napi_get_null(env, &tempValue);
276 bool equal = false;
277 napi_strict_equals(env, jsValue, tempValue, &equal);
278 if (equal) {
279 out = std::monostate();
280 return napi_ok;
281 }
282 LOG_DEBUG("jsValue is not null");
283 return napi_invalid_arg;
284 }
285
IsNull(napi_env env,napi_value value)286 bool JSUtil::IsNull(napi_env env, napi_value value)
287 {
288 napi_valuetype type = napi_undefined;
289 napi_status status = napi_typeof(env, value, &type);
290 if (status == napi_ok && (type == napi_undefined || type == napi_null)) {
291 return true;
292 }
293 return false;
294 }
295 } // namespace OHOS::ObjectStore
296