1 /* 2 * Copyright (c) 2022-2023 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 #ifndef OHOS_FILEMGMT_BACKUP_B_JSON_CACHED_ENTITY_H 17 #define OHOS_FILEMGMT_BACKUP_B_JSON_CACHED_ENTITY_H 18 19 #include <any> 20 #include <functional> 21 #include <memory> 22 #include <sstream> 23 #include <string> 24 #include <string_view> 25 #include <sys/stat.h> 26 #include <system_error> 27 #include <type_traits> 28 29 #include "b_error/b_error.h" 30 #include "b_filesystem/b_file.h" 31 #include "b_json/b_json_entity.h" 32 #include "filemgmt_libhilog.h" 33 #include "unique_fd.h" 34 #include "json/json.h" 35 36 namespace OHOS::FileManagement::Backup { 37 template <typename T> 38 class BJsonCachedEntity { 39 public: 40 /** 41 * @brief 获取结构化对象 42 * 43 * @return T 结构化对象(即实体) 44 */ Structuralize()45 T Structuralize() 46 { 47 static_assert(!std::is_default_constructible_v<T>); 48 static_assert(!std::is_base_of_v<T, BJsonEntity>); 49 return T(obj_); 50 } 51 52 /** 53 * @brief 持久化JSon对象并完成 54 * 55 * @throw std::system_error IO异常 56 */ Persist()57 void Persist() 58 { 59 Json::StreamWriterBuilder builder; 60 const std::string jsonFileContent = Json::writeString(builder, obj_); 61 HILOGD("Try to persist a Json object, whose content reads: %{public}s", jsonFileContent.c_str()); 62 63 BFile::Write(srcFile_, jsonFileContent); 64 } 65 66 /** 67 * @brief 从文件中重新加载JSon对象 68 * 69 * @throw std::system_error IO异常或解析异常 70 */ ReloadFromFile()71 int ReloadFromFile() 72 { 73 Json::CharReaderBuilder builder; 74 std::unique_ptr<Json::CharReader> const jsonReader(builder.newCharReader()); 75 Json::Value jValue; 76 std::string errs; 77 std::unique_ptr<char[]> rawBuf = BFile::ReadFile(srcFile_); 78 std::string_view sv(rawBuf.get()); 79 80 if (sv.empty()) { 81 HILOGI("This Json file is empty"); 82 return 0; 83 } 84 85 bool res = jsonReader->parse(sv.data(), sv.data() + sv.length(), &jValue, &errs); 86 if (!res || !errs.empty()) { 87 return BError(BError::Codes::UTILS_INVAL_JSON_ENTITY, errs).GetCode(); 88 } 89 90 obj_ = std::move(jValue); 91 return 0; 92 } 93 94 /** 95 * @brief 根据字符串重新加载JSon对象 96 * 97 * @throw std::system_error IO异常或解析异常 98 */ ReloadFromString(std::string_view sv)99 void ReloadFromString(std::string_view sv) 100 { 101 Json::CharReaderBuilder builder; 102 std::unique_ptr<Json::CharReader> const jsonReader(builder.newCharReader()); 103 Json::Value jValue; 104 std::string errs; 105 106 bool res = jsonReader->parse(sv.data(), sv.data() + sv.length(), &jValue, &errs); 107 if (!res || !errs.empty()) { 108 HILOGE("Json utils operated on an invalid file"); 109 return; 110 } 111 112 obj_ = std::move(jValue); 113 } 114 115 /** 116 * @brief 获取JSon文件的文件描述符 117 * 118 * @return UniqueFd& 119 */ GetFd()120 UniqueFd &GetFd() 121 { 122 return srcFile_; 123 } 124 125 public: 126 /** 127 * @brief 构造方法,要求T必须具备T(Json::Value&)构造函数 128 * 129 * @param fd 用于加载/持久化JSon对象的文件 130 */ BJsonCachedEntity(UniqueFd fd)131 explicit BJsonCachedEntity(UniqueFd fd) : srcFile_(std::move(fd)), entity_(std::ref(obj_)) 132 { 133 struct stat stat = {}; 134 if (fstat(srcFile_, &stat) == -1) { 135 std::stringstream ss; 136 ss << std::generic_category().message(errno) << " with fd eq" << srcFile_.Get(); 137 BError(BError::Codes::UTILS_INVAL_JSON_ENTITY, ss.str()); 138 return; 139 } 140 141 (void)ReloadFromFile(); 142 } 143 144 /** 145 * @brief 构造方法,要求T必须具备T(Json::Value&, std::any)构造函数 146 * 147 * @param sv 用于加载/持久化JSon对象的字符串 148 * @param option 任意类型对象 149 */ 150 explicit BJsonCachedEntity(std::string_view sv, std::any option = std::any()) : entity_(std::ref(obj_)) 151 { 152 ReloadFromString(entity_.GetJSonSource(sv, option)); 153 } 154 155 private: 156 UniqueFd srcFile_; 157 Json::Value obj_; 158 T entity_; 159 }; 160 } // namespace OHOS::FileManagement::Backup 161 162 #endif // OHOS_FILEMGMT_BACKUP_B_JSON_CACHED_ENTITY_H