From f21607c49650a5255e9030c78272236861477bfd Mon Sep 17 00:00:00 2001 From: HanSY Date: Tue, 12 Nov 2024 11:39:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8F=A0=E5=8A=A0=E7=BC=96?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: HanSY --- include/binary_file_packer.h | 4 ++ include/cmd_parser.h | 3 ++ include/file_manager.h | 3 ++ include/i_resource_compiler.h | 2 + include/id_worker.h | 2 + include/resource_data.h | 1 + include/resource_item.h | 4 ++ include/resource_merge.h | 3 +- include/resource_module.h | 2 +- include/resource_pack.h | 2 + src/binary_file_packer.cpp | 43 +++++++++++++++++++- src/cmd_parser.cpp | 20 ++++++++++ src/file_manager.cpp | 21 +++++++++- src/generic_compiler.cpp | 13 +++++- src/i_resource_compiler.cpp | 5 +++ src/id_worker.cpp | 15 +++++++ src/resource_item.cpp | 11 ++++++ src/resource_merge.cpp | 19 ++++++--- src/resource_module.cpp | 9 ++++- src/resource_pack.cpp | 74 ++++++++++++++++++++++++++++++++++- src/resource_table.cpp | 4 ++ 21 files changed, 244 insertions(+), 16 deletions(-) diff --git a/include/binary_file_packer.h b/include/binary_file_packer.h index b01f9ee..308fbd2 100644 --- a/include/binary_file_packer.h +++ b/include/binary_file_packer.h @@ -29,17 +29,21 @@ public: ~BinaryFilePacker(); std::future CopyBinaryFileAsync(const std::vector &inputs); void StopCopy(); + void SetCopyHapMode(bool state); private: uint32_t CopyBinaryFile(const std::vector &inputs); uint32_t CopyBinaryFile(const std::string &filePath, const std::string &fileType); uint32_t CopyBinaryFileImpl(const std::string &src, const std::string &dst); uint32_t CopySingleFile(const std::string &path, std::string &subPath); + uint32_t CopyBinaryFileWithHap(const std::vector &inputs); PackageParser packageParser_; std::string moduleName_; ThreadPool threadPool_; std::vector> copyResults_; std::atomic stopCopy_{false}; + bool copyHapMode_{false}; + std::mutex mutex_; }; } // namespace Restool } // namespace Global diff --git a/include/cmd_parser.h b/include/cmd_parser.h index 7f3772c..b85fad0 100644 --- a/include/cmd_parser.h +++ b/include/cmd_parser.h @@ -57,6 +57,8 @@ public: bool IsTargetConfig() const; const std::vector &GetSysIdDefinedPaths() const; const std::string &GetCompressionPath() const; + bool ExistIndex(); + bool GetOverlap(); private: void InitCommand(); @@ -112,6 +114,7 @@ private: bool isTtargetConfig_; std::vector sysIdDefinedPaths_; std::string compressionPath_; + bool overlap_ = false; }; template diff --git a/include/file_manager.h b/include/file_manager.h index 5d19a4a..b2de5a8 100644 --- a/include/file_manager.h +++ b/include/file_manager.h @@ -35,8 +35,10 @@ public: { moduleName_ = moduleName; }; + void SetHapItems(); uint32_t MergeResourceItem(const std::map> &resourceInfos); bool ScaleIcons(const std::string &output, const std::map> &iconMap); + void SetHapMode(bool state); private: uint32_t ScanModule(const std::string &input, const std::string &output); @@ -47,6 +49,7 @@ private: // id, resource items std::map> items_; std::string moduleName_; + bool hapMode_ = false; }; } } diff --git a/include/i_resource_compiler.h b/include/i_resource_compiler.h index ad7c69b..301dc25 100644 --- a/include/i_resource_compiler.h +++ b/include/i_resource_compiler.h @@ -33,6 +33,7 @@ public: void SetModuleName(const std::string &moduleName); uint32_t CompileForAppend(const FileInfo &fileInfo); const std::map, std::vector> &GetResourceItems() const; + void SetHapRes(); protected: virtual uint32_t CompileSingleFile(const FileInfo &fileInfo); @@ -42,6 +43,7 @@ protected: ResType type_; std::string output_; std::string moduleName_; + bool isHapRes_ = false; // id, resource items std::map> resourceInfos_; diff --git a/include/id_worker.h b/include/id_worker.h index d080ac0..3fe29e2 100644 --- a/include/id_worker.h +++ b/include/id_worker.h @@ -19,6 +19,7 @@ #include #include "id_defined_parser.h" #include "resource_data.h" +#include "resource_item.h" #include "resource_util.h" #include "singleton.h" @@ -32,6 +33,7 @@ public: std::vector GetHeaderId() const; int64_t GetId(ResType resType, const std::string &name) const; int64_t GetSystemId(ResType resType, const std::string &name) const; + void LoadIdFromHap(const std::map> &items); private: int64_t GenerateAppId(ResType resType, const std::string &name); diff --git a/include/resource_data.h b/include/resource_data.h index 231a01c..fe80c45 100644 --- a/include/resource_data.h +++ b/include/resource_data.h @@ -52,6 +52,7 @@ const static int32_t INT_TO_BYTES = sizeof(uint32_t); static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 5.012" }; const static int32_t TAG_LEN = 4; static std::set g_resourceSet; +static std::set g_hapResourceSet; const static int8_t THREAD_POOL_SIZE = 2; const static int8_t INVALID_ID = -1; diff --git a/include/resource_item.h b/include/resource_item.h index e6699e9..a6c462d 100644 --- a/include/resource_item.h +++ b/include/resource_item.h @@ -34,6 +34,7 @@ public: void SetFilePath(const std::string &filePath); void SetLimitKey(const std::string &limitKey); void SetName(const std::string &name); + void SetHapRes(); const int8_t *GetData() const; uint32_t GetDataLength() const; @@ -43,6 +44,8 @@ public: const std::string &GetFilePath() const; const std::string &GetLimitKey() const; + bool IsHapRes() const; + ResourceItem &operator=(const ResourceItem &other); private: void ReleaseData(); @@ -54,6 +57,7 @@ private: ResType type_; std::string filePath_; std::string limitKey_; + bool isHapRes_ = false; }; } } diff --git a/include/resource_merge.h b/include/resource_merge.h index a58e1a5..7a2c3a0 100644 --- a/include/resource_merge.h +++ b/include/resource_merge.h @@ -20,6 +20,7 @@ #include #include "config_parser.h" #include "restool_errors.h" +#include "cmd_parser.h" namespace OHOS { namespace Global { @@ -28,7 +29,7 @@ class ResourceMerge { public: ResourceMerge(); virtual ~ResourceMerge(); - uint32_t Init(); + uint32_t Init(const PackageParser &packageParser = CmdParser::GetInstance().GetCmdParser()); const std::vector &GetInputs() const; private: std::vector inputsOrder_; diff --git a/include/resource_module.h b/include/resource_module.h index 3e13805..0839466 100644 --- a/include/resource_module.h +++ b/include/resource_module.h @@ -27,7 +27,7 @@ class ResourceModule { public: ResourceModule(const std::string &modulePath, const std::string &moduleOutput, const std::string &moduleName); virtual ~ResourceModule() {}; - uint32_t ScanResource(); + uint32_t ScanResource(bool isHap = false); const std::map> &GetOwner() const; const std::map> &GetScanDirectorys() const; static uint32_t MergeResourceItem(std::map> &alls, diff --git a/include/resource_pack.h b/include/resource_pack.h index 9f566fe..f23c28f 100644 --- a/include/resource_pack.h +++ b/include/resource_pack.h @@ -50,6 +50,7 @@ private: uint32_t PackPreview(); uint32_t PackAppend(); uint32_t PackCombine(); + uint32_t PackOverlap(); uint32_t PackQualifierResources(const ResourceMerge &resourceMerge); uint32_t HandleFeature(); uint32_t FindResourceItems(const std::map> &resInfoLocal, @@ -60,6 +61,7 @@ private: void CheckConfigJson(); void CheckConfigJsonForCombine(ResourceAppend &resourceAppend); bool CopyIcon(std::string &dataPath, const std::string &idName, std::string &fileName) const; + uint32_t LoadHapResources(); PackageParser packageParser_; std::string moduleName_; using HeaderCreater = std::function; diff --git a/src/binary_file_packer.cpp b/src/binary_file_packer.cpp index 75cf11b..2444131 100644 --- a/src/binary_file_packer.cpp +++ b/src/binary_file_packer.cpp @@ -39,13 +39,38 @@ void BinaryFilePacker::StopCopy() stopCopy_.store(true); } +void BinaryFilePacker::SetCopyHapMode(bool state) +{ + copyHapMode_ = state; +} + std::future BinaryFilePacker::CopyBinaryFileAsync(const std::vector &inputs) { - auto func = [this](const std::vector &inputs) { return this->CopyBinaryFile(inputs); }; + if (copyHapMode_) { + auto func = [this](const vector &inputs) { return this->CopyBinaryFileWithHap(inputs); }; + future res = threadPool_.Enqueue(func, inputs); + return res; + } + auto func = [this](const vector &inputs) { return this->CopyBinaryFile(inputs); }; std::future res = threadPool_.Enqueue(func, inputs); return res; } +uint32_t BinaryFilePacker::CopyBinaryFileWithHap(const vector &inputs) +{ + vector hapResource(inputs.begin(), inputs.begin() + 1); + if (CopyBinaryFile(hapResource) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + copyResults_.clear(); + SetCopyHapMode(false); + vector resource(inputs.begin() + 1, inputs.end()); + if (CopyBinaryFile(resource) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + uint32_t BinaryFilePacker::CopyBinaryFile(const vector &inputs) { for (const auto &input : inputs) { @@ -116,14 +141,28 @@ uint32_t BinaryFilePacker::CopyBinaryFileImpl(const string &src, const string &d continue; } - if (!g_resourceSet.emplace(subPath).second) { + bool hapEmplaceSuccess = true; + bool gResEmplaceSuccess = true; + lock_guard lock(mutex_); + if (copyHapMode_) { + hapEmplaceSuccess = g_hapResourceSet.emplace(subPath).second; + gResEmplaceSuccess = g_resourceSet.emplace(subPath).second; + } else if (g_hapResourceSet.count(subPath)) { // overlap the hap resource by new resource + g_hapResourceSet.erase(subPath); + } else { + gResEmplaceSuccess = g_resourceSet.emplace(subPath).second; + } + + if (!hapEmplaceSuccess || !gResEmplaceSuccess) { cerr << "Warning: '" << entry->GetFilePath().GetPath() << "' is defined repeatedly." << endl; continue; } + if (stopCopy_.load()) { cout << "Info: CopyBinaryFileImpl: stop copy binary file." << endl; return RESTOOL_ERROR; } + string path = entry->GetFilePath().GetPath(); auto copyFunc = [this](const string path, string subPath) { return this->CopySingleFile(path, subPath); }; std::future res = threadPool_.Enqueue(copyFunc, path, subPath); diff --git a/src/cmd_parser.cpp b/src/cmd_parser.cpp index 8c09d3a..4e980c6 100644 --- a/src/cmd_parser.cpp +++ b/src/cmd_parser.cpp @@ -18,6 +18,7 @@ #include "resconfig_parser.h" #include "resource_util.h" #include "select_compile_parse.h" +#include "file_entry.h" namespace OHOS { namespace Global { @@ -443,6 +444,25 @@ const std::string &PackageParser::GetCompressionPath() const return compressionPath_; } +bool PackageParser::ExistIndex() +{ + for (auto &input : inputs_) { + string indexPath = ResourceUtil::GetMainPath(input).Append(RESOURCE_INDEX_FILE).GetPath(); + if (ResourceUtil::FileExist(indexPath)) { + inputs_.erase(find(inputs_.begin(), inputs_.end(), input)); + inputs_.emplace(inputs_.begin(), input); + overlap_ = true; + return true; + } + } + return false; +} + +bool PackageParser::GetOverlap() +{ + return overlap_; +} + void PackageParser::InitCommand() { using namespace placeholders; diff --git a/src/file_manager.cpp b/src/file_manager.cpp index 125d01a..9189c3d 100644 --- a/src/file_manager.cpp +++ b/src/file_manager.cpp @@ -42,7 +42,19 @@ uint32_t FileManager::ScanModules(const vector &inputs, const string &ou if (!noBaseResource.empty()) { ResourceUtil::PrintWarningMsg(noBaseResource); } - return isHar ? RESTOOL_SUCCESS : ParseReference(output); + if (hapMode_) { + SetHapItems(); + } + return isHar || hapMode_ ? RESTOOL_SUCCESS : ParseReference(output); +} + +void FileManager::SetHapItems() +{ + for (auto &item : items_) { + for (auto &resourceItem : item.second) { + resourceItem.SetHapRes(); + } + } } uint32_t FileManager::MergeResourceItem(const map> &resourceInfos) @@ -54,7 +66,7 @@ uint32_t FileManager::MergeResourceItem(const map> uint32_t FileManager::ScanModule(const string &input, const string &output) { ResourceModule resourceModule(input, output, moduleName_); - if (resourceModule.ScanResource() != RESTOOL_SUCCESS) { + if (resourceModule.ScanResource(hapMode_) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } MergeResourceItem(resourceModule.GetOwner()); @@ -120,6 +132,11 @@ bool FileManager::ScaleIcons(const string &output, const std::map lock(mutex_); string output = GetOutputFilePath(fileInfo); - if (!g_resourceSet.emplace(output).second) { + bool hapEmplaceSuccess = true; + bool gResEmplaceSuccess = true; + if (isHapRes_) { + hapEmplaceSuccess = g_hapResourceSet.emplace(output).second; + gResEmplaceSuccess = g_resourceSet.emplace(output).second; + } else if (g_hapResourceSet.count(output)) { // overlap the hap resource by new resource + g_hapResourceSet.erase(output); + } else { + gResEmplaceSuccess = g_resourceSet.emplace(output).second; + } + + if (!hapEmplaceSuccess || !gResEmplaceSuccess) { cerr << "Warning: '" << fileInfo.filePath << "' is defined repeatedly." << endl; return true; } diff --git a/src/i_resource_compiler.cpp b/src/i_resource_compiler.cpp index e964fe3..6c01d65 100644 --- a/src/i_resource_compiler.cpp +++ b/src/i_resource_compiler.cpp @@ -104,6 +104,11 @@ const map, vector> &IResourceCompiler::GetRe return nameInfos_; } +void IResourceCompiler::SetHapRes() +{ + isHapRes_ = true; +} + void IResourceCompiler::SetModuleName(const string &moduleName) { moduleName_ = moduleName; diff --git a/src/id_worker.cpp b/src/id_worker.cpp index af0e76e..c97031c 100644 --- a/src/id_worker.cpp +++ b/src/id_worker.cpp @@ -84,6 +84,21 @@ int64_t IdWorker::GetSystemId(ResType resType, const string &name) const return result->second.id; } +void IdWorker::LoadIdFromHap(const map> &items) +{ + int64_t minId = 0xffffffff; + int64_t maxId = 0x01000000; + for (const auto &item : items) { + for (const auto &resourceItem : item.second) { + ids_.emplace(make_pair(resourceItem.GetResType(), resourceItem.GetName()), item.first); + } + minId = min(minId, item.first); + maxId = max(maxId, item.first); + } + maxId_ = GetMaxId(minId); + appId_ = maxId + 1; +} + int64_t IdWorker::GenerateAppId(ResType resType, const string &name) { auto result = ids_.find(make_pair(resType, name)); diff --git a/src/resource_item.cpp b/src/resource_item.cpp index e45c1cd..656b263 100644 --- a/src/resource_item.cpp +++ b/src/resource_item.cpp @@ -85,6 +85,11 @@ void ResourceItem::SetName(const string &name) name_ = name; } +void ResourceItem::SetHapRes() +{ + isHapRes_ = true; +} + const int8_t *ResourceItem::GetData() const { return data_; @@ -120,6 +125,11 @@ const string &ResourceItem::GetLimitKey() const return limitKey_; } +bool ResourceItem::IsHapRes() const +{ + return isHapRes_; +} + ResourceItem &ResourceItem::operator=(const ResourceItem &other) { if (this == &other) { @@ -147,6 +157,7 @@ void ResourceItem::CopyFrom(const ResourceItem &other) dataLen_ = other.dataLen_; filePath_ = other.filePath_; limitKey_ = other.limitKey_; + isHapRes_ = other.isHapRes_; if (!SetData(other.data_, other.dataLen_)) { ReleaseData(); } diff --git a/src/resource_merge.cpp b/src/resource_merge.cpp index 884e9fb..e247f0f 100644 --- a/src/resource_merge.cpp +++ b/src/resource_merge.cpp @@ -14,7 +14,6 @@ */ #include "resource_merge.h" -#include "cmd_parser.h" #include "file_entry.h" namespace OHOS { @@ -37,21 +36,26 @@ ResourceMerge::~ResourceMerge() { } -uint32_t ResourceMerge::Init() +uint32_t ResourceMerge::Init(const PackageParser &packageParser) { - auto &cmdParser = CmdParser::GetInstance().GetCmdParser(); - const vector &inputs = cmdParser.GetInputs(); - if (cmdParser.IsFileList()) { + const vector &inputs = packageParser.GetInputs(); + if (packageParser.IsFileList()) { inputsOrder_ = inputs; return RESTOOL_SUCCESS; } map> inputTypes; + string hapDir = ""; for (auto it = inputs.crbegin(); it != inputs.crend(); it++) { string configPath = ResourceUtil::GetMainPath(*it).Append(ConfigParser::GetConfigName()).GetPath(); string resourceDir = FileEntry::FilePath(*it).GetPath(); + string indexPath = ResourceUtil::GetMainPath(*it).Append(RESOURCE_INDEX_FILE).GetPath(); + if (ResourceUtil::FileExist(indexPath)) { + hapDir = resourceDir; + continue; + } ConfigParser::ModuleType moduleType = ConfigParser::ModuleType::NONE; - if (!ResourceUtil::FileExist(configPath)) { + if (!ResourceUtil::FileExist(configPath) || ResourceUtil::FileExist(indexPath)) { inputTypes[moduleType].push_back(resourceDir); continue; } @@ -69,6 +73,9 @@ uint32_t ResourceMerge::Init() } inputsOrder_.insert(inputsOrder_.end(), inputTypes[type].begin(), inputTypes[type].end()); } + if (hapDir != "") { + inputsOrder_.insert(inputsOrder_.begin(), hapDir); + } return RESTOOL_SUCCESS; } diff --git a/src/resource_module.cpp b/src/resource_module.cpp index 726c5d9..83562d8 100644 --- a/src/resource_module.cpp +++ b/src/resource_module.cpp @@ -33,7 +33,7 @@ ResourceModule::ResourceModule(const string &modulePath, const string &moduleOut { } -uint32_t ResourceModule::ScanResource() +uint32_t ResourceModule::ScanResource(bool isHap) { if (!ResourceUtil::FileExist(modulePath_)) { return RESTOOL_SUCCESS; @@ -56,6 +56,9 @@ uint32_t ResourceModule::ScanResource() unique_ptr resourceCompiler = FactoryResourceCompiler::CreateCompiler(type, moduleOutput_); resourceCompiler->SetModuleName(moduleName_); + if (isHap) { + resourceCompiler->SetHapRes(); + } if (resourceCompiler->Compile(item->second) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } @@ -91,6 +94,10 @@ uint32_t ResourceModule::MergeResourceItem(map> &a result.first->second.push_back(resourceItem); continue; } + if (ret->IsHapRes()) { // overlap the hap resource by new resource + *ret = resourceItem; + continue; + } if (tipError) { cerr << "Error: '"<< resourceItem.GetName() <<"' conflict, first declared."; cerr << NEW_LINE_PATH << ret->GetFilePath() << endl; diff --git a/src/resource_pack.cpp b/src/resource_pack.cpp index 7a45297..4ae04b7 100644 --- a/src/resource_pack.cpp +++ b/src/resource_pack.cpp @@ -42,6 +42,10 @@ uint32_t ResourcePack::Package() if (packageParser_.GetCombine()) { return PackCombine(); } + + if (packageParser_.ExistIndex()) { + return PackOverlap(); + } return PackNormal(); } @@ -272,8 +276,20 @@ uint32_t ResourcePack::ScanResources(const vector &inputs, const string { auto &fileManager = FileManager::GetInstance(); fileManager.SetModuleName(moduleName_); - if (fileManager.ScanModules(inputs, output, configJson_.IsHar()) != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; + if (packageParser_.GetOverlap()) { + vector hapResInput{inputs[0]}; + if (fileManager.ScanModules(hapResInput, output, configJson_.IsHar()) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + fileManager.SetHapMode(false); + vector resInputs(inputs.begin() + 1, inputs.end()); + if (fileManager.ScanModules(resInputs, output, configJson_.IsHar()) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + } else { + if (fileManager.ScanModules(inputs, output, configJson_.IsHar()) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } } return RESTOOL_SUCCESS; } @@ -555,6 +571,60 @@ uint32_t ResourcePack::PackCombine() return RESTOOL_SUCCESS; } +uint32_t ResourcePack::PackOverlap() +{ + if (InitCompression() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + if (Init() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + ResourceMerge resourceMerge; + if (resourceMerge.Init(packageParser_) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + BinaryFilePacker rawFilePacker(packageParser_, moduleName_); + rawFilePacker.SetCopyHapMode(true); + std::future copyFuture = rawFilePacker.CopyBinaryFileAsync(resourceMerge.GetInputs()); + + if (LoadHapResources() != RESTOOL_SUCCESS) { + rawFilePacker.StopCopy(); + return RESTOOL_ERROR; + } + + if (PackQualifierResources(resourceMerge) != RESTOOL_SUCCESS) { + rawFilePacker.StopCopy(); + return RESTOOL_ERROR; + } + + uint32_t copyRet = copyFuture.get(); + return copyRet == RESTOOL_SUCCESS ? RESTOOL_SUCCESS : RESTOOL_ERROR; +} + +uint32_t ResourcePack::LoadHapResources() +{ + ResourceTable resourceTabel; + map> items; + string resourceIndexPath = + FileEntry::FilePath(packageParser_.GetInputs()[0]).GetParent().Append(RESOURCE_INDEX_FILE).GetPath(); + if (resourceTabel.LoadResTable(resourceIndexPath, items) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + IdWorker::GetInstance().LoadIdFromHap(items); + + FileManager &fileManager = FileManager::GetInstance(); + fileManager.SetModuleName(moduleName_); + if (fileManager.MergeResourceItem(items) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + fileManager.SetHapItems(); + fileManager.SetHapMode(true); + return RESTOOL_SUCCESS; +} + void ResourcePack::CheckConfigJsonForCombine(ResourceAppend &resourceAppend) { ResourceCheck resourceCheck(configJson_.GetCheckNode(), make_shared(resourceAppend)); diff --git a/src/resource_table.cpp b/src/resource_table.cpp index 856c5e5..54dd4fb 100644 --- a/src/resource_table.cpp +++ b/src/resource_table.cpp @@ -489,9 +489,13 @@ bool ResourceTable::ReadDataRecordStart(std::ifstream &in, RecordItem &record, cerr << "Error: invalid resources.index limit key offset." << endl; return false; } + const vector &keyparams = limitKeys.find(datas.find(offset)->second.second)->second; ResourceItem resourceitem(filename, keyparams, g_resTypeMap.find(record.resType)->second); resourceitem.SetLimitKey(ResourceUtil::PaserKeyParam(keyparams)); + if (values[value_size - 1] == '\0') { + value_size--; + } resourceitem.SetData(values, value_size); resInfos[record.id].push_back(resourceitem); return true;