Do not use regex to parse /proc/config.gz.

During boot, a compatibility check is performed and
/proc/config.gz is parsed. /proc/config.gz has
a well defined format:

    # CONFIG_FOO is not set
    CONFIG_BAR=y

with no trailing / leading spaces, spaces around
'=', or trailing comments. Using regex is slow
and unnecessary, hence a normal string search
is performed instead.

On the other hand, for assemble_vintf that needs to parse
android-base.cfg, because the file is maintained by
humans, free format is accepted, and regex is used.

Test: boots (boot time compat check passes)
Test: boot time regression no longer happens (~120ms vs. ~90ms)
Test: libvintf_test
Bug: 63537988
Change-Id: If6ab207d40459689386aaf40cd835effc5597886
diff --git a/KernelConfigParser.cpp b/KernelConfigParser.cpp
index 44cbf07..a0955e2 100644
--- a/KernelConfigParser.cpp
+++ b/KernelConfigParser.cpp
@@ -28,7 +28,8 @@
 namespace android {
 namespace vintf {
 
-KernelConfigParser::KernelConfigParser(bool processComments) : mProcessComments(processComments) {}
+KernelConfigParser::KernelConfigParser(bool processComments, bool relaxedFormat)
+    : mProcessComments(processComments), mRelaxedFormat(relaxedFormat) {}
 
 status_t KernelConfigParser::finish() {
     return process("\n", 1 /* sizeof "\n" */);
@@ -61,12 +62,28 @@
     }
 
     std::smatch match;
-    if (std::regex_match(mRemaining, match, sKeyValuePattern)) {
-        if (mConfigs.emplace(match[1], trimTrailingSpaces(match[2])).second) {
-            return OK;
+
+    if (mRelaxedFormat) {
+        // Allow free format like "   CONFIG_FOO  = bar    #trailing comments"
+        if (std::regex_match(mRemaining, match, sKeyValuePattern)) {
+            if (mConfigs.emplace(match[1], trimTrailingSpaces(match[2])).second) {
+                return OK;
+            }
+            mError << "Duplicated key in configs: " << match[1] << "\n";
+            return UNKNOWN_ERROR;
         }
-        mError << "Duplicated key in configs: " << match[1] << "\n";
-        return UNKNOWN_ERROR;
+    } else {
+        // No spaces. Strictly like "CONFIG_FOO=bar"
+        size_t equalPos = mRemaining.find('=');
+        if (equalPos != std::string::npos) {
+            std::string key = mRemaining.substr(0, equalPos);
+            std::string value = mRemaining.substr(equalPos + 1);
+            if (mConfigs.emplace(std::move(key), std::move(value)).second) {
+                return OK;
+            }
+            mError << "Duplicated key in configs: " << mRemaining.substr(0, equalPos) << "\n";
+            return UNKNOWN_ERROR;
+        }
     }
 
     if (mProcessComments && std::regex_match(mRemaining, match, sNotSetPattern)) {
@@ -78,8 +95,16 @@
         return UNKNOWN_ERROR;
     }
 
-    if (std::regex_match(mRemaining, match, sCommentPattern)) {
-        return OK;
+    if (mRelaxedFormat) {
+        // Allow free format like "   #comments here"
+        if (std::regex_match(mRemaining, match, sCommentPattern)) {
+            return OK;
+        }
+    } else {
+        // No leading spaces before the comment
+        if (mRemaining.at(0) == '#') {
+            return OK;
+        }
     }
 
     mError << "Unrecognized line in configs: " << mRemaining << "\n";