From 35c5bcc89ce713aca02852dc10247a648187ea28 Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Mon, 24 Apr 2017 16:55:30 -0700 Subject: [PATCH] init: add Parser::AddSingleLineParser() Add the ability to override the current section being parsed and instead parse a line by itself if a given line starts with a specific prefix. Test: Boot bullhead Change-Id: Idbbf2682b78996b41d05f3db655c8937a8c6ccda --- init/init_parser.cpp | 19 +++++++++++++++++++ init/init_parser.h | 27 +++++++++++++++------------ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/init/init_parser.cpp b/init/init_parser.cpp index 5c7af79ee..c8ef8d9e6 100644 --- a/init/init_parser.cpp +++ b/init/init_parser.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "parser.h" #include "util.h" @@ -37,6 +38,10 @@ void Parser::AddSectionParser(const std::string& name, section_parsers_[name] = std::move(parser); } +void Parser::AddSingleLineParser(const std::string& prefix, LineCallback callback) { + line_callbacks_.emplace_back(prefix, callback); +} + void Parser::ParseData(const std::string& filename, const std::string& data) { //TODO: Use a parser with const input and remove this copy std::vector data_copy(data.begin(), data.end()); @@ -63,6 +68,20 @@ void Parser::ParseData(const std::string& filename, const std::string& data) { if (args.empty()) { break; } + // If we have a line matching a prefix we recognize, call its callback and unset any + // current section parsers. This is meant for /sys/ and /dev/ line entries for uevent. + for (const auto& [prefix, callback] : line_callbacks_) { + if (android::base::StartsWith(args[0], prefix.c_str())) { + if (section_parser) section_parser->EndSection(); + + std::string ret_err; + if (!callback(std::move(args), &ret_err)) { + parse_error(&state, "%s\n", ret_err.c_str()); + } + section_parser = nullptr; + break; + } + } if (section_parsers_.count(args[0])) { if (section_parser) { section_parser->EndSection(); diff --git a/init/init_parser.h b/init/init_parser.h index fe70d7d50..bd8a17805 100644 --- a/init/init_parser.h +++ b/init/init_parser.h @@ -57,24 +57,26 @@ class SectionParser { class Parser { public: + // LineCallback is the type for callbacks that can parse a line starting with a given prefix. + // + // They take the form of bool Callback(std::vector&& args, std::string* err) + // + // Similar to ParseSection() and ParseLineSection(), this function returns bool with false + // indicating a failure and has an std::string* err parameter into which an error string can + // be written. + using LineCallback = std::function&&, std::string*)>; + static Parser& GetInstance(); // Exposed for testing Parser(); bool ParseConfig(const std::string& path); - void AddSectionParser(const std::string& name, - std::unique_ptr parser); - - void set_is_system_etc_init_loaded(bool loaded) { - is_system_etc_init_loaded_ = loaded; - } - void set_is_vendor_etc_init_loaded(bool loaded) { - is_vendor_etc_init_loaded_ = loaded; - } - void set_is_odm_etc_init_loaded(bool loaded) { - is_odm_etc_init_loaded_ = loaded; - } + void AddSectionParser(const std::string& name, std::unique_ptr parser); + void AddSingleLineParser(const std::string& prefix, LineCallback callback); + void set_is_system_etc_init_loaded(bool loaded) { is_system_etc_init_loaded_ = loaded; } + void set_is_vendor_etc_init_loaded(bool loaded) { is_vendor_etc_init_loaded_ = loaded; } + void set_is_odm_etc_init_loaded(bool loaded) { is_odm_etc_init_loaded_ = loaded; } bool is_system_etc_init_loaded() { return is_system_etc_init_loaded_; } bool is_vendor_etc_init_loaded() { return is_vendor_etc_init_loaded_; } bool is_odm_etc_init_loaded() { return is_odm_etc_init_loaded_; } @@ -85,6 +87,7 @@ class Parser { bool ParseConfigDir(const std::string& path); std::map> section_parsers_; + std::vector> line_callbacks_; bool is_system_etc_init_loaded_ = false; bool is_vendor_etc_init_loaded_ = false; bool is_odm_etc_init_loaded_ = false;