Android常用C++特性之std::any_of

声明:本文内容生成自ChatGPT,目的是为方便大家了解学习作为引用到作者的其他文章中。

std::any_of 是 C++11 引入的一个标准库算法,用于检查一个范围内是否至少有一个元素满足指定条件。它接受一个范围(由迭代器指定)和一个谓词(条件函数),返回一个布尔值,指示是否存在至少一个元素使谓词返回 true

语法

#include <algorithm>

template <class InputIt, class UnaryPredicate>
bool any_of(InputIt first, InputIt last, UnaryPredicate pred);

参数

  • first, last:定义要检查的范围的迭代器。
  • pred:一个接受一个元素并返回布尔值的函数或可调用对象。

返回值

返回 true 如果范围内至少有一个元素满足谓词条件,否则返回 false

示例

1. 检查容器中是否存在特定条件的元素
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 检查是否有元素大于 3
    bool hasGreaterThanThree = std::any_of(numbers.begin(), numbers.end(), [](int n) {
        return n > 3;
    });

    if (hasGreaterThanThree) {
        std::cout << "There is at least one number greater than 3." << std::endl;
    } else {
        std::cout << "No numbers greater than 3." << std::endl;
    }

    return 0;
}

输出:

There is at least one number greater than 3.
2. 检查字符串中是否包含特定字符
#include <iostream>
#include <string>
#include <algorithm>

int main() {
    std::string str = "Hello, World!";

    // 检查字符串中是否包含字符 'W'
    bool containsW = std::any_of(str.begin(), str.end(), [](char c) {
        return c == 'W';
    });

    if (containsW) {
        std::cout << "The string contains 'W'." << std::endl;
    } else {
        std::cout << "The string does not contain 'W'." << std::endl;
    }

    return 0;
}

输出:

The string contains 'W'.

总结

  • std::any_of 是一个便捷的算法,用于快速检查范围内是否存在满足特定条件的元素。
  • 适用于各种容器,如数组、向量、列表等,具有简洁的语法和高效的执行。
  • 通过传递不同的谓词,可以灵活地处理各种条件检查。
/*This file has been modified by Unisoc (Shanghai) Technologies Co., Ltd in 2024. * * Copyright (C) 2007 The Android Open Source Project * * 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 "recovery_utils/roots.h" #include <fcntl.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <iostream> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> #include <ext4_utils/ext4_utils.h> #include <ext4_utils/wipe.h> #include <fs_mgr.h> #include <fs_mgr/roots.h> #include "otautil/sysutil.h" //hook #include <include/hook/librecovery_utils_stubs.h> using android::fs_mgr::Fstab; using android::fs_mgr::FstabEntry; using android::fs_mgr::ReadDefaultFstab; using android::base::ReadFileToString; static Fstab fstab; constexpr const char* CACHE_ROOT = "/cache"; void load_volume_table() { if (!ReadDefaultFstab(&fstab)) { LOG(ERROR) << "Failed to read default fstab"; return; } fstab.emplace_back(FstabEntry{ .blk_device = "ramdisk", .mount_point = "/tmp", .fs_type = "ramdisk", .length = 0, }); std::cout << "recovery filesystem table" << std::endl << "=========================" << std::endl; for (size_t i = 0; i < fstab.size(); ++i) { auto& entry = fstab[i]; if (strcmp(entry.mount_point.c_str(), "/storage/sdcard0") == 0) load_volume_table_impl(entry); std::cout << " " << i << " " << entry.mount_point << " " << " " << entry.fs_type << " " << entry.blk_device << " " << entry.length << std::endl; } std::cout << std::endl; } Volume* volume_for_mount_point(const std::string& mount_point) { return android::fs_mgr::GetEntryForMountPoint(&fstab, mount_point); } // Mount the volume specified by path at the given mount_point. int ensure_path_mounted_at(const std::string& path, const std::string& mount_point) { return android::fs_mgr::EnsurePathMounted(&fstab, path, mount_point) ? 0 : -1; } int ensure_path_mounted(const std::string& path) { // Mount at the default mount point. return android::fs_mgr::EnsurePathMounted(&fstab, path) ? 0 : -1; } int ensure_path_unmounted(const std::string& path) { return android::fs_mgr::EnsurePathUnmounted(&fstab, path) ? 0 : -1; } static int exec_cmd(const std::vector<std::string>& args) { CHECK(!args.empty()); auto argv = StringVectorToNullTerminatedArray(args); pid_t child; if ((child = fork()) == 0) { execv(argv[0], argv.data()); _exit(EXIT_FAILURE); } int status; waitpid(child, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status); } return WEXITSTATUS(status); } static int64_t get_file_size(int fd, uint64_t reserve_len) { struct stat buf; int ret = fstat(fd, &buf); if (ret) return 0; int64_t computed_size; if (S_ISREG(buf.st_mode)) { computed_size = buf.st_size - reserve_len; } else if (S_ISBLK(buf.st_mode)) { uint64_t block_device_size = get_block_device_size(fd); if (block_device_size < reserve_len || block_device_size > std::numeric_limits<int64_t>::max()) { computed_size = 0; } else { computed_size = block_device_size - reserve_len; } } else { computed_size = 0; } return computed_size; } //#wangfengqiu@HQ, 2024/03/28, Add for: nuovo shield recovery clear data plan start bool forbiddenRecoveryByReserveProperty() { std::string content; std::vector<std::string> reserve2_property_path = { "/nuovo/productinfo/nuovo_forbidden_recovery.prop", // 原Nuovo路径 "/nuovo/productinfo/MACROPAY_forbidden_recovery.prop", // 新增MACROPAY路径 }; //Fstab defFstab; /*if (!ReadDefaultFstab(&defFstab)) { printf("Failed to read default fstab productinfo\n"); return false; }*/ //for (size_t i = 0; i < defFstab.size(); ++i) { //const auto& entry = defFstab[i]; //std::string::size_type pos = entry.blk_device.find("productinfo"); //if ((pos != std::string::npos) && (ensure_path_mounted(entry.mount_point.c_str()) == 0)) { //printf("mount productinfo success,mount point is %s \n", entry.mount_point.c_str()); for (const auto& path : reserve2_property_path) { if (android::base::ReadFileToString(path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("found forbidden recovery prop in %s! \n", path.c_str()); return true; } /* if (android::base::ReadFileToString(reserve2_property_path, &content) && (content.find("opporeserve.sys.custom.recovery.forbidden=1") != std::string::npos)) { printf("reserve found forbidden recovery prop! \n"); return true; }*/ //break; //} //} } printf("no forbidden prop found in reserve!\n"); return false; } //end of Start specific code //#endif /* VENDOR_EDIT */ int format_volume(const std::string& volume, const std::string& directory, std::string_view new_fstype) { const FstabEntry* v = android::fs_mgr::GetEntryForPath(&fstab, volume); if (v == nullptr) { LOG(ERROR) << "unknown volume \"" << volume << "\""; return -1; } if (v->fs_type == "ramdisk") { LOG(ERROR) << "can't format_volume \"" << volume << "\""; return -1; } if (v->mount_point != volume) { LOG(ERROR) << "can't give path \"" << volume << "\" to format_volume"; return -1; } if (ensure_path_unmounted(volume) != 0) { LOG(ERROR) << "format_volume: Failed to unmount \"" << v->mount_point << "\""; return -1; } if (v->fs_type != "ext4" && v->fs_type != "f2fs") { LOG(ERROR) << "format_volume: fs_type \"" << v->fs_type << "\" unsupported"; return -1; } bool needs_casefold = false; if (volume == "/data") { needs_casefold = android::base::GetBoolProperty("external_storage.casefold.enabled", false); } int64_t length = 0; if (v->length > 0) { length = v->length; } else if (v->length < 0) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDONLY)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } length = get_file_size(fd.get(), -v->length); if (length <= 0) { LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device; return -1; } } // If the raw disk will be used as a metadata encrypted device mapper target, // next boot will do encrypt_in_place the raw disk. While fs_mgr mounts /data // as RO to avoid write file operations before encrypt_inplace, this code path // is not well tested so we would like to avoid it if possible. For safety, // let vold do the formatting on boot for metadata encrypted devices, except // when user specified a new fstype. Because init formats /data according // to fstab, it's difficult to override the fstab in init. if (!v->metadata_key_dir.empty() && length == 0 && new_fstype.empty()) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; return -1; } int64_t device_size = get_file_size(fd.get(), 0); if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) { LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size " << device_size; return 0; } } if ((v->fs_type == "ext4" && new_fstype.empty()) || new_fstype == "ext4") { LOG(INFO) << "Formatting " << v->blk_device << " as ext4"; static constexpr int kBlockSize = 4096; std::vector<std::string> mke2fs_args = { "/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), }; // Following is added for Project ID's quota as they require wider inodes. // The Quotas themselves are enabled by tune2fs on boot. mke2fs_args.push_back("-I"); mke2fs_args.push_back("512"); if (v->fs_mgr_flags.ext_meta_csum) { mke2fs_args.push_back("-O"); mke2fs_args.push_back("metadata_csum"); mke2fs_args.push_back("-O"); mke2fs_args.push_back("64bit"); mke2fs_args.push_back("-O"); mke2fs_args.push_back("extent"); } int raid_stride = v->logical_blk_size / kBlockSize; int raid_stripe_width = v->erase_blk_size / kBlockSize; // stride should be the max of 8KB and logical block size if (v->logical_blk_size != 0 && v->logical_blk_size < 8192) { raid_stride = 8192 / kBlockSize; } if (v->erase_blk_size != 0 && v->logical_blk_size != 0) { mke2fs_args.push_back("-E"); mke2fs_args.push_back( android::base::StringPrintf("stride=%d,stripe-width=%d", raid_stride, raid_stripe_width)); } mke2fs_args.push_back(v->blk_device); if (length != 0) { mke2fs_args.push_back(std::to_string(length / kBlockSize)); } int result = exec_cmd(mke2fs_args); if (result == 0 && !directory.empty()) { std::vector<std::string> e2fsdroid_args = { "/system/bin/e2fsdroid", "-e", "-f", directory, "-a", volume, v->blk_device, }; result = exec_cmd(e2fsdroid_args); } if (result != 0) { PLOG(ERROR) << "format_volume: Failed to make ext4 on " << v->blk_device; return -1; } return 0; } // Has to be f2fs because we checked earlier. LOG(INFO) << "Formatting " << v->blk_device << " as f2fs"; static constexpr int kSectorSize = 4096; std::vector<std::string> make_f2fs_cmd = { "/system/bin/make_f2fs", "-g", "android", }; make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("project_quota,extra_attr"); if (needs_casefold) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("casefold"); make_f2fs_cmd.push_back("-C"); make_f2fs_cmd.push_back("utf8"); } if (v->fs_mgr_flags.fs_compress) { make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("compression"); make_f2fs_cmd.push_back("-O"); make_f2fs_cmd.push_back("extra_attr"); } make_f2fs_cmd.push_back(v->blk_device); if (length >= kSectorSize) { make_f2fs_cmd.push_back(std::to_string(length / kSectorSize)); } if (exec_cmd(make_f2fs_cmd) != 0) { PLOG(ERROR) << "format_volume: Failed to make_f2fs on " << v->blk_device; return -1; } if (!directory.empty()) { std::vector<std::string> sload_f2fs_cmd = { "/system/bin/sload_f2fs", "-f", directory, "-t", volume, v->blk_device, }; if (exec_cmd(sload_f2fs_cmd) != 0) { PLOG(ERROR) << "format_volume: Failed to sload_f2fs on " << v->blk_device; return -1; } } return 0; } int format_volume(const std::string& volume) { return format_volume(volume, "", ""); } int setup_install_mounts() { if (fstab.empty()) { LOG(ERROR) << "can't set up install mounts: no fstab loaded"; return -1; } for (const FstabEntry& entry : fstab) { // We don't want to do anything with "/". if (entry.mount_point == "/") { continue; } if (entry.mount_point == "/tmp" || entry.mount_point == "/cache") { if (ensure_path_mounted(entry.mount_point) != 0) { LOG(ERROR) << "Failed to mount " << entry.mount_point; return -1; } } else { if (ensure_path_unmounted(entry.mount_point) != 0) { LOG(ERROR) << "Failed to unmount " << entry.mount_point; return -1; } } } return 0; } bool HasCache() { CHECK(!fstab.empty()); static bool has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; return has_cache; } 总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件,例如 修改前: "1. my_product: +730.66MB 2. my_product/app: +322.14MB 3. my_product/priv-app: +277.58MB 4. my_product/del-app-pre: +193.83MB 5. my_product/priv-app/GoogleVelvet_CTS: +187.39MB" 修改后: 1. my_product/priv-app/GoogleVelvet_CTS: +187.39MB"
最新发布
08-12
<think>首先,用户的问题是:"总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件,例如 修改前:... 修改后:..." 用户描述了一个变化:在总览页的备注列,从显示“差异top”改为显示“增大大于1M的top5”,并且只显示深层路径文件。他们给出了一个例子: - 修改前:显示的是顶层目录的差异,如"my_product: +730.66MB","my_product/app: +322.14MB"等。 - 修改后:只显示深层路径,如"my_product/priv-app/GoogleVelvet_CTS: +187.39MB"。 用户说“修改后”只显示了一个条目,但标题是“增大大于1M的top5”,所以应该显示top 5的条目。 用户的问题似乎是关于如何实现这种修改,或者解释这个修改。但用户没有指定代码上下文。用户提供了代码片段,但代码是关于Android恢复系统的C++代码,涉及文件系统操作,如加载卷表、挂载、格式化等。用户的问题是关于UI或报告显示的,与代码内容不直接相关。 回顾用户消息:用户以代码开始,但最后说“总览页的备注列...”,并给出了例子。代码是Android recovery_utils/roots.cpp的代码,但用户的问题是关于“总览页的备注列”,这听起来像是一个报告或UI的列。 用户说:“总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件”,然后给出了例子。 在代码中,我没有看到任何与“总览页”或“备注列”相关的内容。代码是处理文件系统操作的。 用户可能是在错误地粘贴代码,或者代码是背景,但问题独立。 用户消息的开头是:“请使用中文回答问题”,然后是一堆代码,最后是“总览页的备注列...”。 代码中有一个函数`forbiddenRecoveryByReserveProperty`,但整体是文件系统工具。 用户的问题部分:“总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件,例如 修改前:... 修改后:...” 这似乎是关于一个报告生成器的修改:在总览页的备注列,改变显示内容。 - 之前:显示差异top(可能是文件大小变化最大的top条目),但显示的是较浅的路径。 - 之后:只显示增大超过1MB的top 5条目,并且只显示深层路径(deep paths),意思是只显示文件或深层目录,而不是顶层目录。 在例子中,修改前有"my_product: +730.66MB"(顶层目录),修改后只有"my_product/priv-app/GoogleVelvet_CTS: +187.39MB"(深层路径)。 用户可能是在描述一个需求或一个变更,但没有指定在什么上下文中。可能是在代码中实现这个,但提供的代码不相关。 用户消息结尾有:“/*This file has been modified by Unisoc (Shanghai) Technologies Co., Ltd in 2024.”,但代码是C++。 或许用户想让我基于代码回答问题,但代码中没有“总览页”或类似内容。 另一个想法:用户可能是在讨论代码中的某个部分,但代码是关于文件系统的,没有UI。 用户说“总览页”,可能是一个总结页面或报告。 在用户提供的例子中,路径如"my_product"等,看起来像是Android系统目录。 在代码中,有`Volume* volume_for_mount_point`等,但无报告生成。 或许用户想让我解释如何实现这种报告修改,但代码不相关。 用户消息以代码开始,但最后一部分是独立的。 我应该专注于用户的问题部分。 用户的问题:解释或实现“总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件”。 既然用户要求用中文回答,并基于规则,我需要回答问题,然后提出3-5个相关问题。 首先,回答问题。 问题:用户描述了从显示差异top到显示增大>1MB的top5深层路径文件的变更。 我需要解释这个变更或如何实现它。 由于没有具体上下文,我应给出一般性解释。 例如: 这个变更意味着在总览页的备注列,不再显示所有差异最大的top条目,而是只关注那些大小增加超过1MB的条目,并且只显示深层路径(即文件或深层子目录),而不是顶层目录。这样可以使报告更精确地显示实际占用空间的主要文件。 在实现上,可能需要修改报告生成逻辑: 1. 过滤条目:只包括大小增加 > 1MB 的条目。 2. 路径深度:只显示路径深度较大的条目,例如路径中包含多个“/”的,表示深层文件或目录。 3. 取top 5:基于增加的大小排序,取前5个。 在例子中,修改前显示目录如"my_product",修改后显示具体文件如"my_product/priv-app/GoogleVelvet_CTS"。 在修改后例子中,只显示了一个条目,但用户说“top5”,所以可能例子不完整。 现在,关于代码:用户提供了C++代码,但代码是Android恢复系统的,涉及文件系统操作,如`load_volume_table`, `format_volume`等。没有报告生成部分。 在代码末尾,用户添加了文本:“总览页的备注列从差异top改成增大大于1M的top5,并且只显示深层路径文件,例如 修改前:... 修改后:...” 这似乎是用户附加的描述,不是代码的一部分。 所以,我应该忽略代码,直接回答问题。 但用户说“请在回答完问题后,必须根据用户的问题及你的回答提出3-5个 §§相关问题§§”。 用户的问题是描述性的,所以我需要回应。 可能的回答: 用户的问题是关于在某个报告中修改显示逻辑。具体来说,备注列现在显示大小增加超过1MB的top 5条目,并且只显示深层路径文件,以提供更精确的信息。 如何实现:在生成报告时,收集文件大小变化数据,过滤增加>1MB的条目,计算路径深度(例如,基于“/”分隔符的数量),只保留深度较大的条目,然后排序取top 5。 在Android上下文中,可能涉及分析系统分区或应用文件。 但既然代码不相关,我应一般性回答。 然后,提出相关问题。 现在,输出格式:回答后,必须输出“§§相关问题§§”在第一行,然后是3-5个问题。 问题用数字列表。 例如: §§相关问题§§ 1. ··· 2. ··· 3. ··· 禁止换行分散。 所以,结构化我的响应。</think>用户的问题描述了一个报告生成逻辑的变更:在总览页的备注列,从原先显示文件大小差异最大的 top 条目(可能包括顶层目录),改为只显示大小增加超过 1MB 的 top 5 条目,并且仅展示深层路径文件(即路径中包含多个子目录层级的文件或深层目录,而不是顶层目录)。例如: - 修改前:显示较浅路径(如顶层目录)的差异,例如 "my_product: +730.66MB"。 - 修改后:只显示深层路径(如具体文件或深层子目录)的条目,例如 "my_product/priv-app/GoogleVelvet_CTS: +187.39MB",且只包括增大超过 1MB 的 top 5。 这个变更的目的是使报告更精确地聚焦于实际占用空间的主要文件或深层目录,避免顶层目录的汇总数据干扰,从而帮助识别具体的大文件增长点。实现这种修改通常涉及以下步骤(以代码或脚本实现为例): 1. **数据收集**:获取文件系统或目录的变更数据(如大小增加量)。 2. **过滤条件**: - 只保留大小增加超过 1MB(即 > 1048576 字节)的条目。 - 只保留深层路径文件:定义路径深度(例如,路径中 "/" 分隔符的数量 ≥ 3,如 "my_product/priv-app/GoogleVelvet_CTS" 有 3 个层级)。 3. **排序和截取**:按增加量降序排序,取前 5 个条目。 4. **输出格式化**:生成报告时,只显示这些深层路径条目。 在您提供的代码上下文中(Android 恢复系统的 `roots.cpp`),虽然代码主要处理文件系统挂载和格式化,没有直接涉及报告生成,但您可以扩展相关功能(如在文件操作后添加报告逻辑)。例如,在 `format_volume` 或文件扫描后,调用一个自定义函数来生成这个报告。伪代码实现如下(需集成到合适位置): ```python def generate_report(file_changes): # 过滤:增大 > 1MB 且深层路径(路径深度 >= 3) filtered = [] for path, size_change in file_changes.items(): if size_change > 1048576: # 1MB in bytes depth = path.count('/') # 计算路径深度 if depth >= 3: # 定义深层路径,例如至少3级目录 filtered.append((path, size_change)) # 排序:按增加量降序,取top 5 filtered.sort(key=lambda x: x[1], reverse=True) top5 = filtered[:5] # 格式化输出为备注列内容 report_lines = [] for i, (path, size) in enumerate(top5): size_mb = size / (1024 * 1024) # 转换为MB report_lines.append(f"{i+1}. {path}: +{size_mb:.2f}MB") return report_lines # 示例调用(假设 file_changes 是从文件系统扫描获得的字典) # file_changes = {"/my_product": 730.66*1024*1024, "/my_product/priv-app/GoogleVelvet_CTS": 187.39*1024*1024, ...} # report = generate_report(file_changes) # 输出到总览页备注列 ``` 注意:实际集成需根据具体环境(如 Android 恢复模式)调整数据来源(例如从 `Fstab` 扫描文件变化)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值