summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--KernelConfigParser.cpp54
-rw-r--r--test/main.cpp60
2 files changed, 91 insertions, 23 deletions
diff --git a/KernelConfigParser.cpp b/KernelConfigParser.cpp
index 1d08fca..44cbf07 100644
--- a/KernelConfigParser.cpp
+++ b/KernelConfigParser.cpp
@@ -18,6 +18,13 @@
18 18
19#include <regex> 19#include <regex>
20 20
21#define KEY "(CONFIG[\\w_]+)"
22#define COMMENT "(?:#.*)"
23
24static const std::regex sKeyValuePattern("^\\s*" KEY "\\s*=\\s*([^#]+)" COMMENT "?$");
25static const std::regex sNotSetPattern("^\\s*#\\s*" KEY " is not set\\s*$");
26static const std::regex sCommentPattern("^\\s*" COMMENT "$");
27
21namespace android { 28namespace android {
22namespace vintf { 29namespace vintf {
23 30
@@ -39,43 +46,44 @@ const std::map<std::string, std::string>& KernelConfigParser::configs() const {
39 return mConfigs; 46 return mConfigs;
40} 47}
41 48
49// trim spaces between value and #, value and end of line
50std::string trimTrailingSpaces(const std::string& s) {
51 auto r = s.rbegin();
52 for (; r != s.rend() && std::isspace(*r); ++r)
53 ;
54 return std::string{s.begin(), r.base()};
55}
56
42status_t KernelConfigParser::processRemaining() { 57status_t KernelConfigParser::processRemaining() {
43 static std::regex sCommentPattern("^# (CONFIG[\\w_]+) is not set$");
44 58
45 if (mRemaining.empty()) { 59 if (mRemaining.empty()) {
46 return OK; 60 return OK;
47 } 61 }
48 62
49 if (mRemaining[0] == '#') { 63 std::smatch match;
50 if (!mProcessComments) { 64 if (std::regex_match(mRemaining, match, sKeyValuePattern)) {
65 if (mConfigs.emplace(match[1], trimTrailingSpaces(match[2])).second) {
51 return OK; 66 return OK;
52 } 67 }
53 std::smatch sm; 68 mError << "Duplicated key in configs: " << match[1] << "\n";
54 if (!std::regex_match(mRemaining, sm, sCommentPattern)) { 69 return UNKNOWN_ERROR;
55 return OK; // ignore this comment;
56 }
57 if (!mConfigs.emplace(sm[1], "n").second) {
58 mError << "Key " << sm[1] << " is set but commented as not set"
59 << "\n";
60 return UNKNOWN_ERROR;
61 }
62
63 return OK;
64 } 70 }
65 71
66 size_t equalPos = mRemaining.find('='); 72 if (mProcessComments && std::regex_match(mRemaining, match, sNotSetPattern)) {
67 if (equalPos == std::string::npos) { 73 if (mConfigs.emplace(match[1], "n").second) {
68 mError << "Unrecognized line in configs: " << mRemaining << "\n"; 74 return OK;
75 }
76 mError << "Key " << match[1] << " is set but commented as not set"
77 << "\n";
69 return UNKNOWN_ERROR; 78 return UNKNOWN_ERROR;
70 } 79 }
71 std::string key = mRemaining.substr(0, equalPos); 80
72 std::string value = mRemaining.substr(equalPos + 1); 81 if (std::regex_match(mRemaining, match, sCommentPattern)) {
73 if (!mConfigs.emplace(std::move(key), std::move(value)).second) { 82 return OK;
74 mError << "Duplicated key in configs: " << mRemaining.substr(0, equalPos) << "\n";
75 return UNKNOWN_ERROR;
76 } 83 }
77 84
78 return OK; 85 mError << "Unrecognized line in configs: " << mRemaining << "\n";
86 return UNKNOWN_ERROR;
79} 87}
80 88
81status_t KernelConfigParser::process(const char* buf, size_t len) { 89status_t KernelConfigParser::process(const char* buf, size_t len) {
diff --git a/test/main.cpp b/test/main.cpp
index 179407f..b3b8a59 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -1362,6 +1362,66 @@ TEST_F(LibVintfTest, KernelConfigParser2) {
1362 EXPECT_EQ(configs.find("CONFIG_NOT_SET2")->second, "n"); 1362 EXPECT_EQ(configs.find("CONFIG_NOT_SET2")->second, "n");
1363} 1363}
1364 1364
1365TEST_F(LibVintfTest, KernelConfigParserSpace) {
1366 // usage in android-base.cfg
1367 const std::string data =
1368 " # CONFIG_NOT_SET is not set \n"
1369 " CONFIG_ONE=1 # 'tis a one!\n"
1370 " CONFIG_TWO=2 #'tis a two! \n"
1371 " CONFIG_THREE=3#'tis a three! \n"
1372 " CONFIG_233=233#'tis a three! \n"
1373 "#yey! random comments\n"
1374 "CONFIG_Y=y \n"
1375 " CONFIG_YES=y#YES! \n"
1376 "CONFIG_STR=string\n"
1377 "CONFIG_HELLO=hello world! #still works\n"
1378 "CONFIG_WORLD=hello world! \n"
1379 "CONFIG_GOOD = good morning! #comments here\n"
1380 " CONFIG_MORNING = good morning! \n";
1381 auto pair = processData(data, true /* processComments */);
1382 ASSERT_EQ(OK, pair.second) << pair.first.error();
1383 const auto& configs = pair.first.configs();
1384
1385 EXPECT_EQ(configs.find("CONFIG_ONE")->second, "1");
1386 EXPECT_EQ(configs.find("CONFIG_TWO")->second, "2");
1387 EXPECT_EQ(configs.find("CONFIG_THREE")->second, "3");
1388 EXPECT_EQ(configs.find("CONFIG_Y")->second, "y");
1389 EXPECT_EQ(configs.find("CONFIG_STR")->second, "string");
1390 EXPECT_EQ(configs.find("CONFIG_HELLO")->second, "hello world!")
1391 << "Value should be \"hello world!\" without trailing spaces";
1392 EXPECT_EQ(configs.find("CONFIG_WORLD")->second, "hello world!")
1393 << "Value should be \"hello world!\" without trailing spaces";
1394 EXPECT_EQ(configs.find("CONFIG_GOOD")->second, "good morning!")
1395 << "Value should be \"good morning!\" without leading or trailing spaces";
1396 EXPECT_EQ(configs.find("CONFIG_MORNING")->second, "good morning!")
1397 << "Value should be \"good morning!\" without leading or trailing spaces";
1398 EXPECT_EQ(configs.find("CONFIG_NOT_SET")->second, "n");
1399}
1400
1401// Run KernelConfigParserInvalidTest on processComments = {true, false}
1402class KernelConfigParserInvalidTest : public ::testing::TestWithParam<bool> {};
1403
1404TEST_P(KernelConfigParserInvalidTest, NonSet1) {
1405 const std::string data = "# CONFIG_NOT_EXIST is not sat\n";
1406 auto pair = processData(data, GetParam() /* processComments */);
1407 ASSERT_EQ(OK, pair.second) << pair.first.error();
1408 const auto& configs = pair.first.configs();
1409 EXPECT_EQ(configs.find("CONFIG_NOT_EXIST"), configs.end())
1410 << "CONFIG_NOT_EXIST should not exist because of typo";
1411}
1412
1413TEST_P(KernelConfigParserInvalidTest, InvalidLine1) {
1414 const std::string data = "FOO_CONFIG=foo\n";
1415 ASSERT_NE(OK, processData(data, GetParam() /* processComments */).second);
1416}
1417
1418TEST_P(KernelConfigParserInvalidTest, InvalidLine2) {
1419 const std::string data = "CONFIG_BAR-BAZ=foo\n";
1420 ASSERT_NE(OK, processData(data, GetParam() /* processComments */).second);
1421}
1422
1423INSTANTIATE_TEST_CASE_P(KernelConfigParser, KernelConfigParserInvalidTest, ::testing::Bool());
1424
1365} // namespace vintf 1425} // namespace vintf
1366} // namespace android 1426} // namespace android
1367 1427