diff --git a/BUILD.gn b/BUILD.gn index 20912be..f5a554d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -15,6 +15,7 @@ import("//build/ohos.gni") import("//build/test.gni") ohos_executable("restool") { sources = [ + "src/append_compiler.cpp", "src/cmd_list.cpp", "src/cmd_parser.cpp", "src/config_parser.cpp", @@ -33,6 +34,7 @@ ohos_executable("restool") { "src/module_combine.cpp", "src/preview_manager.cpp", "src/reference_parser.cpp", + "src/resource_append.cpp", "src/resource_directory.cpp", "src/resource_item.cpp", "src/resource_merge.cpp", @@ -76,6 +78,7 @@ ohos_executable("restool") { ldflags = [ "-static", "-lws2_32", + "-lshlwapi", ] } subsystem_name = "developtools" diff --git a/build/bounds_checking_function/BUILD.gn b/build/bounds_checking_function/BUILD.gn index 3c20d31..34776ae 100644 --- a/build/bounds_checking_function/BUILD.gn +++ b/build/bounds_checking_function/BUILD.gn @@ -31,5 +31,5 @@ ohos_static_library("restool_bounds_checking_function") { "-D_INC_MEMORY_S", ] subsystem_name = "developtools" - part_name = "global_restool" + part_name = "global_resource_tool" } diff --git a/build/jsoncpp/BUILD.gn b/build/jsoncpp/BUILD.gn index 3682a0a..f5c7d76 100644 --- a/build/jsoncpp/BUILD.gn +++ b/build/jsoncpp/BUILD.gn @@ -24,5 +24,5 @@ ohos_static_library("restool_jsoncpp") { cflags = [ "-std=c++17" ] use_exceptions = true subsystem_name = "developtools" - part_name = "global_restool" + part_name = "global_resource_tool" } diff --git a/build/libxml2/BUILD.gn b/build/libxml2/BUILD.gn index 0e76d16..4ced9a4 100644 --- a/build/libxml2/BUILD.gn +++ b/build/libxml2/BUILD.gn @@ -132,5 +132,5 @@ ohos_static_library("restool_libxml2") { public_configs = [ ":restool_libxml2_config" ] subsystem_name = "developtools" - part_name = "global_restool" + part_name = "global_resource_tool" } diff --git a/build/sqlite3/BUILD.gn b/build/sqlite3/BUILD.gn index b807d2e..a04db9e 100644 --- a/build/sqlite3/BUILD.gn +++ b/build/sqlite3/BUILD.gn @@ -18,5 +18,5 @@ ohos_static_library("restool_sqlite") { include_dirs = [ "//third_party/sqlite/include" ] subsystem_name = "developtools" - part_name = "global_restool" + part_name = "global_resource_tool" } diff --git a/include/append_compiler.h b/include/append_compiler.h new file mode 100644 index 0000000..bb88f9e --- /dev/null +++ b/include/append_compiler.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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 OHOS_RESTOOL_APPEND_COMPILER_H +#define OHOS_RESTOOL_APPEND_COMPILER_H + +#include "i_resource_compiler.h" + +namespace OHOS { +namespace Global { +namespace Restool { +class AppendCompiler : public IResourceCompiler { +public: + AppendCompiler(ResType type, const std::string &output); + virtual ~AppendCompiler() {}; +protected: + uint32_t CompileSingleFile(const FileInfo &fileInfo) override; +}; +} +} +} +#endif \ No newline at end of file diff --git a/include/cmd_parser.h b/include/cmd_parser.h index 1bbabcf..6800a9e 100644 --- a/include/cmd_parser.h +++ b/include/cmd_parser.h @@ -50,6 +50,8 @@ public: bool IsFileList() const; bool GetPreviewMode() const; int32_t GetPriority() const; + const std::vector &GetAppend() const; + bool GetCombine() const; private: void InitCommand(); @@ -69,6 +71,9 @@ private: uint32_t ParseFileList(const std::string& fileListPath); uint32_t SetPreviewMode(); uint32_t SetPriority(const std::string& argValue); + uint32_t AddAppend(const std::string& argValue); + uint32_t SetCombine(); + bool IsAscii(const std::string& argValue) const; static const struct option CMD_OPTS[]; static const std::string CMD_PARAMS; @@ -87,6 +92,8 @@ private: bool isFileList_ = false; bool previewMode_ = false; int32_t priority_ = -1; + std::vector append_; + bool combine_ = false; }; template @@ -116,7 +123,8 @@ void CmdParser::ShowUseage() std::cout << " -m module name, can add more, split by ','(like entry1,entry2,...).\n"; std::cout << " -j config.json path.\n"; std::cout << " -e start id mask, e.g 0x01000000, in [0x01000000, 0x06FFFFFF),[0x08000000, 0x41FFFFFF)\n"; - std::cout << " -c increment compile cache directory path.\n"; + std::cout << " -x resources folder path\n"; + std::cout << " -z flag for incremental compilation\n"; } template diff --git a/include/factory_resource_compiler.h b/include/factory_resource_compiler.h index e27f4f8..8e617aa 100644 --- a/include/factory_resource_compiler.h +++ b/include/factory_resource_compiler.h @@ -25,6 +25,7 @@ namespace Restool { class FactoryResourceCompiler { public: static std::unique_ptr CreateCompiler(ResType type, const std::string &output); + static std::unique_ptr CreateCompilerForAppend(ResType type, const std::string &output); }; } } diff --git a/include/file_entry.h b/include/file_entry.h index 3d75161..584993d 100644 --- a/include/file_entry.h +++ b/include/file_entry.h @@ -54,8 +54,9 @@ public: static bool Exist(const std::string &path); static bool RemoveAllDir(const std::string &path); static bool CreateDirs(const std::string &path); - static bool CopyFile(const std::string &src, const std::string &dst); + static bool CopyFileInner(const std::string &src, const std::string &dst); static bool IsDirectory(const std::string &path); + static std::string RealPath(const std::string &path); private: bool IsIgnore(const std::string &filename) const; diff --git a/include/i_resource_compiler.h b/include/i_resource_compiler.h index 4fc882e..cb5df84 100644 --- a/include/i_resource_compiler.h +++ b/include/i_resource_compiler.h @@ -33,6 +33,8 @@ public: uint32_t Compile(const FileInfo &fileInfo); void SetModuleName(const std::string &moduleName); void SetPreviewMode(bool enable) { previewMode_ = enable; }; + uint32_t CompileForAppend(const FileInfo &fileInfo); + const std::map, std::vector> &GetResourceItems() const; protected: virtual uint32_t CompileSingleFile(const FileInfo &fileInfo); diff --git a/include/reference_parser.h b/include/reference_parser.h index b1c3b1e..dbf2b77 100644 --- a/include/reference_parser.h +++ b/include/reference_parser.h @@ -31,6 +31,8 @@ public: uint32_t ParseRefInString(std::string &value, bool &update) const; uint32_t ParseRefInProfile(const std::string &output) const; uint32_t ParseRefInJson(const std::string &filePath) const; + uint32_t ParseRefInJson(const std::string &from, const std::string &to) const; + uint32_t ParseRefInResourceItem(ResourceItem &resourceItem) const; private: bool ParseRefResourceItem(ResourceItem &resourceItem) const; bool ParseRefResourceItemData(const ResourceItem &resourceItem, std::string &data, bool &update) const; @@ -40,7 +42,7 @@ private: bool ParseRefString(std::string &key) const; bool ParseRefString(std::string &key, bool &update) const; bool ParseRefImpl(std::string &key, const std::map &refs, bool isSystem) const; - bool ParseRefJsonImpl(Json::Value &root) const; + bool ParseRefJsonImpl(Json::Value &root, bool &needSave) const; const IdWorker &idWorker_; static const std::map ID_REFS; static const std::map ID_OHOS_REFS; diff --git a/include/resource_append.h b/include/resource_append.h new file mode 100644 index 0000000..7a6f2de --- /dev/null +++ b/include/resource_append.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022 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 OHOS_RESTOOL_RESOURCE_APPEND_H +#define OHOS_RESTOOL_RESOURCE_APPEND_H + +#include +#include "cmd_parser.h" +#include "factory_resource_compiler.h" +#include "file_entry.h" + +namespace OHOS { +namespace Global { +namespace Restool { +class ResourceAppend { +public: + ResourceAppend(const PackageParser &packageParser); + virtual ~ResourceAppend() {}; + uint32_t Append(); + uint32_t Combine(); + +private: + bool Combine(const std::string &folderPath); + bool ScanResources(const std::string &resourcePath, const std::string &outputPath); + bool ScanIegalResources(const std::string &resourcePath, const std::string &outputPath); + bool ScanLimitKey(const std::unique_ptr &entry, const std::string &limitKey, const std::string outputPath); + bool ScanFiles(const std::unique_ptr &entry, const DirectoryInfo &directoryInfo, const std::string &outputPath); + bool ScanFile(const FileInfo &fileInfo, const std::string &outputPath); + bool ScanSingleFile(const std::string &filePath, const std::string &outputPath); + bool WriteFileInner(std::ostringstream &outStream, const std::string &outputPath) const; + bool WriteResourceItem(const ResourceItem &resourceItem, std::ostringstream &out); + bool LoadResourceItem(const std::string &filePath); + bool ScanRawFiles(const std::string &path, const std::string &outputPath); + bool WriteRawFile(const std::string &filePath, const std::string &outputPath); + bool Push(const std::shared_ptr &resourceItem); + void AddRef(const std::shared_ptr &resourceItem); + bool LoadResourceItemFromMem(const char buffer[], int32_t length); + std::string ParseString(const char buffer[], int32_t length, int32_t &offset) const; + int32_t ParseInt32(const char buffer[], int32_t length, int32_t &offset) const; + bool ParseRef(); + bool CheckModuleResourceItem(const std::shared_ptr &resourceItem, int32_t id); +#ifdef __WIN32 + bool LoadResourceItemWin(const std::string &filePath); +#endif + const PackageParser &packageParser_; + std::map>> items_; + std::map>> itemsForModule_; + std::vector> refs_; +}; +} +} +} +#endif \ No newline at end of file diff --git a/include/resource_data.h b/include/resource_data.h index 69fe913..66c1805 100644 --- a/include/resource_data.h +++ b/include/resource_data.h @@ -32,7 +32,7 @@ const static std::string ID_DEFINED_FILE = "id_defined.json"; const static std::string RESOURCE_INDEX_FILE = "resources.index"; const static std::string SEPARATOR = "/"; const static int32_t VERSION_MAX_LEN = 128; -static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 2.009" }; +static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 2.010" }; const static int32_t TAG_LEN = 4; enum class KeyType { diff --git a/include/resource_pack.h b/include/resource_pack.h index 968a109..b92be4a 100644 --- a/include/resource_pack.h +++ b/include/resource_pack.h @@ -43,6 +43,10 @@ private: uint32_t CopyRawFileImpl(const std::string &src, const std::string &dst) const; uint32_t GenerateConfigJson(); uint32_t ScanResources(const std::vector &inputs, const std::string &output); + uint32_t PackNormal(); + uint32_t PackPreview(); + uint32_t PackAppend(); + uint32_t PackCombine(); PackageParser packageParser_; std::string moduleName_; using HeaderCreater = std::function; diff --git a/include/resource_table.h b/include/resource_table.h index 232f369..5191ea7 100644 --- a/include/resource_table.h +++ b/include/resource_table.h @@ -17,6 +17,7 @@ #define OHOS_RESTOOL_RESOURCE_TABLE_H #include +#include #include "resource_item.h" #include "restool_errors.h" @@ -28,6 +29,7 @@ public: ResourceTable(); virtual ~ResourceTable(); uint32_t CreateResourceTable(); + uint32_t CreateResourceTable(const std::map>> &items); private: struct TableData { int32_t id; @@ -63,11 +65,12 @@ private: bool Prepare(const std::map> &configs, std::map &limitKeyConfigs, std::map &idSets, uint32_t &pos) const; - bool SaveRecordItem(const std::map> &configs, std::ofstream &out, + bool SaveRecordItem(const std::map> &configs, std::ostringstream &out, std::map &idSets, uint32_t &pos) const; - void SaveHeader(const IndexHeader &indexHeader, std::ofstream &out) const; - void SaveLimitKeyConfigs(const std::map &limitKeyConfigs, std::ofstream &out) const; - void SaveIdSets(const std::map &idSets, std::ofstream &out) const; + void SaveHeader(const IndexHeader &indexHeader, std::ostringstream &out) const; + void SaveLimitKeyConfigs(const std::map &limitKeyConfigs, + std::ostringstream &out) const; + void SaveIdSets(const std::map &idSets, std::ostringstream &out) const; std::string indexFilePath_; }; } diff --git a/include/resource_util.h b/include/resource_util.h index bbc9a24..be2483c 100644 --- a/include/resource_util.h +++ b/include/resource_util.h @@ -142,7 +142,21 @@ public: * @param key: string * @return hash string */ - static std::string GenerateHash(const std::string key); + static std::string GenerateHash(const std::string &key); + + /** + * @brief get an absolute pathname + * @param path pathname + * @return absolut pathname + */ + static std::string RealPath(const std::string &path); + + /** + * @brief check the directory is legal + * @param path pathname + * @return true is legal, other false; + */ + static bool IslegalPath(const std::string &path); private: enum class IgnoreType { IGNORE_FILE, diff --git a/src/append_compiler.cpp b/src/append_compiler.cpp new file mode 100644 index 0000000..eba4b54 --- /dev/null +++ b/src/append_compiler.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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 "append_compiler.h" +#include +#include "restool_errors.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; +AppendCompiler::AppendCompiler(ResType type, const string &output) : IResourceCompiler(type, output) +{ +} + +uint32_t AppendCompiler::CompileSingleFile(const FileInfo &fileInfo) +{ + ResourceItem resourceItem(fileInfo.filename, fileInfo.keyParams, type_); + resourceItem.SetFilePath(fileInfo.filePath); + resourceItem.SetLimitKey(fileInfo.limitKey); + + string data = fileInfo.filePath; + if (!resourceItem.SetData(reinterpret_cast(data.c_str()), data.length())) { + cerr << "Error: resource item set data fail, " << fileInfo.filePath << endl; + return RESTOOL_ERROR; + } + + if (!MergeResourceItem(resourceItem)) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} +} +} +} \ No newline at end of file diff --git a/src/cmd_parser.cpp b/src/cmd_parser.cpp index bbc17b4..471bd36 100644 --- a/src/cmd_parser.cpp +++ b/src/cmd_parser.cpp @@ -15,9 +15,8 @@ #include "cmd_parser.h" #include -#include "resource_util.h" - #include "cmd_list.h" +#include "resource_util.h" namespace OHOS { namespace Global { @@ -37,9 +36,11 @@ const struct option PackageParser::CMD_OPTS[] = { { "fileList", required_argument, nullptr, 'l' }, { "preview", no_argument, nullptr, 'a' }, { "priority", required_argument, nullptr, 'g' }, + { "append", required_argument, nullptr, 'x' }, + { "combine", required_argument, nullptr, 'z' }, }; -const string PackageParser::CMD_PARAMS = "i:p:o:r:m:j:e:c:l:g:afv"; +const string PackageParser::CMD_PARAMS = "i:p:o:r:m:j:e:c:l:g:x:afvz"; uint32_t PackageParser::Parse(int argc, char *argv[]) { @@ -102,13 +103,22 @@ const string &PackageParser::GetCachePath() const uint32_t PackageParser::AddInput(const string& argValue) { - auto ret = find_if(inputs_.begin(), inputs_.end(), [argValue](auto iter) {return argValue == iter;}); + string inputPath = ResourceUtil::RealPath(argValue); + if (inputPath.empty()) { + cerr << "Error: invalid input '" << argValue << "'" << endl; + return RESTOOL_ERROR; + } + + auto ret = find_if(inputs_.begin(), inputs_.end(), [inputPath](auto iter) {return inputPath == iter;}); if (ret != inputs_.end()) { cerr << "Error: repeat input '" << argValue << "'" << endl; return RESTOOL_ERROR; } - inputs_.push_back(argValue); + if (!IsAscii(inputPath)) { + return RESTOOL_ERROR; + } + inputs_.push_back(inputPath); return RESTOOL_SUCCESS; } @@ -130,7 +140,14 @@ uint32_t PackageParser::AddOutput(const string& argValue) return RESTOOL_ERROR; } - output_ = argValue; + output_ = ResourceUtil::RealPath(argValue); + if (output_.empty()) { + cerr << "Error: invalid output '" << argValue << "'" << endl; + return RESTOOL_ERROR; + } + if (!IsAscii(output_)) { + return RESTOOL_ERROR; + } return RESTOOL_SUCCESS; } @@ -204,7 +221,7 @@ uint32_t PackageParser::AddCachePath(const string& argValue) uint32_t PackageParser::CheckParam() const { - if (inputs_.empty()) { + if (inputs_.empty() && append_.empty()) { cerr << "Error: input path empty." << endl; return RESTOOL_ERROR; } @@ -214,7 +231,7 @@ uint32_t PackageParser::CheckParam() const return RESTOOL_ERROR; } - if (previewMode_) { + if (previewMode_ || !append_.empty()) { return RESTOOL_SUCCESS; } if (packageName_.empty()) { @@ -256,6 +273,59 @@ uint32_t PackageParser::SetPriority(const string& argValue) return RESTOOL_SUCCESS; } +uint32_t PackageParser::AddAppend(const string& argValue) +{ + string appendPath = ResourceUtil::RealPath(argValue); + if (appendPath.empty()) { + cout << "Warning: invaild compress '" << argValue << "'" << endl; + appendPath = argValue; + } + auto ret = find_if(append_.begin(), append_.end(), [appendPath](auto iter) {return appendPath == iter;}); + if (ret != append_.end()) { + cerr << "Error: repeat input '" << argValue << "'" << endl; + return RESTOOL_ERROR; + } + if (!IsAscii(appendPath)) { + return RESTOOL_ERROR; + } + append_.push_back(appendPath); + return RESTOOL_SUCCESS; +} + +const vector &PackageParser::GetAppend() const +{ + return append_; +} + +uint32_t PackageParser::SetCombine() +{ + combine_ = true; + return RESTOOL_SUCCESS; +} + +bool PackageParser::GetCombine() const +{ + return combine_; +} + +bool PackageParser::IsAscii(const string& argValue) const +{ +#ifdef __WIN32 + auto result = find_if(argValue.begin(), argValue.end(), [](auto iter) { + if ((iter & 0x80) != 0) { + return true; + } + return false; + }); + + if (result != argValue.end()) { + cerr << "Error: '" << argValue << "' must be ASCII" << endl; + return false; + } +#endif + return true; +} + void PackageParser::InitCommand() { using namespace placeholders; @@ -271,6 +341,8 @@ void PackageParser::InitCommand() handles_.emplace('c', bind(&PackageParser::AddCachePath, this, _1)); handles_.emplace('a', [this](const string &) -> uint32_t { return SetPreviewMode(); }); handles_.emplace('g', bind(&PackageParser::SetPriority, this, _1)); + handles_.emplace('x', bind(&PackageParser::AddAppend, this, _1)); + handles_.emplace('z', [this](const string &) -> uint32_t { return SetCombine(); }); } uint32_t PackageParser::HandleProcess(int c, const string& argValue) diff --git a/src/factory_resource_compiler.cpp b/src/factory_resource_compiler.cpp index d3e167c..d5cfd6f 100644 --- a/src/factory_resource_compiler.cpp +++ b/src/factory_resource_compiler.cpp @@ -14,6 +14,7 @@ */ #include "factory_resource_compiler.h" +#include "append_compiler.h" #include "generic_compiler.h" #include "json_compiler.h" #include "solid_xml_compiler.h" @@ -32,6 +33,17 @@ unique_ptr FactoryResourceCompiler::CreateCompiler(ResType ty return make_unique(type, output); } } + +unique_ptr FactoryResourceCompiler::CreateCompilerForAppend(ResType type, const string &output) +{ + if (type == ResType::ELEMENT) { + return make_unique(type, output); + } else if (type == ResType::MEDIA || type == ResType::PROF) { + return make_unique(type, output); + } else { + return nullptr; + } +} } } } \ No newline at end of file diff --git a/src/file_entry.cpp b/src/file_entry.cpp index 78aa8cc..ef6cc1c 100644 --- a/src/file_entry.cpp +++ b/src/file_entry.cpp @@ -19,6 +19,10 @@ #include "dirent.h" #include "sys/stat.h" #include "unistd.h" +#ifdef _WIN32 +#include "windows.h" +#include "shlwapi.h" +#endif namespace OHOS { namespace Global { @@ -54,9 +58,30 @@ bool FileEntry::Init() const vector> FileEntry::GetChilds() const { vector> children; - struct dirent *entry; string filePath = filePath_.GetPath(); +#ifdef _WIN32 + WIN32_FIND_DATA findData; + string temp(filePath + "\\*.*"); + HANDLE handle = FindFirstFile(temp.c_str(), &findData); + if (handle == INVALID_HANDLE_VALUE) { + return children; + } + + do { + string filename(findData.cFileName); + if (IsIgnore(filename)) { + continue; + } + + filePath = filePath_.GetPath() + SEPARATE + filename; + unique_ptr f = make_unique(filePath); + f->Init(); + children.push_back(move(f)); + } while (FindNextFile(handle, &findData)); + FindClose(handle); +#else DIR *handle = opendir(filePath.c_str()); + struct dirent *entry; while ((entry = readdir(handle)) != nullptr) { string filename(entry->d_name); if (IsIgnore(filename)) { @@ -69,6 +94,7 @@ const vector> FileEntry::GetChilds() const children.push_back(move(f)); } closedir(handle); +#endif return children; } @@ -84,10 +110,16 @@ const FileEntry::FilePath &FileEntry::GetFilePath() const bool FileEntry::Exist(const string &path) { +#ifdef _WIN32 + if (!PathFileExists(path.c_str())) { + return false; + } +#else struct stat s; if (stat(path.c_str(), &s) != 0) { return false; } +#endif return true; } @@ -110,8 +142,13 @@ bool FileEntry::CreateDirs(const string &path) return CreateDirsInner(path, 0); } -bool FileEntry::CopyFile(const string &src, const string &dst) +bool FileEntry::CopyFileInner(const string &src, const string &dst) { +#ifdef _WIN32 + if (!CopyFile(src.c_str(), dst.c_str(), false)) { + return false; + } +#else ifstream in(src, ios::binary); ofstream out(dst, ios::binary); if (!in || !out) { @@ -119,14 +156,51 @@ bool FileEntry::CopyFile(const string &src, const string &dst) return false; } out << in.rdbuf(); +#endif return true; } bool FileEntry::IsDirectory(const string &path) { +#ifdef _WIN32 + if (!PathIsDirectory(path.c_str())) { + return false; + } + return true; +#else struct stat s; stat(path.c_str(), &s); return S_ISDIR(s.st_mode); +#endif +} + +string FileEntry::RealPath(const string &path) +{ +#ifdef _WIN32 + char buffer[MAX_PATH]; + if (!PathCanonicalize(buffer, path.c_str())) { + return ""; + } + + if (PathIsRelative(buffer)) { + char current[MAX_PATH]; + if (!GetCurrentDirectory(MAX_PATH, current)) { + return ""; + } + + char temp[MAX_PATH]; + if (!PathCombine(temp, current, buffer)) { + return ""; + } + return string(temp); + } +#else + char buffer[PATH_MAX]; + if (!realpath(path.c_str(), buffer)) { + return ""; + } +#endif + return string(buffer); } FileEntry::FilePath::FilePath(const string &path) : filePath_(path) @@ -222,7 +296,7 @@ bool FileEntry::CreateDirsInner(const string &path, string::size_type offset) string::size_type pos = path.find_first_of(SEPARATE.front(), offset); if (pos == string::npos) { #if _WIN32 - return mkdir(path.c_str()) == 0; + return CreateDirectory(path.c_str(), nullptr) != 0; #else return mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0; #endif @@ -231,7 +305,7 @@ bool FileEntry::CreateDirsInner(const string &path, string::size_type offset) string subPath = path.substr(0, pos + 1); if (!Exist(subPath)) { #if _WIN32 - if (mkdir(subPath.c_str()) != 0) { + if (!CreateDirectory(subPath.c_str(), nullptr)) { #else if (mkdir(subPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { #endif diff --git a/src/i_resource_compiler.cpp b/src/i_resource_compiler.cpp index b3c598c..a9f26fd 100644 --- a/src/i_resource_compiler.cpp +++ b/src/i_resource_compiler.cpp @@ -109,6 +109,16 @@ uint32_t IResourceCompiler::Compile(const FileInfo &fileInfo) return PostCommit(); } +uint32_t IResourceCompiler::CompileForAppend(const FileInfo &fileInfo) +{ + return CompileSingleFile(fileInfo); +} + +const map, vector> &IResourceCompiler::GetResourceItems() const +{ + return nameInfos_; +} + void IResourceCompiler::SetModuleName(const string &moduleName) { moduleName_ = moduleName; diff --git a/src/reference_parser.cpp b/src/reference_parser.cpp index c799eec..68ffb2a 100644 --- a/src/reference_parser.cpp +++ b/src/reference_parser.cpp @@ -136,17 +136,39 @@ uint32_t ReferenceParser::ParseRefInProfile(const string &output) const } uint32_t ReferenceParser::ParseRefInJson(const string &filePath) const +{ + return ParseRefInJson(filePath, filePath); +} + +uint32_t ReferenceParser::ParseRefInJson(const string &from, const string &to) const { Json::Value root; - if (!ResourceUtil::OpenJsonFile(filePath, root)) { + if (!ResourceUtil::OpenJsonFile(from, root)) { return RESTOOL_ERROR; } - if (!ParseRefJsonImpl(root)) { + bool needSave = false; + if (!ParseRefJsonImpl(root, needSave)) { return RESTOOL_ERROR; } - if (!ResourceUtil::SaveToJsonFile(filePath, root)) { + if (!needSave) { + return RESTOOL_SUCCESS; + } + + if (!ResourceUtil::CreateDirs(FileEntry::FilePath(to).GetParent().GetPath())) { + return RESTOOL_ERROR; + } + + if (!ResourceUtil::SaveToJsonFile(to, root)) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t ReferenceParser::ParseRefInResourceItem(ResourceItem &resourceItem) const +{ + if (!ParseRefResourceItem(resourceItem)) { return RESTOOL_ERROR; } return RESTOOL_SUCCESS; @@ -295,25 +317,29 @@ bool ReferenceParser::ParseRefImpl(string &key, const map &refs return false; } -bool ReferenceParser::ParseRefJsonImpl(Json::Value &node) const +bool ReferenceParser::ParseRefJsonImpl(Json::Value &node, bool &needSave) const { if (node.isObject()) { for (const auto &member : node.getMemberNames()) { - if (!ParseRefJsonImpl(node[member])) { + if (!ParseRefJsonImpl(node[member], needSave)) { return false; } } } else if (node.isArray()) { for (Json::ArrayIndex i = 0; i < node.size(); i++) { - if (!ParseRefJsonImpl(node[i])) { + if (!ParseRefJsonImpl(node[i], needSave)) { return false; } } } else if (node.isString()) { string value = node.asString(); - if (!ParseRefString(value)) { + bool update = false; + if (!ParseRefString(value, update)) { return false; } + if (update) { + needSave = update; + } node = value; } return true; diff --git a/src/resource_append.cpp b/src/resource_append.cpp new file mode 100644 index 0000000..f0adb63 --- /dev/null +++ b/src/resource_append.cpp @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2022 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 "resource_append.h" +#include +#include +#include +#include +#include "config_parser.h" +#include "header.h" +#include "id_worker.h" +#include "key_parser.h" +#include "reference_parser.h" +#include "resource_table.h" +#include "resource_util.h" +#ifdef __WIN32 +#include "windows.h" +#endif +#include "securec.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; + +ResourceAppend::ResourceAppend(const PackageParser &packageParser) : packageParser_(packageParser) +{ +} + +uint32_t ResourceAppend::Append() +{ + string outputPath = packageParser_.GetOutput(); + for (const auto &iter : packageParser_.GetAppend()) { + if (!ScanResources(iter, outputPath)) { + return RESTOOL_ERROR; + } + } + return RESTOOL_SUCCESS; +} + +uint32_t ResourceAppend::Combine() +{ + for (const auto &iter : packageParser_.GetInputs()) { + if (!Combine(iter)) { + return RESTOOL_ERROR; + } + } + + if (!ParseRef()) { + return false; + } + + ResourceTable resourceTable; + if (resourceTable.CreateResourceTable(items_) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +// private + bool ResourceAppend::Combine(const string &folderPath) + { + FileEntry entry(folderPath); + if (!entry.Init()) { + return false; + } + + itemsForModule_.clear(); + for (const auto &child : entry.GetChilds()) { + if (!child->IsFile()) { + cerr << "Error:" << child->GetFilePath().GetPath() << " not file" << endl; + return false; + } + + if (!LoadResourceItem(child->GetFilePath().GetPath())) { + return false; + } + } + return true; + } + +bool ResourceAppend::ParseRef() +{ + for (auto &iter : refs_) { + ReferenceParser ref; + if (iter->GetResType() == ResType::PROF) { + string dst = FileEntry::FilePath(packageParser_.GetOutput()).Append(RESOURCES_DIR) + .Append("base").Append("profile").Append(iter->GetName()).GetPath(); + if (ref.ParseRefInJson(iter->GetFilePath(), dst) != RESTOOL_SUCCESS) { + return false; + } + + if (ResourceUtil::FileExist(dst)) { + iter->SetData(reinterpret_cast(dst.c_str()), dst.length()); + } + continue; + } + + if (ref.ParseRefInResourceItem(*iter) != RESTOOL_SUCCESS) { + return false; + } + } + return true; +} + +bool ResourceAppend::ScanResources(const string &resourcePath, const string &outputPath) +{ + if (!ResourceUtil::FileExist(resourcePath)) { + string filePath = FileEntry::FilePath(outputPath).Append(ResourceUtil::GenerateHash(resourcePath)).GetPath(); + if (remove(filePath.c_str()) != 0) { + cerr << "Error: remove '" << filePath << "'" << endl; + return false; + } + return true; + } + + FileEntry entry(resourcePath); + if (!entry.Init()) { + return false; + } + + if (entry.IsFile()) { + return ScanSingleFile(resourcePath, outputPath); + } + + vector keyParams; + if (KeyParser::Parse(entry.GetFilePath().GetFilename(), keyParams)) { + for (const auto &child : entry.GetChilds()) { + if(!ResourceUtil::IslegalPath(child->GetFilePath().GetFilename())){ + continue; + } + if(!ScanIegalResources(child->GetFilePath().GetPath(), outputPath)){ + return false; + } + } + return true; + } + + if (ResourceUtil::IslegalPath(entry.GetFilePath().GetFilename())){ + return ScanIegalResources(resourcePath, outputPath); + } + + for (const auto &child : entry.GetChilds()) { + string limitKey = child->GetFilePath().GetFilename(); + if (ResourceUtil::IsIgnoreFile(limitKey, child->IsFile())) { + continue; + } + + if (limitKey == RAW_FILE_DIR) { + if (!ScanRawFiles(child->GetFilePath().GetPath(), outputPath)) { + return false; + } + continue; + } + + if (child->IsFile()) { + cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl; + return false; + } + + if (!ScanLimitKey(child, limitKey, outputPath)) { + return false; + } + } + return true; +} + +bool ResourceAppend::ScanIegalResources(const string &resourcePath, const string &outputPath) +{ + FileEntry entry(resourcePath); + if (!entry.Init()) { + return false; + } + for (const auto &child : entry.GetChilds()) { + if(!ScanSingleFile(child->GetFilePath().GetPath(), outputPath)){ + return false; + } + } + return true; +} +bool ResourceAppend::ScanLimitKey(const unique_ptr &entry, + const string &limitKey, const string outputPath) +{ + vector keyParams; + if (!KeyParser::Parse(limitKey, keyParams)) { + cerr << "Error: " << entry->GetFilePath().GetPath() << ",invalid limit key '" << limitKey << "'" << endl; + return false; + } + + for (const auto &child : entry->GetChilds()) { + string fileCuster = child->GetFilePath().GetFilename(); + if (ResourceUtil::IsIgnoreFile(fileCuster, child->IsFile())) { + continue; + } + + if (child->IsFile()) { + cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl; + return false; + } + + ResType resType = ResourceUtil::GetResTypeByDir(fileCuster); + if (resType == ResType::INVALID_RES_TYPE) { + cerr << "Error: " << child->GetFilePath().GetPath() << " invalid" << endl; + return false; + } + + DirectoryInfo directoryInfo = { limitKey, fileCuster, child->GetFilePath().GetPath(), keyParams, resType}; + if (!ScanFiles(child, directoryInfo, outputPath)) { + return false; + } + } + return true; +} + + +bool ResourceAppend::ScanFiles(const unique_ptr &entry, + const DirectoryInfo &directoryInfo, const string &outputPath) +{ + for (const auto &child : entry->GetChilds()) { + string filename = child->GetFilePath().GetFilename(); + if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) { + continue; + } + + if (!child->IsFile()) { + cerr << "Error: '" << child->GetFilePath().GetPath() << "' not regular." << endl; + return false; + } + + FileInfo fileInfo = {directoryInfo, child->GetFilePath().GetPath(), filename}; + if (!ScanFile(fileInfo, outputPath)) { + return false; + } + } + return true; +} + +bool ResourceAppend::ScanFile(const FileInfo &fileInfo, const string &outputPath) +{ + unique_ptr resourceCompiler = + FactoryResourceCompiler::CreateCompilerForAppend(fileInfo.dirType, outputPath); + if (resourceCompiler == nullptr) { + return true; + } + + if (resourceCompiler->CompileForAppend(fileInfo) != RESTOOL_SUCCESS) { + return false; + } + + ostringstream outStream; + const auto &items = resourceCompiler->GetResourceItems(); + for (const auto &item : items) { + for (const auto &resourceItem : item.second) { + if (!WriteResourceItem(resourceItem, outStream)) { + return false; + } + } + } + + string hash = ResourceUtil::GenerateHash(fileInfo.filePath); + FileEntry::FilePath output(outputPath); + if (!WriteFileInner(outStream, output.Append(hash).GetPath())) { + return false; + } + return true; +} + + bool ResourceAppend::ScanSingleFile(const string &filePath, const string &outputPath) + { + if (filePath.find(RAW_FILE_DIR) != string::npos) { + return WriteRawFile(filePath, outputPath); + } + + FileEntry::FilePath path(filePath); + string fileCuster = path.GetParent().GetFilename(); + ResType resType = ResourceUtil::GetResTypeByDir(fileCuster); + if (resType == ResType::INVALID_RES_TYPE) { + cerr << "Error: invalid resType '" << filePath << "'" << endl; + return false; + } + + string limitKey = path.GetParent().GetParent().GetFilename(); + vector keyParams; + if (!KeyParser::Parse(limitKey, keyParams)) { + cerr << "Error: invalid limit key '" << filePath << "'" << endl; + return false; + } + + DirectoryInfo directoryInfo = {limitKey, fileCuster, path.GetParent().GetPath(), keyParams, resType}; + FileInfo fileInfo = {directoryInfo, filePath, path.GetFilename() }; + if (!ScanFile(fileInfo, outputPath)) { + return false; + } + return true; + } + +bool ResourceAppend::WriteFileInner(ostringstream &outStream, const string &outputPath) const +{ +#ifdef __WIN32 + HANDLE hWriteFile = CreateFile(outputPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, + nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hWriteFile == INVALID_HANDLE_VALUE) { + cerr << "Error: '" << outputPath << "' " << GetLastError() << endl; + return false; + } + + DWORD writeBytes; + if (!WriteFile(hWriteFile, outStream.str().c_str(), outStream.tellp(), &writeBytes, nullptr)) { + cerr << "Error: write '" << outputPath << "' " << GetLastError() << endl; + CloseHandle(hWriteFile); + return false; + } + CloseHandle(hWriteFile); +#else + ofstream out(outputPath, ofstream::out | ofstream::binary); + if (!out.is_open()) { + cerr << "Error: open fail '" << outputPath << "'" << endl; + return false; + } + out << outStream.str(); +#endif + return true; +} + +bool ResourceAppend::WriteResourceItem(const ResourceItem &resourceItem, ostringstream &out) +{ + int32_t size = resourceItem.GetName().length(); + out.write(reinterpret_cast(&size), sizeof(int32_t)); + out.write(reinterpret_cast(resourceItem.GetName().c_str()), size); + + size = resourceItem.GetLimitKey().length(); + out.write(reinterpret_cast(&size), sizeof(int32_t)); + out.write(reinterpret_cast(resourceItem.GetLimitKey().c_str()),size); + + size = resourceItem.GetFilePath().length(); + out.write(reinterpret_cast(&size), sizeof(int32_t)); + out.write(reinterpret_cast(resourceItem.GetFilePath().c_str()), size); + + int32_t type = static_cast(resourceItem.GetResType()); + out.write(reinterpret_cast(&type), sizeof(int32_t)); + + size = resourceItem.GetKeyParam().size(); + out.write(reinterpret_cast(&size), sizeof(int32_t)); + for (const auto &keyParam : resourceItem.GetKeyParam()) { + out.write(reinterpret_cast(&keyParam.keyType), sizeof(int32_t)); + out.write(reinterpret_cast(&keyParam.value), sizeof(int32_t)); + } + + size = resourceItem.GetDataLength(); + out.write(reinterpret_cast(&size), sizeof(int32_t)); + out.write(reinterpret_cast(resourceItem.GetData()), size); + return true; +} + +bool ResourceAppend::LoadResourceItem(const string &filePath) +{ +#ifdef __WIN32 + return LoadResourceItemWin(filePath); +#else + ifstream in(filePath, ifstream::in | ifstream::binary); + if (!in.is_open()) { + cerr << "Error: open fail '" << filePath << "'" << endl; + return false; + } + + in.seekg(0, in.end); + int32_t length = in.tellg(); + in.seekg(0, in.beg); + if (length <= 0) { + cerr << "Error: invalid '" << filePath << "' file size=" << length << endl; + return false; + } + char buffer[length]; + in.read(buffer, length); + return LoadResourceItemFromMem(buffer, length); +#endif +} + +bool ResourceAppend::ScanRawFiles(const string &path, const string &outputPath) +{ + FileEntry entry(path); + if (!entry.Init()) { + return false; + } + + for (const auto &child : entry.GetChilds()) { + string filename = child->GetFilePath().GetFilename(); + if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) { + continue; + } + + bool ret = false; + if (child->IsFile()) { + ret = WriteRawFile(child->GetFilePath().GetPath(), outputPath); + } else { + ret = ScanRawFiles(child->GetFilePath().GetPath(), outputPath); + } + + if (!ret) { + return false; + } + } + return true; +} + +bool ResourceAppend::WriteRawFile(const string &filePath, const string &outputPath) +{ + string::size_type pos = filePath.find(RAW_FILE_DIR); + if (pos == string::npos) { + cerr << "Error: invaild raw file '" << filePath << "'" << endl; + return false; + } + + string sub = filePath.substr(pos); + sub = FileEntry::FilePath(RESOURCES_DIR).Append(sub).GetPath(); + vector keyParams; + ResourceItem resourceItem("", keyParams, ResType::RAW); + resourceItem.SetData(sub); + resourceItem.SetFilePath(filePath); + resourceItem.SetLimitKey(""); + + ostringstream outStream; + if (!WriteResourceItem(resourceItem, outStream)) { + return false; + } + + string hash = ResourceUtil::GenerateHash(filePath); + FileEntry::FilePath output(outputPath); + if (!WriteFileInner(outStream, output.Append(hash).GetPath())) { + return false; + } + return true; +} + +bool ResourceAppend::Push(const shared_ptr &resourceItem) +{ + string idName = ResourceUtil::GetIdName(resourceItem->GetName(), resourceItem->GetResType()); + int32_t id = IdWorker::GetInstance().GenerateId(resourceItem->GetResType(), idName); + if (id < 0) { + return false; + } + + if (!CheckModuleResourceItem(resourceItem, id)) { + return false; + } + + const auto &result = items_.find(id); + if (result == items_.end()) { + items_[id].push_back(resourceItem); + AddRef(resourceItem); + return true; + } + + if (find_if(result->second.begin(), result->second.end(), [resourceItem](auto &iter) { + return resourceItem->GetLimitKey() == iter->GetLimitKey(); + }) != result->second.end()) { + return true; + } + + items_[id].push_back(resourceItem); + AddRef(resourceItem); + return true; +} + +void ResourceAppend::AddRef(const shared_ptr &resourceItem) +{ + string data(reinterpret_cast(resourceItem->GetData()), resourceItem->GetDataLength()); + ResType resType = resourceItem->GetResType(); + if (resType == ResType::MEDIA) { + return; + } + + if (resType == ResType::PROF) { + if (resourceItem->GetLimitKey() != "base" || + FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() != ".json") { + return; + } + refs_.push_back(resourceItem); + return; + } + + if (regex_match(data, regex(".*\\$.+:.*"))) { + refs_.push_back(resourceItem); + } +} + +bool ResourceAppend::LoadResourceItemFromMem(const char buffer[], int32_t length) +{ + int32_t offset = 0; + do { + // name + string nameStr = ParseString(buffer, length, offset); + // limit key + string limitKeyStr = ParseString(buffer, length, offset); + // file path + string filePathStr = ParseString(buffer, length, offset);; + // ResType + int32_t type = ParseInt32(buffer, length, offset); + ResType resType = static_cast(type); + // keyParam + int32_t keyParamSize = ParseInt32(buffer, length, offset); + vector keyParams; + for (int i = 0; i < keyParamSize; i++) { + KeyParam keyParam; + keyParam.keyType = static_cast(ParseInt32(buffer, length, offset)); + keyParam.value = ParseInt32(buffer, length, offset); + keyParams.push_back(keyParam); + } + // data + string data = ParseString(buffer, length, offset); + if (resType == ResType::RAW) { + FileEntry::FilePath outPath(packageParser_.GetOutput()); + if (!ResourceUtil::CreateDirs(outPath.Append(data).GetParent().GetPath())) { + return false; + } + + if (!ResourceUtil::CopyFleInner(filePathStr, outPath.Append(data).GetPath())) { + return false; + } + continue; + } + + shared_ptr resourceItem = make_shared(nameStr, keyParams, resType); + resourceItem->SetData(reinterpret_cast(data.c_str()), data.length()); + resourceItem->SetLimitKey(limitKeyStr); + resourceItem->SetFilePath(filePathStr); + if (!Push(resourceItem)) { + return false; + } + } while (offset < length); + return true; +} + +string ResourceAppend::ParseString(const char buffer[], int32_t length, int32_t &offset) const +{ + int32_t size = ParseInt32(buffer, length, offset); + if (size < 0 || offset + size > length) { + offset = length; + return ""; + } + + if (size == 0) { + return ""; + } + + string value(buffer + offset, size); + offset += size; + return value; +} + +int32_t ResourceAppend::ParseInt32(const char buffer[], int32_t length, int32_t &offset) const +{ + if (offset + static_cast(sizeof(int32_t)) > length) { + offset = length; + return -1; + } + + int32_t size = 0; + if (memcpy_s(&size, sizeof(int32_t), buffer + offset, sizeof(int32_t)) != EOK) { + offset = length; + return -1; + } + offset += sizeof(int32_t); + return size; +} + +bool ResourceAppend::CheckModuleResourceItem(const shared_ptr &resourceItem, int32_t id) +{ + const auto &result = itemsForModule_.find(id); + if (result == itemsForModule_.end()) { + itemsForModule_[id].push_back(resourceItem); + return true; + } + + const auto &ret = find_if(result->second.begin(), result->second.end(), [resourceItem](auto iter) { + return resourceItem->GetLimitKey() == iter->GetLimitKey(); + }); + + if (ret != result->second.end()) { + string error = "'" + resourceItem->GetName() + "' conflict, first declared in " + (*ret)->GetFilePath() + \ + ", but declared again in " + resourceItem->GetFilePath(); + cerr << "Error: " << error << endl; + return false; + } + + itemsForModule_[id].push_back(resourceItem); + return true; +} + +#ifdef __WIN32 +bool ResourceAppend::LoadResourceItemWin(const string &filePath) +{ + bool result = false; + HANDLE hReadFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS, nullptr); + if (hReadFile == INVALID_HANDLE_VALUE) { + cerr << "Error: '" << filePath << "' " << GetLastError() << endl; + return result; + } + + DWORD fileSize = GetFileSize(hReadFile, nullptr); + HANDLE hFileMap = CreateFileMapping(hReadFile, nullptr, PAGE_READONLY, 0, fileSize, nullptr); + if (hFileMap == INVALID_HANDLE_VALUE) { + cerr << "Error: create file mapping " << GetLastError() << endl; + CloseHandle(hReadFile); + return result; + } + + void * pBuffer = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); + if (pBuffer == nullptr) { + cerr << "Error: map view of file " << GetLastError() << endl; + CloseHandle(hReadFile); + return result; + } + + char * buffer = reinterpret_cast(pBuffer); + result = LoadResourceItemFromMem(buffer, fileSize); + UnmapViewOfFile(hFileMap); + CloseHandle(hReadFile); + return result; +} +#endif +} +} +} \ No newline at end of file diff --git a/src/resource_pack.cpp b/src/resource_pack.cpp index 6cf0cbf..9fe369f 100644 --- a/src/resource_pack.cpp +++ b/src/resource_pack.cpp @@ -22,7 +22,7 @@ #include "increment_manager.h" #include "resource_merge.h" #include "resource_table.h" - +#include "resource_append.h" #include "preview_manager.h" namespace OHOS { @@ -36,40 +36,17 @@ ResourcePack::ResourcePack(const PackageParser &packageParser):packageParser_(pa uint32_t ResourcePack::Package() { if (packageParser_.GetPreviewMode()) { - PreviewManager preview; - preview.SetPriority(packageParser_.GetPriority()); - return preview.ScanModules(packageParser_.GetInputs(), packageParser_.GetOutput()); - } - if (Init() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; + return PackPreview(); } - ResourceMerge resourceMerge; - if (resourceMerge.Init() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; + if (!packageParser_.GetAppend().empty()) { + return PackAppend(); } - if (ScanResources(resourceMerge.GetInputs(), packageParser_.GetOutput()) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; + if (packageParser_.GetCombine()) { + return PackCombine(); } - - if (GenerateHeader() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - - if (CopyRawFile(resourceMerge.GetInputs()) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - - if (GenerateConfigJson() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - - ResourceTable resourceTable; - if (resourceTable.CreateResourceTable() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - return RESTOOL_SUCCESS; + return PackNormal(); } // below private founction @@ -358,6 +335,77 @@ uint32_t ResourcePack::ScanResources(const vector &inputs, const string } return RESTOOL_SUCCESS; } + +uint32_t ResourcePack::PackNormal() +{ + if (Init() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + ResourceMerge resourceMerge; + if (resourceMerge.Init() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (ScanResources(resourceMerge.GetInputs(), packageParser_.GetOutput()) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (GenerateHeader() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (CopyRawFile(resourceMerge.GetInputs()) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (GenerateConfigJson() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + ResourceTable resourceTable; + if (resourceTable.CreateResourceTable() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t ResourcePack::PackPreview() +{ + PreviewManager preview; + preview.SetPriority(packageParser_.GetPriority()); + return preview.ScanModules(packageParser_.GetInputs(), packageParser_.GetOutput()); +} + +uint32_t ResourcePack::PackAppend() +{ + ResourceAppend resourceAppend(packageParser_); + if (!packageParser_.GetAppend().empty()) { + return resourceAppend.Append(); + } + return RESTOOL_SUCCESS; +} + +uint32_t ResourcePack::PackCombine() +{ + if (Init() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + ResourceAppend resourceAppend(packageParser_); + if (resourceAppend.Combine() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (GenerateConfigJson() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (GenerateHeader() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} } } } diff --git a/src/resource_table.cpp b/src/resource_table.cpp index dc716dc..c6ea461 100644 --- a/src/resource_table.cpp +++ b/src/resource_table.cpp @@ -58,6 +58,27 @@ uint32_t ResourceTable::CreateResourceTable() return RESTOOL_SUCCESS; } +uint32_t ResourceTable::CreateResourceTable(const map>> &items) +{ + map> configs; + for (const auto &item : items) { + for (const auto &resourceItemPtr : item.second) { + if (resourceItemPtr->GetResType() == ResType::ID) { + break; + } + TableData tableData; + tableData.id = item.first; + tableData.resourceItem = *resourceItemPtr; + configs[resourceItemPtr->GetLimitKey()].push_back(tableData); + } + } + + if (SaveToResouorceIndex(configs) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + // below private uint32_t ResourceTable::SaveToResouorceIndex(const map> &configs) const { @@ -80,14 +101,18 @@ uint32_t ResourceTable::SaveToResouorceIndex(const map return RESTOOL_ERROR; } - if (!SaveRecordItem(configs, out, idSets, pos)) { + ostringstream outStreamData; + if (!SaveRecordItem(configs, outStreamData, idSets, pos)) { return RESTOOL_ERROR; } + ostringstream outStreamHeader; indexHeader.fileSize = pos; - SaveHeader(indexHeader, out); - SaveLimitKeyConfigs(limitKeyConfigs, out); - SaveIdSets(idSets, out); + SaveHeader(indexHeader, outStreamHeader); + SaveLimitKeyConfigs(limitKeyConfigs, outStreamHeader); + SaveIdSets(idSets, outStreamHeader); + out << outStreamHeader.str(); + out << outStreamData.str(); return RESTOOL_SUCCESS; } @@ -139,9 +164,8 @@ bool ResourceTable::Prepare(const map> &configs, } bool ResourceTable::SaveRecordItem(const map> &configs, - ofstream &out, map &idSets, uint32_t &pos) const + ostringstream &out, map &idSets, uint32_t &pos) const { - out.seekp(pos); for (const auto &config : configs) { auto idSet = idSets.find(config.first); if (idSet == idSets.end()) { @@ -178,15 +202,14 @@ bool ResourceTable::SaveRecordItem(const map> &configs return true; } -void ResourceTable::SaveHeader(const IndexHeader &indexHeader, std::ofstream &out) const +void ResourceTable::SaveHeader(const IndexHeader &indexHeader, ostringstream &out) const { - out.seekp(0); out.write(reinterpret_cast(&indexHeader.version), VERSION_MAX_LEN); out.write(reinterpret_cast(&indexHeader.fileSize), sizeof(uint32_t)); out.write(reinterpret_cast(&indexHeader.limitKeyConfigSize), sizeof(uint32_t)); } -void ResourceTable::SaveLimitKeyConfigs(const map &limitKeyConfigs, ofstream &out) const +void ResourceTable::SaveLimitKeyConfigs(const map &limitKeyConfigs, ostringstream &out) const { for (const auto &iter : limitKeyConfigs) { out.write(reinterpret_cast(iter.second.keyTag), TAG_LEN); @@ -198,7 +221,7 @@ void ResourceTable::SaveLimitKeyConfigs(const map &limit } } -void ResourceTable::SaveIdSets(const map &idSets, ofstream &out) const +void ResourceTable::SaveIdSets(const map &idSets, ostringstream &out) const { for (const auto &iter : idSets) { out.write(reinterpret_cast(iter.second.idTag), TAG_LEN); diff --git a/src/resource_util.cpp b/src/resource_util.cpp index f47c1db..761aa44 100644 --- a/src/resource_util.cpp +++ b/src/resource_util.cpp @@ -18,10 +18,8 @@ #include #include #include +#include #include "file_entry.h" -#ifdef __WIN32 -#include "windows.h" -#endif namespace OHOS { namespace Global { @@ -214,17 +212,10 @@ ResType ResourceUtil::GetResTypeFromString(const string &type) bool ResourceUtil::CopyFleInner(const string &src, const string &dst) { -#ifdef __WIN32 - if (!CopyFileA(src.c_str(), dst.c_str(), false)) { + if (!FileEntry::CopyFileInner(src, dst)) { cerr << "Error: copy file fail from '" << src << "' to '" << dst << "'" << endl; return false; } -#else - if (!FileEntry::CopyFile(src, dst)) { - cerr << "Error: copy file fail from '" << src << "' to '" << dst << "'" << endl; - return false; - } -#endif return true; } @@ -266,11 +257,20 @@ bool ResourceUtil::NeedConverToSolidXml(ResType resType) return false; } -string ResourceUtil::GenerateHash(const std::string key) +string ResourceUtil::GenerateHash(const string &key) { hash hash_function; return to_string(hash_function(key)); } + +string ResourceUtil::RealPath(const string &path) +{ + return FileEntry::RealPath(path); +} +bool ResourceUtil::IslegalPath(const string &path) +{ + return path == "element" || path == "media" || path == "profile"; +} } } } diff --git a/src/task_handle.cpp b/src/task_handle.cpp index bd329b9..9067917 100644 --- a/src/task_handle.cpp +++ b/src/task_handle.cpp @@ -14,7 +14,6 @@ */ #include "task_handle.h" - #include "resource_pack.h" namespace OHOS {