diff --git a/BUILD.gn b/BUILD.gn index 85ac654..3f045a9 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -18,7 +18,6 @@ import("./restool.gni") ohos_executable("restool") { sources = [ "src/append_compiler.cpp", - "src/cmd_list.cpp", "src/cmd_parser.cpp", "src/config_parser.cpp", "src/factory_resource_compiler.cpp", @@ -27,10 +26,12 @@ ohos_executable("restool") { "src/generic_compiler.cpp", "src/header.cpp", "src/i_resource_compiler.cpp", + "src/id_defined_parser.cpp", "src/id_worker.cpp", "src/json_compiler.cpp", "src/key_parser.cpp", "src/reference_parser.cpp", + "src/resconfig_parser.cpp", "src/resource_append.cpp", "src/resource_check.cpp", "src/resource_directory.cpp", @@ -53,7 +54,7 @@ ohos_executable("restool") { deps = [ "//third_party/bounds_checking_function:libsec_static", - "//third_party/jsoncpp:jsoncpp_static", + "//third_party/cJSON:cjson_static", "//third_party/libpng:libpng_static", ] diff --git a/README.md b/README.md index 6e6cf1d..8e10d0d 100644 --- a/README.md +++ b/README.md @@ -50,11 +50,9 @@ entry Directory Structure **global_resource_tool** -[third_party_libxml2](https://gitee.com/openharmony/third_party_libxml2/blob/master/README.md) +[third_party_cJSON](https://gitee.com/openharmony/third_party_cJSON/blob/master/README.md) -[third_party_jsoncpp](https://gitee.com/openharmony/third_party_jsoncpp/blob/master/README.md) - -[third_party_sqlite](https://gitee.com/openharmony/third_party_sqlite/blob/master/README.md) +[third_party_libpng](https://gitee.com/openharmony/third_party_libpng/blob/master/README.md) [third_party_bounds_checking_function](https://gitee.com/openharmony/third_party_bounds_checking_function/blob/master/README.en.md) diff --git a/README_zh.md b/README_zh.md index afddf12..a05b73a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -120,10 +120,8 @@ restool -i entry/src/main -j entry/src/main/module.json -p com.ohos.demo -o out **global_resource_tool** -[third_party_libxml2](https://gitee.com/openharmony/third_party_libxml2/blob/master/README.md) +[third_party_cJSON](https://gitee.com/openharmony/third_party_cJSON/blob/master/README.md) -[third_party_jsoncpp](https://gitee.com/openharmony/third_party_jsoncpp/blob/master/README.md) - -[third_party_sqlite](https://gitee.com/openharmony/third_party_sqlite/blob/master/README.md) +[third_party_libpng](https://gitee.com/openharmony/third_party_libpng/blob/master/README.md) [third_party_bounds_checking_function](https://gitee.com/openharmony/third_party_bounds_checking_function/blob/master/README.md ) diff --git a/bundle.json b/bundle.json index f1f8727..01e4a5a 100644 --- a/bundle.json +++ b/bundle.json @@ -14,14 +14,14 @@ "subsystem": "developtools", "syscap": [], "feature": [], - "adapted_system_type": ["mini", "small", "standard" ], + "adapted_system_type": [ "mini", "small", "standard" ], "rom": "0KB", "ram": "0KB", "deps": { "components": [], "third_party": [ "bounds_checking_function", - "jsoncpp", + "cJSON", "libpng" ] }, diff --git a/include/config_parser.h b/include/config_parser.h index b6d25ce..2927583 100644 --- a/include/config_parser.h +++ b/include/config_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -18,6 +18,7 @@ #include #include +#include #include "resource_util.h" namespace OHOS { @@ -67,25 +68,24 @@ public: return useModule_ ? MODULE_JSON : CONFIG_JSON; }; private: - bool ParseModule(Json::Value &moduleNode); - bool ParseDistro(Json::Value &distroNode); - bool ParseAbilities(const Json::Value &abilites); - bool ParseAbilitiy(const Json::Value &ability, bool &isMainAbility); - bool IsMainAbility(const Json::Value &skills); - bool IsHomeAction(const Json::Value &actions); + bool ParseModule(cJSON *moduleNode); + bool ParseDistro(cJSON *distroNode); + bool ParseAbilities(const cJSON *abilities); + bool ParseAbilitiy(const cJSON *ability, bool &isMainAbility); + bool IsMainAbility(const cJSON *skills); + bool IsHomeAction(const cJSON *actions); bool dependEntry = false; - bool ParseRefImpl(Json::Value &parent, const std::string &key, Json::Value &node); - bool ParseJsonArrayRef(Json::Value &parent, const std::string &key, Json::Value &node); - bool ParseJsonStringRef(Json::Value &parent, const std::string &key, Json::Value &node); + bool ParseRefImpl(cJSON *parent, const std::string &key, cJSON *node); + bool ParseJsonArrayRef(cJSON *parent, const std::string &key, cJSON *node); + bool ParseJsonStringRef(cJSON *parent, const std::string &key, cJSON *node); bool GetRefIdFromString(std::string &value, bool &update, const std::string &match) const; bool ParseModuleType(const std::string &type); - bool ParseAbilitiesForDepend(Json::Value &moduleNode); + bool ParseAbilitiesForDepend(cJSON *moduleNode); void AddCheckNode(const std::string &key, uint32_t id); std::string filePath_; std::string packageName_; std::string moduleName_; ModuleType moduleType_; - Json::Value rootNode_; std::string mainAbility_; int32_t abilityIconId_; int32_t abilityLabelId_; @@ -94,6 +94,7 @@ private: static const std::map JSON_STRING_IDS; static const std::map JSON_ARRAY_IDS; static bool useModule_; + cJSON *root_; }; } } diff --git a/include/generic_compiler.h b/include/generic_compiler.h index 08d36eb..669ac2b 100644 --- a/include/generic_compiler.h +++ b/include/generic_compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -32,7 +32,6 @@ private: std::string GetOutputFilePath(const FileInfo &fileInfo) const; bool IsIgnore(const FileInfo &fileInfo) const; bool CopyFile(const FileInfo &fileInfo) const; - bool IsConvertToSolidXml(const FileInfo &fileInfo) const; }; } } diff --git a/include/header.h b/include/header.h index 3b27361..a7f78bf 100644 --- a/include/header.h +++ b/include/header.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -16,9 +16,10 @@ #ifndef OHOS_RESTOOL_HEADER_H #define OHOS_RESTOOL_HEADER_H -#include -#include -#include +#include +#include +#include +#include #include "id_worker.h" #include "restool_errors.h" @@ -31,7 +32,7 @@ public: Header(const std::string &outputPath); virtual ~Header(); using HandleHeaderTail = std::function; - using HandleBody = std::function; + using HandleBody = std::function; uint32_t Create(HandleHeaderTail headerHandler, HandleBody bodyHander, HandleHeaderTail tailHander) const; private: const std::string &outputPath_; diff --git a/include/id_defined_parser.h b/include/id_defined_parser.h new file mode 100755 index 0000000..504886b --- /dev/null +++ b/include/id_defined_parser.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 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_ID_DEFINED_PARSER_H +#define OHOS_RESTOOL_ID_DEFINED_PARSER_H + +#include +#include +#include "cmd_parser.h" + +namespace OHOS { +namespace Global { +namespace Restool { +class IdDefinedParser { +public: + IdDefinedParser(const PackageParser &packageParser, const ResourceIdCluster &type); + virtual ~IdDefinedParser(); + std::map, ResourceId> &GetSysDefinedIds() + { + return sysDefinedIds_; + } + std::map, ResourceId> &GetAppDefinedIds() + { + return appDefinedIds_; + } + uint32_t Init(); +private: + uint32_t Init(const std::string &filePath, bool isSystem); + using ParseFunction = std::function; + void InitParser(); + uint32_t IdDefinedToResourceIds(const cJSON *record, bool isSystem, const int32_t strtSysId = 0); + bool ParseType(const cJSON *type, ResourceId &resourceId); + bool ParseName(const cJSON *name, ResourceId &resourceId); + bool ParseOrder(const cJSON *order, ResourceId &resourceId); + bool ParseId(const cJSON *id, ResourceId &resourceId); + bool PushResourceId(const ResourceId &resourceId, bool isSystem); + int32_t GetStartId() const; + std::map, ResourceId> sysDefinedIds_; + std::map, ResourceId> appDefinedIds_; + std::map idDefineds_; + std::map handles_; + const PackageParser packageParser_; + static const int32_t START_SYS_ID; + ResourceIdCluster type_; + cJSON *root_; +}; +} +} +} +#endif \ No newline at end of file diff --git a/include/id_worker.h b/include/id_worker.h index d304688..b7705fd 100644 --- a/include/id_worker.h +++ b/include/id_worker.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -16,31 +16,18 @@ #ifndef OHOS_RESTOOL_ID_WORKER_H #define OHOS_RESTOOL_ID_WORKER_H -#include -#include -#include "singleton.h" +#include +#include "id_defined_parser.h" #include "resource_data.h" #include "resource_util.h" +#include "singleton.h" namespace OHOS { namespace Global { namespace Restool { class IdWorker : public Singleton { public: - enum class ResourceIdCluster { - RES_ID_APP = 0, - RES_ID_SYS, - RES_ID_TYPE_MAX, - }; - - struct ResourceId { - int32_t id; - int32_t seq; - std::string type; - std::string name; - }; - - uint32_t Init(ResourceIdCluster type, int32_t start = 0x01000000); + uint32_t Init(ResourceIdCluster &type, int32_t start = 0x01000000); int32_t GenerateId(ResType resType, const std::string &name); std::vector GetHeaderId() const; int32_t GetId(ResType resType, const std::string &name) const; @@ -52,18 +39,6 @@ public: private: int32_t GenerateAppId(ResType resType, const std::string &name); int32_t GenerateSysId(ResType resType, const std::string &name); - uint32_t InitIdDefined(); - uint32_t InitIdDefined(const std::string &filePath, bool isSystem); - uint32_t IdDefinedToResourceIds(const Json::Value &record, bool isSystem, const int32_t strtSysId = 0); - using ParseFunction = std::function; - void InitParser(); - bool ParseType(const Json::Value &type, ResourceId &resourceId); - bool ParseName(const Json::Value &name, ResourceId &resourceId); - bool ParseOrder(const Json::Value &order, ResourceId &resourceId); - bool ParseId(const Json::Value &id, ResourceId &resourceId); - bool PushResourceId(const ResourceId &resourceId, bool isSystem); - bool IsValidSystemName(const std::string &name) const; - int32_t GetStartId(const Json::Value &root) const; int32_t GetMaxId(int32_t startId) const; int32_t GetCurId(); int32_t appId_; @@ -72,11 +47,8 @@ private: std::map, int32_t> ids_; std::map, ResourceId> sysDefinedIds_; std::map, ResourceId> appDefinedIds_; - std::map idDefineds_; - std::map handles_; std::vector delIds_; std::map, int32_t> cacheIds_; - static const int32_t START_SYS_ID; }; } } diff --git a/include/json_compiler.h b/include/json_compiler.h index f24891c..cf6bb5a 100644 --- a/include/json_compiler.h +++ b/include/json_compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -17,6 +17,7 @@ #define OHOS_RESTOOL_JSON_COMPILER_H #include +#include #include "i_resource_compiler.h" #include "resource_util.h" @@ -31,34 +32,34 @@ protected: uint32_t CompileSingleFile(const FileInfo &fileInfo) override; private: void InitParser(); - bool ParseJsonArrayLevel(const Json::Value &arrayNode, const FileInfo &fileInfo); - bool ParseJsonObjectLevel(const Json::Value &objectNode, const FileInfo &fileInfo); + bool ParseJsonArrayLevel(const cJSON *arrayNode, const FileInfo &fileInfo); + bool ParseJsonObjectLevel(const cJSON *objectNode, const FileInfo &fileInfo); - using HandleResource = std::function; - bool HandleString(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleInteger(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleBoolean(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleColor(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleFloat(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleStringArray(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleIntegerArray(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleTheme(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandlePattern(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandlePlural(const Json::Value &objectNode, ResourceItem &resourceItem) const; - bool HandleSymbol(const Json::Value &objectNode, ResourceItem &resourceItem) const; + using HandleResource = std::function; + bool HandleString(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleInteger(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleBoolean(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleColor(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleFloat(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleStringArray(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleIntegerArray(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleTheme(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandlePattern(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandlePlural(const cJSON *objectNode, ResourceItem &resourceItem) const; + bool HandleSymbol(const cJSON *objectNode, ResourceItem &resourceItem) const; bool PushString(const std::string &value, ResourceItem &resourceItem) const; - bool CheckJsonStringValue(const Json::Value &valueNode, const ResourceItem &resourceItem) const; - bool CheckJsonIntegerValue(const Json::Value &valueNode, const ResourceItem &resourceItem) const; - bool CheckJsonSymbolValue(const Json::Value &valueNode, const ResourceItem &resourceItem) const; - using HandleValue = std::function&)>; - bool ParseValueArray(const Json::Value &objectNode, ResourceItem &resourceItem, + bool CheckJsonStringValue(const cJSON *valueNode, const ResourceItem &resourceItem) const; + bool CheckJsonIntegerValue(const cJSON *valueNode, const ResourceItem &resourceItem) const; + bool CheckJsonSymbolValue(const cJSON *valueNode, const ResourceItem &resourceItem) const; + using HandleValue = std::function&)>; + bool ParseValueArray(const cJSON *objectNode, ResourceItem &resourceItem, const std::vector &extra, HandleValue callback) const; - bool ParseParent(const Json::Value &objectNode, const ResourceItem &resourceItem, + bool ParseParent(const cJSON *objectNode, const ResourceItem &resourceItem, std::vector &extra) const; - bool ParseAttribute(const Json::Value &arrayItem, const ResourceItem &resourceItem, + bool ParseAttribute(const cJSON *arrayItem, const ResourceItem &resourceItem, std::vector &values) const; - bool CheckPluralValue(const Json::Value &arrayItem, const ResourceItem &resourceItem) const; + bool CheckPluralValue(const cJSON *arrayItem, const ResourceItem &resourceItem) const; bool CheckColorValue(const char *s) const; std::map handles_; static const std::string TAG_NAME; @@ -66,6 +67,7 @@ private: static const std::string TAG_PARENT; static const std::string TAG_QUANTITY; static const std::vector QUANTITY_ATTRS; + cJSON *root_; }; } } diff --git a/include/key_manager.h b/include/key_manager.h deleted file mode 100644 index 639ccf4..0000000 --- a/include/key_manager.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2021 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_KEY_MANAGER_H -#define OHOS_RESTOOL_KEY_MANAGER_H - -#include -#include "xml_key_node.h" - -namespace OHOS { -namespace Global { -namespace Restool { -class KeyManager { -public: - KeyManager(); - virtual ~KeyManager() {}; - bool LoadKey(const std::string &keysPath); - bool SaveKey(const std::string &keysPath); - std::map> &GetKeys() - { - return keys_; - }; -private: - std::map> keys_; -}; -} -} -} -#endif \ No newline at end of file diff --git a/include/reference_parser.h b/include/reference_parser.h index 98acda3..e90552f 100644 --- a/include/reference_parser.h +++ b/include/reference_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -16,6 +16,7 @@ #ifndef OHOS_RESTOOL_REFERENCE_PARSER_H #define OHOS_RESTOOL_REFERENCE_PARSER_H +#include #include "id_worker.h" #include "resource_item.h" @@ -31,7 +32,7 @@ public: uint32_t ParseRefInJsonFile(ResourceItem &resourceItem, const std::string &output, const bool isIncrement = false); uint32_t ParseRefInString(std::string &value, bool &update) const; private: - bool ParseRefJson(const std::string &from, const std::string &to) const; + bool ParseRefJson(const std::string &from, const std::string &to); bool ParseRefResourceItemData(const ResourceItem &resourceItem, std::string &data, bool &update) const; bool IsStringOfResourceItem(ResType resType) const; bool IsArrayOfResourceItem(ResType resType) const; @@ -41,10 +42,11 @@ 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, bool &needSave) const; + bool ParseRefJsonImpl(cJSON *root, bool &needSave) const; const IdWorker &idWorker_; static const std::map ID_REFS; static const std::map ID_OHOS_REFS; + cJSON *root_; }; } } diff --git a/include/cmd_list.h b/include/resconfig_parser.h similarity index 53% rename from include/cmd_list.h rename to include/resconfig_parser.h index ffd074a..5fab1ea 100644 --- a/include/cmd_list.h +++ b/include/resconfig_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -13,30 +13,32 @@ * limitations under the License. */ -#ifndef OHOS_RESTOOL_CMD_LIST_H -#define OHOS_RESTOOL_CMD_LIST_H +#ifndef OHOS_RESTOOL_RES_CONFIG_PARSER_H +#define OHOS_RESTOOL_RES_CONFIG_PARSER_H -#include -#include +#include +#include +#include #include "resource_util.h" namespace OHOS { namespace Global { namespace Restool { -class CmdList { +class ResConfigParser { public: - CmdList() {}; - virtual ~CmdList() {}; + ResConfigParser(); + virtual ~ResConfigParser(); using HandleBack = std::function; uint32_t Init(const std::string &filePath, HandleBack callback); private: - void InitFileListCommand(Json::Value &root, HandleBack callback); - using HandleFileListValue = std::function; - std::vector fileListHandles_; - uint32_t GetString(const Json::Value &node, int c, HandleBack callback); - uint32_t GetArray(const Json::Value &node, int c, HandleBack callback); - uint32_t GetModuleNames(const Json::Value &node, int c, HandleBack callback); - uint32_t GetBool(const Json::Value &node, int c, HandleBack callback); + void InitFileListCommand(HandleBack callback); + using HandleFileListValue = std::function; + std::map fileListHandles_; + uint32_t GetString(const cJSON *node, int c, HandleBack callback); + uint32_t GetArray(const cJSON *node, int c, HandleBack callback); + uint32_t GetModuleNames(const cJSON *node, int c, HandleBack callback); + uint32_t GetBool(const cJSON *node, int c, HandleBack callback); + cJSON *root_; }; } } diff --git a/include/resource_check.h b/include/resource_check.h index f0796a6..03cf474 100755 --- a/include/resource_check.h +++ b/include/resource_check.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -30,13 +30,14 @@ namespace Restool { class ResourceCheck { public: - ResourceCheck(const ConfigParser &configJson, const std::shared_ptr &resourceAppend = nullptr); + ResourceCheck(const std::map> &jsonCheckIds, + const std::shared_ptr &resourceAppend = nullptr); virtual ~ResourceCheck() {}; void CheckConfigJson(); void CheckConfigJsonForCombine(); private: - const ConfigParser configJson_; + const std::map> jsonCheckIds_; const std::shared_ptr resourceAppend_; void CheckNodeInResourceItem(const std::string &key, const ResourceItem &resourceItem); bool GetPngWidthAndHeight(const std::string &filePath, uint32_t *width, uint32_t *height); diff --git a/include/resource_data.h b/include/resource_data.h index 31cf3d5..7c3319a 100644 --- a/include/resource_data.h +++ b/include/resource_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -40,7 +40,7 @@ const static std::string LONG_PATH_HEAD = "\\\\?\\"; const static std::string ID_DEFINED_INDENTATION = " "; const static int32_t VERSION_MAX_LEN = 128; const static int32_t INT_TO_BYTES = sizeof(uint32_t); -static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 4.105" }; +static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 5.000" }; const static int32_t TAG_LEN = 4; enum class KeyType { @@ -114,6 +114,12 @@ enum class InputDevice { INPUTDEVICE_POINTINGDEVICE = 0, }; +enum class ResourceIdCluster { + RES_ID_APP = 0, + RES_ID_SYS, + RES_ID_TYPE_MAX, +}; + enum Option { END = -1, IDS = 1, @@ -184,6 +190,13 @@ struct IdData { uint32_t dataOffset; }; +struct ResourceId { + int32_t id; + int32_t seq; + std::string type; + std::string name; +}; + const std::map g_copyFileMap = { { RAW_FILE_DIR, ResType::RAW }, { RES_FILE_DIR, ResType::RES }, diff --git a/include/resource_table.h b/include/resource_table.h index 13bbdcd..ebf2fd3 100644 --- a/include/resource_table.h +++ b/include/resource_table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -18,6 +18,7 @@ #include #include +#include #include "resource_item.h" #include "restool_errors.h" diff --git a/include/resource_util.h b/include/resource_util.h index 1de7602..666d9c1 100644 --- a/include/resource_util.h +++ b/include/resource_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -17,8 +17,8 @@ #define OHOS_RESTOOL_RESOURCE_UTIL_H #include +#include #include "file_entry.h" -#include "json/json.h" #include "resource_data.h" namespace OHOS { @@ -62,7 +62,7 @@ public: * @param root: json root node * @return true if open success, other false. */ - static bool OpenJsonFile(const std::string &path, Json::Value &root); + static bool OpenJsonFile(const std::string &path, cJSON **root); /** * @brief save json file. @@ -70,7 +70,7 @@ public: * @param root: json root node * @return true if save success, other false. */ - static bool SaveToJsonFile(const std::string &path, const Json::Value &root); + static bool SaveToJsonFile(const std::string &path, const cJSON *root); /** * @brief get resource type from directory. @@ -222,6 +222,17 @@ public: */ static void RemoveSpaces(std::string &str); + /** + * @brief Check whether the system resource name is valid + * @param str system resource name + */ + static bool IsValidSystemName(const std::string &name); + + /** + * @brief Check whether the value is int + * @param snode cJSON node + */ + static bool IsIntValue(const cJSON *node); private: enum class IgnoreType { IGNORE_FILE, diff --git a/src/cmd_list.cpp b/src/cmd_list.cpp deleted file mode 100644 index 430bf8b..0000000 --- a/src/cmd_list.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 "cmd_list.h" -#include "restool_errors.h" - -namespace OHOS { -namespace Global { -namespace Restool { -using namespace std; -uint32_t CmdList::Init(const string &filePath, HandleBack callback) -{ - Json::Value root; - if (!ResourceUtil::OpenJsonFile(filePath, root)) { - return RESTOOL_ERROR; - } - - if (!callback) { - return RESTOOL_SUCCESS; - } - - InitFileListCommand(root, callback); - - for (auto iter : fileListHandles_) { - if (iter() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - } - - callback(Option::FORCEWRITE, ""); - return RESTOOL_SUCCESS; -} - -// below private -void CmdList::InitFileListCommand(Json::Value &root, HandleBack callback) -{ - using namespace placeholders; - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["configPath"], Option::JSON, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["packageName"], Option::PACKAGENAME, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["output"], Option::OUTPUTPATH, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["startId"], Option::STARTID, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["entryCompiledResource"], - Option::DEPENDENTRY, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["ids"], Option::IDS, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["definedIds"], Option::DEFINED_IDS, callback)); - fileListHandles_.push_back(bind(&CmdList::GetString, this, root["applicationResource"], - Option::INPUTPATH, callback)); - fileListHandles_.push_back(bind(&CmdList::GetArray, this, root["ResourceTable"], Option::RESHEADER, callback)); - fileListHandles_.push_back(bind(&CmdList::GetArray, this, root["moduleResources"], Option::INPUTPATH, callback)); - fileListHandles_.push_back(bind(&CmdList::GetArray, this, root["dependencies"], Option::INPUTPATH, callback)); - fileListHandles_.push_back(bind(&CmdList::GetModuleNames, this, root["moduleNames"], Option::MODULES, callback)); - fileListHandles_.push_back(bind(&CmdList::GetBool, this, root["iconCheck"], Option::ICON_CHECK, callback)); -} - -uint32_t CmdList::GetString(const Json::Value &node, int c, HandleBack callback) -{ - if (!node.isString()) { - return RESTOOL_SUCCESS; - } - - if (callback(c, node.asString()) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - return RESTOOL_SUCCESS; -} - -uint32_t CmdList::GetArray(const Json::Value &node, int c, HandleBack callback) -{ - if (!node.isArray()) { - return RESTOOL_SUCCESS; - } - - for (Json::ArrayIndex i = 0; i < node.size(); i++) { - if (!node[i].isString()) { - return RESTOOL_ERROR; - } - if (callback(c, node[i].asString()) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - } - return RESTOOL_SUCCESS; -} - -uint32_t CmdList::GetModuleNames(const Json::Value &node, int c, HandleBack callback) -{ - string moduleNames; - if (node.isString()) { - return GetString(node, c, callback); - } - if (GetArray(node, c, [&moduleNames](int c, const string &argValue) { - if (!moduleNames.empty()) { - moduleNames.append(","); - } - moduleNames.append(argValue); - return RESTOOL_SUCCESS; - }) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - - if (!moduleNames.empty() && callback(c, moduleNames) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - return RESTOOL_SUCCESS; -} - -uint32_t CmdList::GetBool(const Json::Value &node, int c, HandleBack callback) -{ - if (node.type() != Json::booleanValue) { - return RESTOOL_SUCCESS; - } - - if (node.asBool() && callback(c, "") != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - return RESTOOL_SUCCESS; -} -} -} -} diff --git a/src/cmd_parser.cpp b/src/cmd_parser.cpp index ad1d9bb..2548b6c 100644 --- a/src/cmd_parser.cpp +++ b/src/cmd_parser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -15,7 +15,7 @@ #include "cmd_parser.h" #include -#include "cmd_list.h" +#include "resconfig_parser.h" #include "resource_util.h" #include "select_compile_parse.h" @@ -434,8 +434,8 @@ uint32_t PackageParser::HandleProcess(int c, const string& argValue) uint32_t PackageParser::ParseFileList(const string& fileListPath) { isFileList_ = true; - CmdList cmdList; - if (cmdList.Init(fileListPath, [this](int c, const string &argValue) -> int32_t { + ResConfigParser resConfigParser; + if (resConfigParser.Init(fileListPath, [this](int c, const string &argValue) -> int32_t { return HandleProcess(c, argValue); }) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; diff --git a/src/config_parser.cpp b/src/config_parser.cpp index d31391e..44a945b 100644 --- a/src/config_parser.cpp +++ b/src/config_parser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -51,31 +51,35 @@ const map ConfigParser::JSON_ARRAY_IDS = { bool ConfigParser::useModule_ = false; ConfigParser::ConfigParser() - : filePath_(""), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE) + : filePath_(""), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE), root_(nullptr) { } ConfigParser::ConfigParser(const string &filePath) - : filePath_(filePath), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE) + : filePath_(filePath), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE), root_(nullptr) { } ConfigParser::~ConfigParser() { + if (root_) { + cJSON_Delete(root_); + } } uint32_t ConfigParser::Init() { - if (!ResourceUtil::OpenJsonFile(filePath_, rootNode_)) { + if (!ResourceUtil::OpenJsonFile(filePath_, &root_)) { return RESTOOL_ERROR; } - if (!rootNode_.isObject()) { - cerr << "Error: root node not obeject." << NEW_LINE_PATH << filePath_ << endl; + if (!root_ || !cJSON_IsObject(root_)) { + cerr << "Error: ConfigParser root node not obeject." << NEW_LINE_PATH << filePath_ << endl; return RESTOOL_ERROR; } - if (!ParseModule(rootNode_["module"])) { + cJSON *moduleNode = cJSON_GetObjectItem(root_, "module"); + if (!ParseModule(moduleNode)) { return RESTOOL_ERROR; } return RESTOOL_SUCCESS; @@ -108,7 +112,7 @@ ConfigParser::ModuleType ConfigParser::GetModuleType() const uint32_t ConfigParser::ParseRefence() { - if (ParseRefImpl(rootNode_, "", rootNode_)) { + if (ParseRefImpl(root_, "", root_)) { return RESTOOL_SUCCESS; } return RESTOOL_ERROR; @@ -116,7 +120,7 @@ uint32_t ConfigParser::ParseRefence() uint32_t ConfigParser::Save(const string &filePath) const { - if (ResourceUtil::SaveToJsonFile(filePath, rootNode_)) { + if (ResourceUtil::SaveToJsonFile(filePath, root_)) { return RESTOOL_SUCCESS; } return RESTOOL_ERROR; @@ -124,91 +128,97 @@ uint32_t ConfigParser::Save(const string &filePath) const bool ConfigParser::SetAppIcon(string &icon, int32_t id) { - if (!rootNode_["app"].isObject()) { + cJSON *appNode = cJSON_GetObjectItem(root_, "app"); + if (!appNode || !cJSON_IsObject(appNode)) { cerr << "Error: 'app' not object" << endl; return false; } - rootNode_["app"]["icon"] = icon; - rootNode_["app"]["iconId"] = id; + cJSON_AddStringToObject(appNode, "icon", icon.c_str()); + cJSON_AddNumberToObject(appNode, "iconId", id); return true; } bool ConfigParser::SetAppLabel(string &label, int32_t id) { - if (!rootNode_["app"].isObject()) { + cJSON *appNode = cJSON_GetObjectItem(root_, "app"); + if (!appNode || !cJSON_IsObject(appNode)) { cerr << "Error: 'app' not object" << endl; return false; } - rootNode_["app"]["label"] = label; - rootNode_["app"]["labelId"] = id; + cJSON_AddStringToObject(appNode, "label", label.c_str()); + cJSON_AddNumberToObject(appNode, "labelId", id); return true; } // below private -bool ConfigParser::ParseModule(Json::Value &moduleNode) +bool ConfigParser::ParseModule(cJSON *moduleNode) { - if (!moduleNode.isObject()) { + if (!moduleNode || !cJSON_IsObject(moduleNode)) { cerr << "Error: 'module' not object." << NEW_LINE_PATH << filePath_ << endl; return false; } - if (moduleNode.empty()) { + if (cJSON_GetArraySize(moduleNode) == 0) { cerr << "Error: 'module' empty." << NEW_LINE_PATH << filePath_ << endl; return false; } if (!useModule_) { - if (moduleNode.isMember("package") && moduleNode["package"].isString()) { - packageName_ = moduleNode["package"].asString(); + cJSON *packageNode = cJSON_GetObjectItem(moduleNode, "package"); + if (packageNode && cJSON_IsString(packageNode)) { + packageName_ = packageNode->valuestring; } - if (!ParseDistro(moduleNode["distro"])) { + cJSON *distroNode = cJSON_GetObjectItem(moduleNode, "distro"); + if (!ParseDistro(distroNode)) { return false; } return ParseAbilitiesForDepend(moduleNode); } - - if (moduleNode["name"].isString()) { - moduleName_ = moduleNode["name"].asString(); + cJSON *nameNode = cJSON_GetObjectItem(moduleNode, "name"); + if (nameNode && cJSON_IsString(nameNode)) { + moduleName_ = nameNode->valuestring; } if (moduleName_.empty()) { cerr << "Error: 'name' don't found in 'module'." << NEW_LINE_PATH << filePath_ << endl; return false; } - - if (moduleNode["type"].isString() && !ParseModuleType(moduleNode["type"].asString())) { + cJSON *typeNode = cJSON_GetObjectItem(moduleNode, "type"); + if (typeNode && cJSON_IsString(typeNode) && !ParseModuleType(typeNode->valuestring)) { return false; } return true; } -bool ConfigParser::ParseAbilitiesForDepend(Json::Value &moduleNode) +bool ConfigParser::ParseAbilitiesForDepend(cJSON *moduleNode) { if (!IsDependEntry()) { return true; } - if (moduleNode["mainAbility"].isString()) { - mainAbility_ = moduleNode["mainAbility"].asString(); + cJSON *mainAbilityNode = cJSON_GetObjectItem(moduleNode, "mainAbility"); + if (mainAbilityNode && cJSON_IsString(mainAbilityNode)) { + mainAbility_ = mainAbilityNode->valuestring; if (mainAbility_[0] == '.') { mainAbility_ = packageName_ + mainAbility_; } - return ParseAbilities(moduleNode["abilities"]); + return ParseAbilities(cJSON_GetObjectItem(moduleNode, "abilities")); } return true; } -bool ConfigParser::ParseDistro(Json::Value &distroNode) +bool ConfigParser::ParseDistro(cJSON *distroNode) { - if (!distroNode.isObject()) { + if (!distroNode || !cJSON_IsObject(distroNode)) { cerr << "Error: 'distro' not object." << NEW_LINE_PATH << filePath_ << endl; return false; } - if (distroNode.empty()) { + if (cJSON_GetArraySize(distroNode) == 0) { cerr << "Error: 'distro' empty." << NEW_LINE_PATH << filePath_ << endl; return false; } - if (distroNode["moduleName"].isString()) { - moduleName_ = distroNode["moduleName"].asString(); + cJSON *moduleNameNode = cJSON_GetObjectItem(distroNode, "moduleName"); + if (moduleNameNode && cJSON_IsString(moduleNameNode)) { + moduleName_ = moduleNameNode->valuestring; } if (moduleName_.empty()) { @@ -216,24 +226,25 @@ bool ConfigParser::ParseDistro(Json::Value &distroNode) return false; } - if (distroNode["moduleType"].isString() && !ParseModuleType(distroNode["moduleType"].asString())) { + cJSON *moduleTypeNode = cJSON_GetObjectItem(distroNode, "moduleType"); + if (moduleTypeNode && cJSON_IsString(moduleTypeNode) && !ParseModuleType(moduleTypeNode->valuestring)) { return false; } return true; } -bool ConfigParser::ParseAbilities(const Json::Value &abilites) +bool ConfigParser::ParseAbilities(const cJSON *abilities) { - if (abilites.empty()) { - return true; - } - if (!abilites.isArray()) { + if (!abilities || !cJSON_IsArray(abilities)) { cerr << "Error: abilites not array." << NEW_LINE_PATH << filePath_ << endl; return false; } + if (cJSON_GetArraySize(abilities) == 0) { + return true; + } bool isMainAbility = false; - for (Json::ArrayIndex i = 0; i < abilites.size(); i++) { - if (!ParseAbilitiy(abilites[i], isMainAbility)) { + for (cJSON *ability = abilities->child; ability; ability = ability->next) { + if (!ParseAbilitiy(ability, isMainAbility)) { cerr << "Error: ParseAbilitiy fail." << endl; return false; } @@ -244,30 +255,37 @@ bool ConfigParser::ParseAbilities(const Json::Value &abilites) return true; } -bool ConfigParser::ParseAbilitiy(const Json::Value &ability, bool &isMainAbility) +bool ConfigParser::ParseAbilitiy(const cJSON *ability, bool &isMainAbility) { - if (ability.empty()) { - return true; - } - if (!ability["name"].isString()) { + if (!ability || !cJSON_IsArray(ability)) { + cerr << "Error: ability not array." << NEW_LINE_PATH << filePath_ << endl; return false; } - string name = ability["name"].asString(); + if (cJSON_GetArraySize(ability) == 0) { + return true; + } + cJSON *nameNode = cJSON_GetObjectItem(ability, "name"); + if (!nameNode || !cJSON_IsString(nameNode)) { + return false; + } + string name = nameNode->valuestring; if (name[0] == '.') { name = packageName_ + name; } - if (mainAbility_ != name && !IsMainAbility(ability["skills"])) { + if (mainAbility_ != name && !IsMainAbility(cJSON_GetObjectItem(ability, "skills"))) { return true; } - if (ability["iconId"].isInt()) { - abilityIconId_ = ability["iconId"].asInt(); + cJSON *iconIdNode = cJSON_GetObjectItem(ability, "iconId"); + if (iconIdNode && ResourceUtil::IsIntValue(iconIdNode)) { + abilityIconId_ = iconIdNode->valueint; } if (abilityIconId_ <= 0) { cerr << "Error: iconId don't found in 'ability'." << NEW_LINE_PATH << filePath_ << endl; return false; } - if (ability["labelId"].isInt()) { - abilityLabelId_ = ability["labelId"].asInt(); + cJSON *labelIdNode = cJSON_GetObjectItem(ability, "labelId"); + if (labelIdNode && ResourceUtil::IsIntValue(labelIdNode)) { + abilityLabelId_ = labelIdNode->valueint; } if (abilityLabelId_ <= 0) { cerr << "Error: labelId don't found in 'ability'." << NEW_LINE_PATH << filePath_ << endl; @@ -277,100 +295,110 @@ bool ConfigParser::ParseAbilitiy(const Json::Value &ability, bool &isMainAbility return true; } -bool ConfigParser::IsMainAbility(const Json::Value &skills) +bool ConfigParser::IsMainAbility(const cJSON *skills) { - if (!skills.isArray()) { + if (!skills || !cJSON_IsArray(skills)) { return false; } - for (Json::ArrayIndex i = 0; i < skills.size(); i++) { - if (!skills[i].isObject()) { + for (cJSON *skill = skills->child; skill; skill = skill->next) { + if (!cJSON_IsObject(skill)) { return false; } - if (IsHomeAction(skills[i]["actions"])) { + if (IsHomeAction(cJSON_GetObjectItem(skill, "actions"))) { return true; } } return false; } -bool ConfigParser::IsHomeAction(const Json::Value &actions) +bool ConfigParser::IsHomeAction(const cJSON *actions) { - if (!actions.isArray()) { + if (!actions || !cJSON_IsArray(actions)) { return false; } - for (Json::ArrayIndex i = 0; i < actions.size(); i++) { - if (!actions[i].isObject()) { + for (cJSON *action = actions->child; action; action = action->next) { + if (!cJSON_IsObject(action)) { return false; } - if (actions[i].asString() == "action.system.home") { + if (strcmp(action->valuestring, "action.system.home") == 0) { return true; } } return false; } -bool ConfigParser::ParseRefImpl(Json::Value &parent, const std::string &key, Json::Value &node) +bool ConfigParser::ParseRefImpl(cJSON *parent, const string &key, cJSON *node) { - if (node.isArray()) { + if (cJSON_IsArray(node)) { const auto &result = JSON_ARRAY_IDS.find(key); if (result != JSON_ARRAY_IDS.end()) { return ParseJsonArrayRef(parent, key, node); } - for (Json::ArrayIndex index = 0; index < node.size(); index++) { - if (!ParseRefImpl(node, "", node[index])) { + cJSON *arrayItem = node->child; + while (arrayItem) { + if (!ParseRefImpl(node, "", arrayItem)) { return false; } + arrayItem = arrayItem->next; } - } else if (node.isObject()) { - const auto members = node.getMemberNames(); - for (const auto &member : members) { - if (!ParseRefImpl(node, member, node[member])) { + } else if (cJSON_IsObject(node)) { + cJSON *child = node->child; + while (child) { + if (!ParseRefImpl(node, child->string, child)) { return false; } + child = child->next; } - } else if (!key.empty() && node.isString()) { + } else if (!key.empty() && cJSON_IsString(node)) { return ParseJsonStringRef(parent, key, node); } return true; } -bool ConfigParser::ParseJsonArrayRef(Json::Value &parent, const string &key, Json::Value &node) +bool ConfigParser::ParseJsonArrayRef(cJSON *parent, const string &key, cJSON *node) { - Json::ArrayIndex size = node.size(); - Json::Value array(Json::arrayValue); - for (Json::ArrayIndex index = 0; index < size; index++) { - if (!node[index].isString()) { + if (!node || !cJSON_IsArray(node)) { + cerr << "Error: '"<< key << "'node not array." << NEW_LINE_PATH << filePath_ << endl; + return false; + } + cJSON *array = cJSON_CreateArray(); + for (cJSON *item = node->child; item; item = item->next) { + if (!cJSON_IsString(item)) { cerr << "Error: '" << key << "' invalid value." << NEW_LINE_PATH << filePath_ << endl; return false; } - string value = node[index].asString(); + string value = item->valuestring; bool update = false; if (!GetRefIdFromString(value, update, JSON_ARRAY_IDS.at(key))) { - cerr << "Error: '" << key << "' value " << node[index] << " invalid." << NEW_LINE_PATH << filePath_ << endl; + cerr << "Error: '" << key << "' value " << value << " invalid." << NEW_LINE_PATH << filePath_ << endl; return false; } if (update) { - array.append(atoi(value.c_str())); + cJSON_AddItemToArray(array, cJSON_CreateNumber(atoi(value.c_str()))); } } - parent[key + "Id"] = array; + cJSON_AddItemToObject(parent, (key + "Id").c_str(), array); return true; } -bool ConfigParser::ParseJsonStringRef(Json::Value &parent, const string &key, Json::Value &node) +bool ConfigParser::ParseJsonStringRef(cJSON *parent, const string &key, cJSON *node) { const auto &result = JSON_STRING_IDS.find(key); if (result == JSON_STRING_IDS.end()) { return true; } - string value = node.asString(); + if (!node || !cJSON_IsString(node)) { + cerr << "Error: '" << key << "' invalid value." << endl; + return false; + } + string value = node->valuestring; bool update = false; if (!GetRefIdFromString(value, update, JSON_STRING_IDS.at(key))) { - cerr << "Error: '" << key << "' value " << node << " invalid value." << NEW_LINE_PATH << filePath_ << endl; + cerr << "Error: '" << key << "' value " << value << " invalid value." << NEW_LINE_PATH << filePath_ << endl; return false; } if (update) { - parent[key + "Id"] = atoi(value.c_str()); + cJSON_AddItemToObject(parent, (key + "Id").c_str(), cJSON_CreateNumber(atoi(value.c_str()))); AddCheckNode(key, static_cast(atoi(value.c_str()))); } return true; diff --git a/src/header.cpp b/src/header.cpp index 5fdc639..ac6e935 100644 --- a/src/header.cpp +++ b/src/header.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -14,10 +14,10 @@ */ #include "header.h" -#include -#include -#include -#include +#include +#include +#include +#include namespace OHOS { namespace Global { @@ -49,7 +49,7 @@ Header::~Header() uint32_t Header::Create(HandleHeaderTail headerHandler, HandleBody bodyHandler, HandleHeaderTail tailHandler) const { IdWorker &idWorker = IdWorker::GetInstance(); - vector resourceIds = idWorker.GetHeaderId(); + vector resourceIds = idWorker.GetHeaderId(); ofstream out(outputPath_, ofstream::out | ofstream::binary); if (!out.is_open()) { diff --git a/src/id_defined_parser.cpp b/src/id_defined_parser.cpp new file mode 100755 index 0000000..19880de --- /dev/null +++ b/src/id_defined_parser.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2024 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 "id_defined_parser.h" +#include "file_entry.h" +#include "resource_util.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; +const int32_t IdDefinedParser::START_SYS_ID = 0x07800000; +IdDefinedParser::IdDefinedParser(const PackageParser &packageParser, const ResourceIdCluster &type) + : packageParser_(packageParser), type_(type), root_(nullptr) +{ +} + +IdDefinedParser::~IdDefinedParser() +{ + if (root_) { + cJSON_Delete(root_); + } +} + +uint32_t IdDefinedParser::Init() +{ + InitParser(); + string idDefinedInput = packageParser_.GetIdDefinedInputPath(); + int32_t startId = packageParser_.GetStartId(); + bool combine = packageParser_.GetCombine(); + bool isSys = type_ == ResourceIdCluster::RES_ID_SYS; + for (const auto &inputPath : packageParser_.GetInputs()) { + string idDefinedPath; + if (combine) { + idDefinedPath = FileEntry::FilePath(inputPath).Append(ID_DEFINED_FILE).GetPath(); + } else { + idDefinedPath = ResourceUtil::GetBaseElementPath(inputPath).Append(ID_DEFINED_FILE).GetPath(); + } + if (ResourceUtil::FileExist(idDefinedPath) && startId > 0) { + cerr << "Error: the set start_id and id_defined.json cannot be used together." << endl; + return RESTOOL_ERROR; + } + if (Init(idDefinedPath, isSys) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + } + if (isSys) { + return RESTOOL_SUCCESS; + } + if (!idDefinedInput.empty()) { + appDefinedIds_.clear(); + string idDefinedPath = FileEntry::FilePath(idDefinedInput).GetPath(); + if (Init(idDefinedPath, false) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + } + string sysIdDefinedPath = FileEntry::FilePath(packageParser_.GetRestoolPath()) + .GetParent().Append(ID_DEFINED_FILE).GetPath(); + if (Init(sysIdDefinedPath, true) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t IdDefinedParser::Init(const string &filePath, bool isSystem) +{ + if (!ResourceUtil::FileExist(filePath)) { + return RESTOOL_SUCCESS; + } + + if (!ResourceUtil::OpenJsonFile(filePath, &root_)) { + return RESTOOL_ERROR; + } + + if (!root_ || !cJSON_IsObject(root_)) { + cerr << "Error: IdDefinedParser root node not obeject." << NEW_LINE_PATH << filePath << endl; + return RESTOOL_ERROR; + } + + cJSON *recordNode = cJSON_GetObjectItem(root_, "record"); + if (!recordNode || !cJSON_IsArray(recordNode)) { + cerr << "Error: id_defined.json record not array." << endl; + return RESTOOL_ERROR; + } + if (cJSON_GetArraySize(recordNode) == 0) { + cerr << "Error: id_defined.json 'record' empty." << endl; + return RESTOOL_ERROR; + } + int32_t startSysId = 0; + if (isSystem) { + startSysId = GetStartId(); + if (startSysId < 0) { + return RESTOOL_ERROR; + } + } + + if (IdDefinedToResourceIds(recordNode, isSystem, startSysId) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +void IdDefinedParser::InitParser() +{ + using namespace placeholders; + handles_.emplace("type", bind(&IdDefinedParser::ParseType, this, _1, _2)); + handles_.emplace("name", bind(&IdDefinedParser::ParseName, this, _1, _2)); + handles_.emplace("id", bind(&IdDefinedParser::ParseId, this, _1, _2)); + handles_.emplace("order", bind(&IdDefinedParser::ParseOrder, this, _1, _2)); +} + +uint32_t IdDefinedParser::IdDefinedToResourceIds(const cJSON *record, bool isSystem, const int32_t startSysId) +{ + int32_t index = -1; + for (cJSON *item = record->child; item; item = item->next) { + index++; + if (!cJSON_IsObject(item)) { + return RESTOOL_ERROR; + } + ResourceId resourceId; + resourceId.seq = index; + resourceId.id = startSysId; + for (const auto &handle : handles_) { + if ((handle.first == "id" && isSystem) || (handle.first == "order" && !isSystem)) { + continue; + } + if (!handle.second(cJSON_GetObjectItem(item, handle.first.c_str()), resourceId)) { + return RESTOOL_ERROR; + } + } + if (!PushResourceId(resourceId, isSystem)) { + return RESTOOL_ERROR; + } + } + return RESTOOL_SUCCESS; +} + +bool IdDefinedParser::PushResourceId(const ResourceId &resourceId, bool isSystem) +{ + ResType resType = ResourceUtil::GetResTypeFromString(resourceId.type); + auto ret = idDefineds_.emplace(resourceId.id, resourceId); + if (!ret.second) { + cerr << "Error: '" << ret.first->second.name << "' and '" << resourceId.name << "' defind the same ID." << endl; + return false; + } + if (isSystem) { + auto ret1 = sysDefinedIds_.emplace(make_pair(resType, resourceId.name), resourceId); + if (!ret1.second) { + cerr << "Error: the same type of '" << resourceId.name << "' exists in the id_defined.json. " << endl; + return false; + } + } else { + auto ret2 = appDefinedIds_.emplace(make_pair(resType, resourceId.name), resourceId); + if (!ret2.second) { + cerr << "Error: the same type of '" << resourceId.name << "' exists in the id_defined.json. " << endl; + return false; + } + } + return true; +} + +bool IdDefinedParser::ParseId(const cJSON *origId, ResourceId &resourceId) +{ + if (!origId) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " id empty." << endl; + return false; + } + if (!cJSON_IsString(origId)) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " id not string." << endl; + return false; + } + string idStr = origId->valuestring; + if (!ResourceUtil::CheckHexStr(idStr)) { + cerr << "Error: id_defined.json seq =" << resourceId.seq; + cerr << " id must be a hex string, eg:^0[xX][0-9a-fA-F]{8}" << endl; + return false; + } + int32_t id = strtol(idStr.c_str(), nullptr, 16); + if (id < 0x01000000 || (id >= 0x06FFFFFF && id < 0x08000000) || id >= 0x41FFFFFF) { + cerr << "Error: id_defined.json seq = "<< resourceId.seq; + cerr << " id must in [0x01000000,0x06FFFFFF),[0x08000000,0x41FFFFFF)." << endl; + return false; + } + resourceId.id = id; + return true; +} + +bool IdDefinedParser::ParseType(const cJSON *type, ResourceId &resourceId) +{ + if (!type) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " type empty." << endl; + return false; + } + if (!cJSON_IsString(type)) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " type not string." << endl; + return false; + } + if (ResourceUtil::GetResTypeFromString(type->valuestring) == ResType::INVALID_RES_TYPE) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " type '"; + cerr << type->valuestring << "' invalid." << endl; + return false; + } + resourceId.type = type->valuestring; + return true; +} + +bool IdDefinedParser::ParseName(const cJSON *name, ResourceId &resourceId) +{ + if (!name) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " name empty." << endl; + return false; + } + if (!cJSON_IsString(name)) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " name not string." << endl; + return false; + } + resourceId.name = name->valuestring; + if (type_ == ResourceIdCluster::RES_ID_SYS && + (resourceId.id & START_SYS_ID) == START_SYS_ID && !ResourceUtil::IsValidSystemName(resourceId.name)) { + cerr << "Error: id_defined.json."<< endl; + return false; + } + return true; +} + +bool IdDefinedParser::ParseOrder(const cJSON *order, ResourceId &resourceId) +{ + if (!order) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " order empty." << endl; + return false; + } + if (!ResourceUtil::IsIntValue(order)) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " order not int." << endl; + return false; + } + int32_t orderId = order->valueint; + if (orderId != resourceId.seq) { + cerr << "Error: id_defined.json seq =" << resourceId.seq << " order value "; + cerr << orderId << " vs expect " << resourceId.seq << endl; + return false; + } + resourceId.id = resourceId.id + orderId; + return true; +} + +int32_t IdDefinedParser::GetStartId() const +{ + cJSON *startIdNode = cJSON_GetObjectItem(root_, "startId"); + if (!startIdNode) { + cerr << "Error: id_defined.json 'startId' empty." << endl; + return -1; + } + + if (!cJSON_IsString(startIdNode)) { + cerr << "Error: id_defined.json 'startId' not string." << endl; + return -1; + } + + int32_t id = strtol(startIdNode->valuestring, nullptr, 16); + return id; +} + +} +} +} \ No newline at end of file diff --git a/src/id_worker.cpp b/src/id_worker.cpp index f622a3a..0bd259d 100644 --- a/src/id_worker.cpp +++ b/src/id_worker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -14,23 +14,25 @@ */ #include "id_worker.h" -#include -#include +#include +#include #include "cmd_parser.h" -#include "file_entry.h" namespace OHOS { namespace Global { namespace Restool { using namespace std; -const int32_t IdWorker::START_SYS_ID = 0x07800000; -uint32_t IdWorker::Init(ResourceIdCluster type, int32_t startId) +uint32_t IdWorker::Init(ResourceIdCluster &type, int32_t startId) { type_ = type; - if (InitIdDefined() != RESTOOL_SUCCESS) { + CmdParser &parser = CmdParser::GetInstance(); + PackageParser &packageParser = parser.GetCmdParser(); + IdDefinedParser idDefinedParser = IdDefinedParser(packageParser, type_); + if (idDefinedParser.Init() != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } - + sysDefinedIds_ = idDefinedParser.GetSysDefinedIds(); + appDefinedIds_ = idDefinedParser.GetAppDefinedIds(); if (type == ResourceIdCluster::RES_ID_APP) { appId_ = startId; maxId_ = GetMaxId(startId); @@ -46,7 +48,16 @@ int32_t IdWorker::GenerateId(ResType resType, const string &name) return GenerateSysId(resType, name); } -vector IdWorker::GetHeaderId() const +int32_t IdWorker::GetId(ResType resType, const string &name) const +{ + auto result = ids_.find(make_pair(resType, name)); + if (result == ids_.end()) { + return -1; + } + return result->second; +} + +vector IdWorker::GetHeaderId() const { map> idClassify; for (const auto &it : ids_) { @@ -64,15 +75,6 @@ vector IdWorker::GetHeaderId() const return ids; } -int32_t IdWorker::GetId(ResType resType, const string &name) const -{ - auto result = ids_.find(make_pair(resType, name)); - if (result == ids_.end()) { - return -1; - } - return result->second; -} - int32_t IdWorker::GetSystemId(ResType resType, const string &name) const { auto result = sysDefinedIds_.find(make_pair(resType, name)); @@ -91,7 +93,7 @@ bool IdWorker::IsValidName(const string &name) const if (type_ != ResourceIdCluster::RES_ID_SYS) { return true; } - return IsValidSystemName(name); + return ResourceUtil::IsValidSystemName(name); } bool IdWorker::PushCache(ResType resType, const string &name, int32_t id) @@ -192,249 +194,6 @@ int32_t IdWorker::GenerateSysId(ResType resType, const string &name) return -1; } -uint32_t IdWorker::InitIdDefined() -{ - InitParser(); - CmdParser &parser = CmdParser::GetInstance(); - PackageParser &packageParser = parser.GetCmdParser(); - string idDefinedInput = packageParser.GetIdDefinedInputPath(); - int32_t startId = packageParser.GetStartId(); - bool combine = packageParser.GetCombine(); - bool isSys = type_ == ResourceIdCluster::RES_ID_SYS; - for (const auto &inputPath : packageParser.GetInputs()) { - string idDefinedPath; - if (combine) { - idDefinedPath = FileEntry::FilePath(inputPath).Append(ID_DEFINED_FILE).GetPath(); - } else { - idDefinedPath = ResourceUtil::GetBaseElementPath(inputPath).Append(ID_DEFINED_FILE).GetPath(); - } - if (ResourceUtil::FileExist(idDefinedPath) && startId > 0) { - cerr << "Error: the set start_id and id_defined.json cannot be used together." << endl; - return RESTOOL_ERROR; - } - if (InitIdDefined(idDefinedPath, isSys) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - } - if (isSys) { - return RESTOOL_SUCCESS; - } - if (!idDefinedInput.empty()) { - appDefinedIds_.clear(); - string idDefinedPath = FileEntry::FilePath(idDefinedInput).GetPath(); - if (InitIdDefined(idDefinedPath, false) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - } - string sysIdDefinedPath = FileEntry::FilePath(packageParser.GetRestoolPath()) - .GetParent().Append(ID_DEFINED_FILE).GetPath(); - if (InitIdDefined(sysIdDefinedPath, true) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - return RESTOOL_SUCCESS; -} - -uint32_t IdWorker::InitIdDefined(const std::string &filePath, bool isSystem) -{ - if (!ResourceUtil::FileExist(filePath)) { - return RESTOOL_SUCCESS; - } - - Json::Value root; - if (!ResourceUtil::OpenJsonFile(filePath, root)) { - return RESTOOL_ERROR; - } - - auto record = root["record"]; - if (record.empty()) { - cerr << "Error: id_defined.json record empty." << endl; - return RESTOOL_ERROR; - } - if (!record.isArray()) { - cerr << "Error: id_defined.json record not array." << endl; - return RESTOOL_ERROR; - } - int32_t startSysId = 0; - if (isSystem) { - startSysId = GetStartId(root); - if (startSysId < 0) { - return RESTOOL_ERROR; - } - } - - if (IdDefinedToResourceIds(record, isSystem, startSysId) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } - return RESTOOL_SUCCESS; -} - -uint32_t IdWorker::IdDefinedToResourceIds(const Json::Value &record, bool isSystem, const int32_t startSysId) -{ - for (Json::ArrayIndex index = 0; index < record.size(); index++) { - auto arrayItem = record[index]; - if (!arrayItem.isObject()) { - return RESTOOL_ERROR; - } - ResourceId resourceId; - resourceId.seq = index; - resourceId.id = startSysId; - for (const auto &handle : handles_) { - if ((handle.first == "id" && isSystem) || (handle.first == "order" && !isSystem)) { - continue; - } - if (!handle.second(arrayItem[handle.first], resourceId)) { - return RESTOOL_ERROR; - } - } - if (!PushResourceId(resourceId, isSystem)) { - return RESTOOL_ERROR; - } - } - return RESTOOL_SUCCESS; -} - -void IdWorker::InitParser() -{ - using namespace placeholders; - handles_.emplace("type", bind(&IdWorker::ParseType, this, _1, _2)); - handles_.emplace("name", bind(&IdWorker::ParseName, this, _1, _2)); - handles_.emplace("id", bind(&IdWorker::ParseId, this, _1, _2)); - handles_.emplace("order", bind(&IdWorker::ParseOrder, this, _1, _2)); -} - -bool IdWorker::ParseId(const Json::Value &origId, ResourceId &resourceId) -{ - if (origId.empty()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " id empty." << endl; - return false; - } - if (!origId.isString()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " id not string." << endl; - return false; - } - string idStr = origId.asString(); - if (!ResourceUtil::CheckHexStr(idStr)) { - cerr << "Error: id_defined.json seq =" << resourceId.seq; - cerr << " id must be a hex string, eg:^0[xX][0-9a-fA-F]{8}" << endl; - return false; - } - int32_t id = strtol(idStr.c_str(), nullptr, 16); - if (id < 0x01000000 || (id >= 0x06FFFFFF && id < 0x08000000) || id >= 0x41FFFFFF) { - cerr << "Error: id_defined.json seq = "<< resourceId.seq; - cerr << " id must in [0x01000000,0x06FFFFFF),[0x08000000,0x41FFFFFF)." << endl; - return false; - } - resourceId.id = id; - return true; -} - -bool IdWorker::ParseType(const Json::Value &type, ResourceId &resourceId) -{ - if (type.empty()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " type empty." << endl; - return false; - } - if (!type.isString()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " type not string." << endl; - return false; - } - if (ResourceUtil::GetResTypeFromString(type.asString()) == ResType::INVALID_RES_TYPE) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " type '"; - cerr << type.asString() << "' invalid." << endl; - return false; - } - resourceId.type = type.asString(); - return true; -} - -bool IdWorker::ParseName(const Json::Value &name, ResourceId &resourceId) -{ - if (name.empty()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " name empty." << endl; - return false; - } - if (!name.isString()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " name not string." << endl; - return false; - } - resourceId.name = name.asString(); - if (type_ == ResourceIdCluster::RES_ID_SYS && - (resourceId.id & START_SYS_ID) == START_SYS_ID && !IsValidSystemName(resourceId.name)) { - cerr << "Error: id_defined.json."<< endl; - return false; - } - return true; -} - -bool IdWorker::ParseOrder(const Json::Value &order, ResourceId &resourceId) -{ - if (order.empty()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " order empty." << endl; - return false; - } - if (!order.isInt()) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " order not int." << endl; - return false; - } - if (order.asInt() != resourceId.seq) { - cerr << "Error: id_defined.json seq =" << resourceId.seq << " order value "; - cerr << order.asInt() << " vs expect " << resourceId.seq << endl; - return false; - } - resourceId.id = resourceId.id + order.asInt(); - return true; -} - -bool IdWorker::PushResourceId(const ResourceId &resourceId, bool isSystem) -{ - ResType resType = ResourceUtil::GetResTypeFromString(resourceId.type); - auto ret = idDefineds_.emplace(resourceId.id, resourceId); - if (!ret.second) { - cerr << "Error: '" << ret.first->second.name << "' and '" << resourceId.name << "' defind the same ID." << endl; - return false; - } - if (isSystem) { - auto ret1 = sysDefinedIds_.emplace(make_pair(resType, resourceId.name), resourceId); - if (!ret1.second) { - cerr << "Error: the same type of '" << resourceId.name << "' exists in the id_defined.json. " << endl; - return false; - } - } else { - auto ret2 = appDefinedIds_.emplace(make_pair(resType, resourceId.name), resourceId); - if (!ret2.second) { - cerr << "Error: the same type of '" << resourceId.name << "' exists in the id_defined.json. " << endl; - return false; - } - } - return true; -} - -bool IdWorker::IsValidSystemName(const string &name) const -{ - if (regex_match(name, regex("^ohos.+"))) { - return true; - } - cerr << "Error: '" << name << "' must start with 'ohos'" << endl; - return false; -} - -int32_t IdWorker::GetStartId(const Json::Value &root) const -{ - auto startId = root["startId"]; - if (startId.empty()) { - cerr << "Error: id_defined.json 'startId' empty." << endl; - return -1; - } - - if (!startId.isString()) { - cerr << "Error: id_defined.json 'startId' not string." << endl; - return -1; - } - - int32_t id = strtol(startId.asString().c_str(), nullptr, 16); - return id; -} - int32_t IdWorker::GetMaxId(int32_t startId) const { int32_t flag = 1; diff --git a/src/json_compiler.cpp b/src/json_compiler.cpp index 7d3f876..d03303c 100644 --- a/src/json_compiler.cpp +++ b/src/json_compiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -15,6 +15,7 @@ #include "json_compiler.h" #include +#include #include #include "restool_errors.h" @@ -29,13 +30,16 @@ const string JsonCompiler::TAG_QUANTITY = "quantity"; const vector JsonCompiler::QUANTITY_ATTRS = { "zero", "one", "two", "few", "many", "other" }; JsonCompiler::JsonCompiler(ResType type, const string &output) - : IResourceCompiler(type, output) + : IResourceCompiler(type, output), root_(nullptr) { InitParser(); } JsonCompiler::~JsonCompiler() { + if (root_) { + cJSON_Delete(root_); + } } uint32_t JsonCompiler::CompileSingleFile(const FileInfo &fileInfo) @@ -46,22 +50,20 @@ uint32_t JsonCompiler::CompileSingleFile(const FileInfo &fileInfo) return RESTOOL_SUCCESS; } - Json::Value root; - if (!ResourceUtil::OpenJsonFile(fileInfo.filePath, root)) { + if (!ResourceUtil::OpenJsonFile(fileInfo.filePath, &root_)) { return RESTOOL_ERROR; } - - if (!root.isObject()) { - cerr << "Error: root node must object." << NEW_LINE_PATH << fileInfo.filePath << endl; + if (!root_ || !cJSON_IsObject(root_)) { + cerr << "Error: JsonCompiler root node not obeject." << NEW_LINE_PATH << fileInfo.filePath << endl; return RESTOOL_ERROR; } - - if (root.getMemberNames().size() != 1) { + cJSON *item = root_->child; + if (cJSON_GetArraySize(root_) != 1) { cerr << "Error: root node must only one member." << NEW_LINE_PATH << fileInfo.filePath << endl; return RESTOOL_ERROR; } - string tag = root.getMemberNames()[0]; + string tag = item->string; auto ret = g_contentClusterMap.find(tag); if (ret == g_contentClusterMap.end()) { cerr << "Error: invalid tag name '" << tag << "'." << NEW_LINE_PATH << fileInfo.filePath << endl; @@ -70,7 +72,7 @@ uint32_t JsonCompiler::CompileSingleFile(const FileInfo &fileInfo) FileInfo copy = fileInfo; copy.fileType = ret->second; - if (!ParseJsonArrayLevel(root[tag], copy)) { + if (!ParseJsonArrayLevel(item, copy)) { return RESTOOL_ERROR; } return RESTOOL_SUCCESS; @@ -93,46 +95,47 @@ void JsonCompiler::InitParser() handles_.emplace(ResType::SYMBOL, bind(&JsonCompiler::HandleSymbol, this, _1, _2)); } -bool JsonCompiler::ParseJsonArrayLevel(const Json::Value &arrayNode, const FileInfo &fileInfo) +bool JsonCompiler::ParseJsonArrayLevel(const cJSON *arrayNode, const FileInfo &fileInfo) { - if (!arrayNode.isArray()) { + if (!arrayNode || !cJSON_IsArray(arrayNode)) { cerr << "Error: '" << ResourceUtil::ResTypeToString(fileInfo.fileType) << "' must be array."; cerr << NEW_LINE_PATH << fileInfo.filePath << endl; return false; } - if (arrayNode.empty()) { + if (cJSON_GetArraySize(arrayNode) == 0) { cerr << "Error: '" << ResourceUtil::ResTypeToString(fileInfo.fileType) << "' empty."; cerr << NEW_LINE_PATH << fileInfo.filePath << endl; return false; } - - for (Json::ArrayIndex index = 0; index < arrayNode.size(); index++) { - if (!arrayNode[index].isObject()) { + int32_t index = -1; + for (cJSON *item = arrayNode->child; item; item = item->next) { + index++; + if (!item || !cJSON_IsObject(item)) { cerr << "Error: the seq=" << index << " item must be object." << NEW_LINE_PATH << fileInfo.filePath << endl; return false; } - if (!ParseJsonObjectLevel(arrayNode[index], fileInfo)) { + if (!ParseJsonObjectLevel(item, fileInfo)) { return false; } } return true; } -bool JsonCompiler::ParseJsonObjectLevel(const Json::Value &objectNode, const FileInfo &fileInfo) +bool JsonCompiler::ParseJsonObjectLevel(const cJSON *objectNode, const FileInfo &fileInfo) { - auto nameNode = objectNode[TAG_NAME]; - if (nameNode.empty()) { + cJSON *nameNode = cJSON_GetObjectItem(objectNode, TAG_NAME.c_str()); + if (!nameNode) { cerr << "Error: name empty." << NEW_LINE_PATH << fileInfo.filePath << endl; return false; } - if (!nameNode.isString()) { + if (!cJSON_IsString(nameNode)) { cerr << "Error: name must string." << NEW_LINE_PATH << fileInfo.filePath << endl; return false; } - ResourceItem resourceItem(nameNode.asString(), fileInfo.keyParams, fileInfo.fileType); + ResourceItem resourceItem(nameNode->valuestring, fileInfo.keyParams, fileInfo.fileType); resourceItem.SetFilePath(fileInfo.filePath); resourceItem.SetLimitKey(fileInfo.limitKey); auto ret = handles_.find(fileInfo.fileType); @@ -148,111 +151,121 @@ bool JsonCompiler::ParseJsonObjectLevel(const Json::Value &objectNode, const Fil return MergeResourceItem(resourceItem); } -bool JsonCompiler::HandleString(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleString(const cJSON *objectNode, ResourceItem &resourceItem) const { - Json::Value valueNode = objectNode[TAG_VALUE]; + cJSON *valueNode = cJSON_GetObjectItem(objectNode, TAG_VALUE.c_str()); if (!CheckJsonStringValue(valueNode, resourceItem)) { return false; } - return PushString(valueNode.asString(), resourceItem); + return PushString(valueNode->valuestring, resourceItem); } -bool JsonCompiler::HandleInteger(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleInteger(const cJSON *objectNode, ResourceItem &resourceItem) const { - Json::Value valueNode = objectNode[TAG_VALUE]; + cJSON *valueNode = cJSON_GetObjectItem(objectNode, TAG_VALUE.c_str()); if (!CheckJsonIntegerValue(valueNode, resourceItem)) { return false; } - return PushString(valueNode.asString(), resourceItem); + if (cJSON_IsString(valueNode)) { + return PushString(valueNode->valuestring, resourceItem); + } + return PushString(to_string(valueNode->valueint), resourceItem); } -bool JsonCompiler::HandleBoolean(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleBoolean(const cJSON *objectNode, ResourceItem &resourceItem) const { - Json::Value valueNode = objectNode[TAG_VALUE]; - if (valueNode.isString()) { + cJSON *valueNode = cJSON_GetObjectItem(objectNode, TAG_VALUE.c_str()); + if (cJSON_IsString(valueNode)) { regex ref("^\\$(ohos:)?boolean:.*"); - if (!regex_match(valueNode.asString(), ref)) { - cerr << "Error: '" << valueNode.asString() << "' only refer '$boolean:xxx'."; + if (!regex_match(valueNode->valuestring, ref)) { + cerr << "Error: '" << valueNode->valuestring << "' only refer '$boolean:xxx'."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - } else if (!valueNode.isBool()) { + return PushString(valueNode->valuestring, resourceItem); + } + if (!cJSON_IsBool(valueNode)) { cerr << "Error: '" << resourceItem.GetName() << "' value not boolean."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - return PushString(valueNode.asString(), resourceItem); + return PushString(cJSON_IsTrue(valueNode) == 1 ? "true" : "false", resourceItem); } -bool JsonCompiler::HandleColor(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleColor(const cJSON *objectNode, ResourceItem &resourceItem) const { return HandleString(objectNode, resourceItem); } -bool JsonCompiler::HandleFloat(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleFloat(const cJSON *objectNode, ResourceItem &resourceItem) const { return HandleString(objectNode, resourceItem); } -bool JsonCompiler::HandleStringArray(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleStringArray(const cJSON *objectNode, ResourceItem &resourceItem) const { vector extra; return ParseValueArray(objectNode, resourceItem, extra, - [this](const Json::Value &arrayItem, const ResourceItem &resourceItem, vector &values) -> bool { - if (!arrayItem.isObject()) { + [this](const cJSON *arrayItem, const ResourceItem &resourceItem, vector &values) -> bool { + if (!cJSON_IsObject(arrayItem)) { cerr << "Error: '" << resourceItem.GetName() << "' value array item not object."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - auto value = arrayItem[TAG_VALUE]; - if (!CheckJsonStringValue(value, resourceItem)) { + cJSON *valueNode = cJSON_GetObjectItem(arrayItem, TAG_VALUE.c_str()); + if (!CheckJsonStringValue(valueNode, resourceItem)) { return false; } - values.push_back(value.asString()); + values.push_back(valueNode->valuestring); return true; }); } -bool JsonCompiler::HandleIntegerArray(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleIntegerArray(const cJSON *objectNode, ResourceItem &resourceItem) const { vector extra; return ParseValueArray(objectNode, resourceItem, extra, - [this](const Json::Value &arrayItem, const ResourceItem &resourceItem, vector &values) -> bool { + [this](const cJSON *arrayItem, const ResourceItem &resourceItem, vector &values) -> bool { if (!CheckJsonIntegerValue(arrayItem, resourceItem)) { return false; } - values.push_back(arrayItem.asString()); + if (cJSON_IsString(arrayItem)) { + values.push_back(arrayItem->valuestring); + } else { + values.push_back(to_string(arrayItem->valueint)); + } return true; }); } -bool JsonCompiler::HandleTheme(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleTheme(const cJSON *objectNode, ResourceItem &resourceItem) const { vector extra; if (!ParseParent(objectNode, resourceItem, extra)) { return false; } return ParseValueArray(objectNode, resourceItem, extra, - [this](const Json::Value &arrayItem, const ResourceItem &resourceItem, vector &values) { + [this](const cJSON *arrayItem, const ResourceItem &resourceItem, vector &values) { return ParseAttribute(arrayItem, resourceItem, values); }); } -bool JsonCompiler::HandlePattern(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandlePattern(const cJSON *objectNode, ResourceItem &resourceItem) const { return HandleTheme(objectNode, resourceItem); } -bool JsonCompiler::HandlePlural(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandlePlural(const cJSON *objectNode, ResourceItem &resourceItem) const { vector extra; vector attrs; bool result = ParseValueArray(objectNode, resourceItem, extra, - [&attrs, this](const Json::Value &arrayItem, const ResourceItem &resourceItem, vector &values) { + [&attrs, this](const cJSON *arrayItem, const ResourceItem &resourceItem, vector &values) { if (!CheckPluralValue(arrayItem, resourceItem)) { return false; } - string quantityValue = arrayItem[TAG_QUANTITY].asString(); + cJSON *quantityNode = cJSON_GetObjectItem(arrayItem, TAG_QUANTITY.c_str()); + string quantityValue = quantityNode->valuestring; if (find(attrs.begin(), attrs.end(), quantityValue) != attrs.end()) { cerr << "Error: Plural '" << resourceItem.GetName() << "' quantity '" << quantityValue; cerr << "' duplicated." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; @@ -260,7 +273,8 @@ bool JsonCompiler::HandlePlural(const Json::Value &objectNode, ResourceItem &res } attrs.push_back(quantityValue); values.push_back(quantityValue); - values.push_back(arrayItem[TAG_VALUE].asString()); + cJSON *valueNode = cJSON_GetObjectItem(arrayItem, TAG_VALUE.c_str()); + values.push_back(valueNode->valuestring); return true; }); if (!result) { @@ -274,13 +288,13 @@ bool JsonCompiler::HandlePlural(const Json::Value &objectNode, ResourceItem &res return true; } -bool JsonCompiler::HandleSymbol(const Json::Value &objectNode, ResourceItem &resourceItem) const +bool JsonCompiler::HandleSymbol(const cJSON *objectNode, ResourceItem &resourceItem) const { - Json::Value valueNode = objectNode[TAG_VALUE]; + cJSON *valueNode = cJSON_GetObjectItem(objectNode, TAG_VALUE.c_str()); if (!CheckJsonSymbolValue(valueNode, resourceItem)) { return false; } - return PushString(valueNode.asString(), resourceItem); + return PushString(valueNode->valuestring, resourceItem); } bool JsonCompiler::PushString(const string &value, ResourceItem &resourceItem) const @@ -293,9 +307,9 @@ bool JsonCompiler::PushString(const string &value, ResourceItem &resourceItem) c return true; } -bool JsonCompiler::CheckJsonStringValue(const Json::Value &valueNode, const ResourceItem &resourceItem) const +bool JsonCompiler::CheckJsonStringValue(const cJSON *valueNode, const ResourceItem &resourceItem) const { - if (!valueNode.isString()) { + if (!valueNode || !cJSON_IsString(valueNode)) { cerr << "Error: '" << resourceItem.GetName() << "' value not string."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; @@ -308,7 +322,7 @@ bool JsonCompiler::CheckJsonStringValue(const Json::Value &valueNode, const Reso { ResType::FLOAT, "\\$(ohos:)?float:" } }; - string value = valueNode.asString(); + string value = valueNode->valuestring; ResType type = resourceItem.GetResType(); if (type == ResType::COLOR && !CheckColorValue(value.c_str())) { string error = "invalid color value '" + value + \ @@ -326,16 +340,21 @@ bool JsonCompiler::CheckJsonStringValue(const Json::Value &valueNode, const Reso return true; } -bool JsonCompiler::CheckJsonIntegerValue(const Json::Value &valueNode, const ResourceItem &resourceItem) const +bool JsonCompiler::CheckJsonIntegerValue(const cJSON *valueNode, const ResourceItem &resourceItem) const { - if (valueNode.isString()) { + if (!valueNode) { + cerr << "Error: '" << resourceItem.GetName() << "' value is empty"; + cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; + return false; + } + if (cJSON_IsString(valueNode)) { regex ref("^\\$(ohos:)?integer:.*"); - if (!regex_match(valueNode.asString(), ref)) { - cerr << "Error: '" << valueNode.asString() << "', only refer '$integer:xxx'."; + if (!regex_match(valueNode->valuestring, ref)) { + cerr << "Error: '" << valueNode->valuestring << "', only refer '$integer:xxx'."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - } else if (!valueNode.isInt()) { + } else if (!ResourceUtil::IsIntValue(valueNode)) { cerr << "Error: '" << resourceItem.GetName() << "' value not integer."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; @@ -343,14 +362,14 @@ bool JsonCompiler::CheckJsonIntegerValue(const Json::Value &valueNode, const Res return true; } -bool JsonCompiler::CheckJsonSymbolValue(const Json::Value &valueNode, const ResourceItem &resourceItem) const +bool JsonCompiler::CheckJsonSymbolValue(const cJSON *valueNode, const ResourceItem &resourceItem) const { - if (!valueNode.isString()) { + if (!valueNode || !cJSON_IsString(valueNode)) { cerr << "Error: '" << resourceItem.GetName() << "' value not string."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - string unicodeStr = valueNode.asString(); + string unicodeStr = valueNode->valuestring; if (regex_match(unicodeStr, regex("^\\$(ohos:)?symbol:.*"))) { return true; } @@ -363,17 +382,17 @@ bool JsonCompiler::CheckJsonSymbolValue(const Json::Value &valueNode, const Reso return true; } -bool JsonCompiler::ParseValueArray(const Json::Value &objectNode, ResourceItem &resourceItem, +bool JsonCompiler::ParseValueArray(const cJSON *objectNode, ResourceItem &resourceItem, const vector &extra, HandleValue callback) const { - Json::Value arrayNode = objectNode[TAG_VALUE]; - if (!arrayNode.isArray()) { + cJSON *arrayNode = cJSON_GetObjectItem(objectNode, TAG_VALUE.c_str()); + if (!cJSON_IsArray(arrayNode)) { cerr << "Error: '" << resourceItem.GetName() << "' value not array."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - if (arrayNode.empty()) { + if (cJSON_GetArraySize(arrayNode) == 0) { cerr << "Error: '" << resourceItem.GetName() << "' value empty."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; @@ -383,9 +402,9 @@ bool JsonCompiler::ParseValueArray(const Json::Value &objectNode, ResourceItem & if (!extra.empty()) { contents.assign(extra.begin(), extra.end()); } - for (Json::ArrayIndex index = 0; index < arrayNode.size(); index++) { + for (cJSON *item = arrayNode->child; item; item = item->next) { vector values; - if (!callback(arrayNode[index], resourceItem, values)) { + if (!callback(item, resourceItem, values)) { return false; } contents.insert(contents.end(), values.begin(), values.end()); @@ -400,23 +419,23 @@ bool JsonCompiler::ParseValueArray(const Json::Value &objectNode, ResourceItem & return PushString(data, resourceItem); } -bool JsonCompiler::ParseParent(const Json::Value &objectNode, const ResourceItem &resourceItem, +bool JsonCompiler::ParseParent(const cJSON *objectNode, const ResourceItem &resourceItem, vector &extra) const { - auto parent = objectNode[TAG_PARENT]; + cJSON *parentNode = cJSON_GetObjectItem(objectNode, TAG_PARENT.c_str()); string type = ResourceUtil::ResTypeToString(resourceItem.GetResType()); - if (!parent.isNull()) { - if (!parent.isString()) { + if (parentNode) { + if (!cJSON_IsString(parentNode)) { cerr << "Error: " << type << " '" << resourceItem.GetName() << "' parent not string."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - if (parent.empty()) { + string parentValue = parentNode->valuestring; + if (parentValue.empty()) { cerr << "Error: " << type << " '"<< resourceItem.GetName() << "' parent empty."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - string parentValue = parent.asString(); if (regex_match(parentValue, regex("^ohos:" + type + ":.+"))) { parentValue = "$" + parentValue; } else { @@ -427,62 +446,62 @@ bool JsonCompiler::ParseParent(const Json::Value &objectNode, const ResourceItem return true; } -bool JsonCompiler::ParseAttribute(const Json::Value &arrayItem, const ResourceItem &resourceItem, +bool JsonCompiler::ParseAttribute(const cJSON *arrayItem, const ResourceItem &resourceItem, vector &values) const { string type = ResourceUtil::ResTypeToString(resourceItem.GetResType()); - if (!arrayItem.isObject()) { + if (!arrayItem || !cJSON_IsObject(arrayItem)) { cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute not object."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - auto name = arrayItem[TAG_NAME]; - if (name.empty()) { + cJSON *nameNode = cJSON_GetObjectItem(arrayItem, TAG_NAME.c_str()); + if (!nameNode) { cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute name empty."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - if (!name.isString()) { + if (!cJSON_IsString(nameNode)) { cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute name not string."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - values.push_back(name.asString()); + values.push_back(nameNode->valuestring); - auto value = arrayItem[TAG_VALUE]; - if (value.isNull()) { - cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute '" << name.asString(); + cJSON *valueNode = cJSON_GetObjectItem(arrayItem, TAG_VALUE.c_str()); + if (!valueNode) { + cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute '" << nameNode->valuestring; cerr << "' value empty." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - if (!value.isString()) { - cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute '" << name.asString(); + if (!cJSON_IsString(valueNode)) { + cerr << "Error: " << type << " '" << resourceItem.GetName() << "' attribute '" << nameNode->valuestring; cerr << "' value not string." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - values.push_back(value.asString()); + values.push_back(valueNode->valuestring); return true; } -bool JsonCompiler::CheckPluralValue(const Json::Value &arrayItem, const ResourceItem &resourceItem) const +bool JsonCompiler::CheckPluralValue(const cJSON *arrayItem, const ResourceItem &resourceItem) const { - if (!arrayItem.isObject()) { + if (!arrayItem || !cJSON_IsObject(arrayItem)) { cerr << "Error: Plural '" << resourceItem.GetName() << "' array item not object."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - auto quantity = arrayItem[TAG_QUANTITY]; - if (quantity.empty()) { + cJSON *quantityNode = cJSON_GetObjectItem(arrayItem, TAG_QUANTITY.c_str()); + if (!quantityNode) { cerr << "Error: Plural '" << resourceItem.GetName() << "' quantity empty."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - if (!quantity.isString()) { + if (!cJSON_IsString(quantityNode)) { cerr << "Error: Plural '" << resourceItem.GetName() << "' quantity not string."; cerr << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - string quantityValue = quantity.asString(); + string quantityValue = quantityNode->valuestring; if (find(QUANTITY_ATTRS.begin(), QUANTITY_ATTRS.end(), quantityValue) == QUANTITY_ATTRS.end()) { string buffer(" "); for_each(QUANTITY_ATTRS.begin(), QUANTITY_ATTRS.end(), [&buffer](auto iter) { @@ -493,13 +512,13 @@ bool JsonCompiler::CheckPluralValue(const Json::Value &arrayItem, const Resource return false; } - auto value = arrayItem[TAG_VALUE]; - if (value.isNull()) { + cJSON *valueNode = cJSON_GetObjectItem(arrayItem, TAG_VALUE.c_str()); + if (!valueNode) { cerr << "Error: Plural '" << resourceItem.GetName() << "' quantity '" << quantityValue; cerr << "' value empty." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - if (!value.isString()) { + if (!cJSON_IsString(valueNode)) { cerr << "Error: Plural '" << resourceItem.GetName() << "' quantity '" << quantityValue; cerr << "' value not string." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; diff --git a/src/reference_parser.cpp b/src/reference_parser.cpp index 02d9b5b..517d5dc 100644 --- a/src/reference_parser.cpp +++ b/src/reference_parser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -53,12 +53,15 @@ const map ReferenceParser::ID_OHOS_REFS = { { "^\\$ohos:symbol:", ResType::SYMBOL } }; -ReferenceParser::ReferenceParser() : idWorker_(IdWorker::GetInstance()) +ReferenceParser::ReferenceParser() : idWorker_(IdWorker::GetInstance()), root_(nullptr) { } ReferenceParser::~ReferenceParser() { + if (root_) { + cJSON_Delete(root_); + } } uint32_t ReferenceParser::ParseRefInResources(map> &items, const string &output) @@ -135,15 +138,17 @@ uint32_t ReferenceParser::ParseRefInString(string &value, bool &update) const return RESTOOL_ERROR; } -bool ReferenceParser::ParseRefJson(const string &from, const string &to) const +bool ReferenceParser::ParseRefJson(const string &from, const string &to) { - Json::Value root; - if (!ResourceUtil::OpenJsonFile(from, root)) { + if (!ResourceUtil::OpenJsonFile(from, &root_)) { return false; } - + if (!root_ || !cJSON_IsObject(root_)) { + cerr << "Error: ReferenceParser root node not obeject." << NEW_LINE_PATH << from << endl; + return RESTOOL_ERROR; + } bool needSave = false; - if (!ParseRefJsonImpl(root, needSave)) { + if (!ParseRefJsonImpl(root_, needSave)) { return false; } @@ -155,7 +160,7 @@ bool ReferenceParser::ParseRefJson(const string &from, const string &to) const return false; } - if (!ResourceUtil::SaveToJsonFile(to, root)) { + if (!ResourceUtil::SaveToJsonFile(to, root_)) { return false; } return true; @@ -287,22 +292,16 @@ bool ReferenceParser::ParseRefImpl(string &key, const map &refs return false; } -bool ReferenceParser::ParseRefJsonImpl(Json::Value &node, bool &needSave) const +bool ReferenceParser::ParseRefJsonImpl(cJSON *node, bool &needSave) const { - if (node.isObject()) { - for (const auto &member : node.getMemberNames()) { - if (!ParseRefJsonImpl(node[member], needSave)) { + if (cJSON_IsObject(node) || cJSON_IsArray(node)) { + for (cJSON *item = node->child; item; item = item->next) { + if (!ParseRefJsonImpl(item, needSave)) { return false; } } - } else if (node.isArray()) { - for (Json::ArrayIndex i = 0; i < node.size(); i++) { - if (!ParseRefJsonImpl(node[i], needSave)) { - return false; - } - } - } else if (node.isString()) { - string value = node.asString(); + } else if (cJSON_IsString(node)) { + string value = node->valuestring; bool update = false; if (!ParseRefString(value, update)) { return false; @@ -310,7 +309,7 @@ bool ReferenceParser::ParseRefJsonImpl(Json::Value &node, bool &needSave) const if (update) { needSave = update; } - node = value; + cJSON_SetValuestring(node, value.c_str()); } return true; } diff --git a/src/resconfig_parser.cpp b/src/resconfig_parser.cpp new file mode 100644 index 0000000..2abdd7e --- /dev/null +++ b/src/resconfig_parser.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2024 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 "resconfig_parser.h" +#include +#include "restool_errors.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; +ResConfigParser::ResConfigParser() : root_(nullptr) {} +ResConfigParser::~ResConfigParser() +{ + if (root_) { + cJSON_Delete(root_); + } +} +uint32_t ResConfigParser::Init(const string &filePath, HandleBack callback) +{ + if (!ResourceUtil::OpenJsonFile(filePath, &root_)) { + return RESTOOL_ERROR; + } + if (!root_ || !cJSON_IsObject(root_)) { + cerr << "Error: ResConfigParser root node not obeject." << NEW_LINE_PATH << filePath << endl; + return RESTOOL_ERROR; + } + if (!callback) { + return RESTOOL_SUCCESS; + } + + InitFileListCommand(callback); + + for (cJSON *item = root_->child; item; item = item->next) { + auto handler = fileListHandles_.find(item->string); + if (handler == fileListHandles_.end()) { + cout << "Warning: unsupport " << item->string << endl; + continue; + } + if (handler->second(item) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + } + + callback(Option::FORCEWRITE, ""); + return RESTOOL_SUCCESS; +} + +// below private +void ResConfigParser::InitFileListCommand(HandleBack callback) +{ + using namespace placeholders; + fileListHandles_.emplace("configPath", bind(&ResConfigParser::GetString, this, _1, + Option::JSON, callback)); + fileListHandles_.emplace("packageName", bind(&ResConfigParser::GetString, this, _1, + Option::PACKAGENAME, callback)); + fileListHandles_.emplace("output", bind(&ResConfigParser::GetString, this, _1, + Option::OUTPUTPATH, callback)); + fileListHandles_.emplace("startId", bind(&ResConfigParser::GetString, this, _1, + Option::STARTID, callback)); + fileListHandles_.emplace("entryCompiledResource", bind(&ResConfigParser::GetString, this, _1, + Option::DEPENDENTRY, callback)); + fileListHandles_.emplace("ids", bind(&ResConfigParser::GetString, this, _1, + Option::IDS, callback)); + fileListHandles_.emplace("definedIds", bind(&ResConfigParser::GetString, this, _1, + Option::DEFINED_IDS, callback)); + fileListHandles_.emplace("applicationResource", bind(&ResConfigParser::GetString, this, _1, + Option::INPUTPATH, callback)); + fileListHandles_.emplace("ResourceTable", bind(&ResConfigParser::GetArray, this, _1, + Option::RESHEADER, callback)); + fileListHandles_.emplace("moduleResources", bind(&ResConfigParser::GetArray, this, _1, + Option::INPUTPATH, callback)); + fileListHandles_.emplace("dependencies", bind(&ResConfigParser::GetArray, this, _1, + Option::INPUTPATH, callback)); + fileListHandles_.emplace("moduleNames", bind(&ResConfigParser::GetModuleNames, this, _1, + Option::MODULES, callback)); + fileListHandles_.emplace("iconCheck", bind(&ResConfigParser::GetBool, this, _1, + Option::ICON_CHECK, callback)); +} + +uint32_t ResConfigParser::GetString(const cJSON *node, int c, HandleBack callback) +{ + if (!node || !cJSON_IsString(node)) { + cerr << "Error: GetString node not string. Option = " << c << endl; + return RESTOOL_ERROR; + } + + if (callback(c, node->valuestring) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t ResConfigParser::GetArray(const cJSON *node, int c, HandleBack callback) +{ + if (!node || !cJSON_IsArray(node)) { + cerr << "Error: GetArray node not array. Option = " << c << endl; + return RESTOOL_ERROR; + } + + for (cJSON *item = node->child; item; item = item->next) { + if (!cJSON_IsString(item)) { + return RESTOOL_ERROR; + } + if (callback(c, item->valuestring) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + } + return RESTOOL_SUCCESS; +} + +uint32_t ResConfigParser::GetModuleNames(const cJSON *node, int c, HandleBack callback) +{ + if (!node) { + cerr << "Error: GetModuleNames node is null. Option = " << c << endl; + return RESTOOL_ERROR; + } + if (cJSON_IsString(node)) { + return GetString(node, c, callback); + } + string moduleNames; + if (GetArray(node, c, [&moduleNames](int c, const string &argValue) { + if (!moduleNames.empty()) { + moduleNames.append(","); + } + moduleNames.append(argValue); + return RESTOOL_SUCCESS; + }) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (!moduleNames.empty() && callback(c, moduleNames) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t ResConfigParser::GetBool(const cJSON *node, int c, HandleBack callback) +{ + if (!node || !cJSON_IsBool(node)) { + cerr << "Error: GetBool node not bool. Option = " << c << endl; + return RESTOOL_ERROR; + } + + if (cJSON_IsTrue(node) == 1 && callback(c, "") != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} +} +} +} diff --git a/src/resource_check.cpp b/src/resource_check.cpp index 2b1a878..da84785 100755 --- a/src/resource_check.cpp +++ b/src/resource_check.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 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 @@ -25,17 +25,16 @@ namespace { constexpr int PNG_BYTRS_TO_CHECK = 8; } -ResourceCheck::ResourceCheck(const ConfigParser &configJson, const shared_ptr &resourceAppend) - : configJson_(configJson), resourceAppend_(resourceAppend) +ResourceCheck::ResourceCheck(const std::map> &jsonCheckIds, + const shared_ptr &resourceAppend) : jsonCheckIds_(jsonCheckIds), resourceAppend_(resourceAppend) { } void ResourceCheck::CheckConfigJson() { - const map> jsonCheckIds = configJson_.GetCheckNode(); auto &fileManager = FileManager::GetInstance(); auto &allResource = fileManager.GetResources(); - for (auto it = jsonCheckIds.begin(); it != jsonCheckIds.end(); it++) { + for (auto it = jsonCheckIds_.begin(); it != jsonCheckIds_.end(); it++) { for (const auto &id : it->second) { auto res = allResource.find(id); if (res == allResource.end()) { @@ -50,9 +49,8 @@ void ResourceCheck::CheckConfigJson() void ResourceCheck::CheckConfigJsonForCombine() { - const map> jsonCheckIds = configJson_.GetCheckNode(); auto &allResource = resourceAppend_->GetItems(); - for (auto it = jsonCheckIds.begin(); it != jsonCheckIds.end(); it++) { + for (auto it = jsonCheckIds_.begin(); it != jsonCheckIds_.end(); it++) { for (const auto &id : it->second) { auto res = allResource.find(id); if (res == allResource.end()) { diff --git a/src/resource_pack.cpp b/src/resource_pack.cpp index f44520c..02581d5 100644 --- a/src/resource_pack.cpp +++ b/src/resource_pack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -19,9 +19,9 @@ #include "file_entry.h" #include "file_manager.h" #include "header.h" +#include "resource_check.h" #include "resource_merge.h" #include "resource_table.h" -#include "resource_check.h" namespace OHOS { namespace Global { @@ -63,10 +63,10 @@ uint32_t ResourcePack::Init() uint32_t ResourcePack::InitModule() { - IdWorker::ResourceIdCluster hapType = IdWorker::ResourceIdCluster::RES_ID_APP; + ResourceIdCluster hapType = ResourceIdCluster::RES_ID_APP; string packageName = packageParser_.GetPackageName(); if (packageName == "ohos.global.systemres") { - hapType = IdWorker::ResourceIdCluster::RES_ID_SYS; + hapType = ResourceIdCluster::RES_ID_SYS; } moduleName_ = configJson_.GetModuleName(); @@ -177,7 +177,7 @@ uint32_t ResourcePack::GenerateTextHeader(const string &headerPath) const Header textHeader(headerPath); bool first = true; uint32_t result = textHeader.Create([](stringstream &buffer) {}, - [&first](stringstream &buffer, const IdWorker::ResourceId& resourceId) { + [&first](stringstream &buffer, const ResourceId& resourceId) { if (first) { first = false; } else { @@ -201,7 +201,7 @@ uint32_t ResourcePack::GenerateCplusHeader(const string &headerPath) const buffer << "#define RESOURCE_TABLE_H\n\n"; buffer << "#include\n\n"; buffer << "namespace OHOS {\n"; - }, [](stringstream &buffer, const IdWorker::ResourceId& resourceId) { + }, [](stringstream &buffer, const ResourceId& resourceId) { string name = resourceId.type + "_" + resourceId.name; transform(name.begin(), name.end(), name.begin(), ::toupper); buffer << "const int32_t " << name << " = "; @@ -220,7 +220,7 @@ uint32_t ResourcePack::GenerateJsHeader(const std::string &headerPath) const uint32_t result = JsHeader.Create([](stringstream &buffer) { buffer << Header::LICENSE_HEADER << "\n"; buffer << "export default {\n"; - }, [&itemType](stringstream &buffer, const IdWorker::ResourceId& resourceId) { + }, [&itemType](stringstream &buffer, const ResourceId& resourceId) { if (itemType != resourceId.type) { if (!itemType.empty()) { buffer << "\n" << " " << "},\n"; @@ -317,7 +317,7 @@ uint32_t ResourcePack::GenerateConfigJson() void ResourcePack::CheckConfigJson() { - ResourceCheck resourceCheck(configJson_); + ResourceCheck resourceCheck(configJson_.GetCheckNode()); resourceCheck.CheckConfigJson(); } @@ -591,7 +591,7 @@ uint32_t ResourcePack::PackCombine() void ResourcePack::CheckConfigJsonForCombine(ResourceAppend &resourceAppend) { - ResourceCheck resourceCheck(configJson_, make_shared(resourceAppend)); + ResourceCheck resourceCheck(configJson_.GetCheckNode(), make_shared(resourceAppend)); resourceCheck.CheckConfigJsonForCombine(); } diff --git a/src/resource_table.cpp b/src/resource_table.cpp index 977fcc0..dffa35c 100644 --- a/src/resource_table.cpp +++ b/src/resource_table.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -14,6 +14,7 @@ */ #include "resource_table.h" +#include #include "cmd_parser.h" #include "file_entry.h" #include "file_manager.h" @@ -147,9 +148,11 @@ uint32_t ResourceTable::LoadResTable(const string path, map> &allResource) const { - Json::Value root; + cJSON *root = cJSON_CreateObject(); + cJSON *recordArray = cJSON_CreateArray(); + cJSON_AddItemToObject(root, "record", recordArray); for (const auto &pairPtr : allResource) { - Json::Value jsonItem; + cJSON *jsonItem = cJSON_CreateObject(); ResourceItem item = pairPtr.second.front(); ResType resType = item.GetResType(); string type = ResourceUtil::ResTypeToString(resType); @@ -160,22 +163,14 @@ uint32_t ResourceTable::CreateIdDefined(const map> cerr << ResourceUtil::GetAllRestypeString() << endl; return RESTOOL_ERROR; } - jsonItem["type"] = type; - jsonItem["name"] = ResourceUtil::GetIdName(name, resType); - jsonItem["id"] = ResourceUtil::DecToHexStr(id); - root["record"].append(jsonItem); + cJSON_AddStringToObject(jsonItem, "type", type.c_str()); + cJSON_AddStringToObject(jsonItem, "name", ResourceUtil::GetIdName(name, resType).c_str()); + cJSON_AddStringToObject(jsonItem, "id", ResourceUtil::DecToHexStr(id).c_str()); + cJSON_AddItemToArray(recordArray, jsonItem); } - - ofstream out(idDefinedPath_, ofstream::out | ofstream::binary); - if (!out.is_open()) { - cerr << "Error: open failed '" << idDefinedPath_ << "',reason: " << strerror(errno) << endl; + if (!ResourceUtil::SaveToJsonFile(idDefinedPath_, root)) { return RESTOOL_ERROR; } - Json::StreamWriterBuilder jswBuilder; - jswBuilder["indentation"] = ID_DEFINED_INDENTATION; - unique_ptr writer(jswBuilder.newStreamWriter()); - writer->write(root, &out); - out.close(); return RESTOOL_SUCCESS; } diff --git a/src/resource_util.cpp b/src/resource_util.cpp index 716951d..7e10039 100644 --- a/src/resource_util.cpp +++ b/src/resource_util.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -20,6 +20,7 @@ #include #include #include +#include #include "file_entry.h" namespace OHOS { @@ -69,7 +70,7 @@ bool ResourceUtil::RmoveAllDir(const string &path) return FileEntry::RemoveAllDir(path); } -bool ResourceUtil::OpenJsonFile(const string &path, Json::Value &root) +bool ResourceUtil::OpenJsonFile(const string &path, cJSON **root) { ifstream ifs(FileEntry::AdaptLongPath(path), ios::binary); if (!ifs.is_open()) { @@ -77,13 +78,11 @@ bool ResourceUtil::OpenJsonFile(const string &path, Json::Value &root) return false; } - Json::CharReaderBuilder readBuilder; - readBuilder["collectComments"] = false; - readBuilder["failIfExtra"] = true; - JSONCPP_STRING errs; - if (!parseFromStream(readBuilder, ifs, &root, &errs)) { - cerr << "Error: parseFromStream failed." << NEW_LINE_PATH << path; - cerr << "\n" << errs << endl; + string jsonString((istreambuf_iterator(ifs)), istreambuf_iterator()); + *root = cJSON_Parse(jsonString.c_str()); + if (!root) { + cerr << "Error: cJSON_Parse failed." << NEW_LINE_PATH << path; + cerr << "\n" << cJSON_GetErrorPtr() << endl; ifs.close(); return false; } @@ -91,18 +90,17 @@ bool ResourceUtil::OpenJsonFile(const string &path, Json::Value &root) return true; } -bool ResourceUtil::SaveToJsonFile(const string &path, const Json::Value &root) +bool ResourceUtil::SaveToJsonFile(const string &path, const cJSON *root) { - Json::StreamWriterBuilder writerBuilder; - writerBuilder["indentation"] = " "; - writerBuilder["emitUTF8"] = true; - unique_ptr writer(writerBuilder.newStreamWriter()); ofstream out(FileEntry::AdaptLongPath(path), ofstream::out | ofstream::binary); if (!out.is_open()) { - cerr << "Error: open failed '" << path <<"', reason: " << strerror(errno) << endl; + cerr << "Error: SaveToJsonFile open failed '" << path <<"', reason: " << strerror(errno) << endl; return false; } - writer->write(root, &out); + char *jsonString = cJSON_Print(root); + out << jsonString; + free(jsonString); + out.close(); return true; } @@ -433,6 +431,28 @@ void ResourceUtil::RemoveSpaces(string &str) str.erase(str.find_last_not_of(" ") + 1); // move back one place } +bool ResourceUtil::IsValidSystemName(const string &name) +{ + if (regex_match(name, regex("^ohos.+"))) { + return true; + } + cerr << "Error: '" << name << "' must start with 'ohos'" << endl; + return false; +} + +bool ResourceUtil::IsIntValue(const cJSON *node) +{ + if (node && cJSON_IsNumber(node)) { + double num = node->valuedouble; + if (num == static_cast(num)) { + return true; + } else { + return false; + } + } + return false; +} + } } } diff --git a/src/restool.cpp b/src/restool.cpp index 85e780d..97039e0 100644 --- a/src/restool.cpp +++ b/src/restool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 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 @@ -24,11 +24,6 @@ uint32_t ProccssHap(PackageParser &packageParser) TaskHandle taskHandle; return taskHandle.HandlePackage(packageParser); } - -uint32_t PackCmdHandle(PackageParser &packageParser) -{ - return ProccssHap(packageParser); -} } int main(int argc, char *argv[]) @@ -44,7 +39,7 @@ int main(int argc, char *argv[]) } auto &packageParser = parser.GetCmdParser(); - if (PackCmdHandle(packageParser) != RESTOOL_SUCCESS) { + if (ProccssHap(packageParser) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } cout << "Info: restool resources compile success." << endl;