Eagerly read the full file contents during include scanning

This is slightly more efficient than the current hand-rolled implementation, especially
the line-by-line reading of pre-grepped files.

RELNOTES: None.
PiperOrigin-RevId: 293979591
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java
index 1e674b6..11d999d 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java
@@ -59,6 +59,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -685,41 +686,65 @@
       'a', Kind.NEXT_ANGLE);
 
   /**
-   * Processes the output generated by an auxiliary include-scanning binary. Closes the stream upon
-   * completion.
+   * Processes the output generated by an auxiliary include-scanning binary.
    *
    * <p>If a source file has the following include statements:
+   *
    * <pre>
    *   #include &lt;string&gt;
    *   #include "directory/header.h"
    * </pre>
    *
    * <p>Then the output file has the following contents:
+   *
    * <pre>
    *   "directory/header.h
    *   &lt;string
    * </pre>
+   *
    * <p>Each line of the output is translated into an Inclusion object.
    */
-  public static List<Inclusion> processIncludes(Object streamName, InputStream is)
-      throws IOException {
+  private static List<Inclusion> processIncludes(List<String> lines) throws IOException {
     List<Inclusion> inclusions = new ArrayList<>();
-    try (InputStreamReader reader = new InputStreamReader(is, ISO_8859_1)) {
-      for (String line : CharStreams.readLines(reader)) {
-        char qchar = line.charAt(0);
-        String name = line.substring(1);
-        Kind kind = KIND_MAP.get(qchar);
-        if (kind == null) {
-          throw new IOException("Illegal inclusion kind '" + qchar + "'");
-        }
-        inclusions.add(new Inclusion(name, kind));
+    for (String line : lines) {
+      if (line.isEmpty()) {
+        continue;
       }
-    } catch (IOException e) {
-      throw new IOException("Error reading include file " + streamName + ": " + e.getMessage());
+      char qchar = line.charAt(0);
+      String name = line.substring(1);
+      Kind kind = KIND_MAP.get(qchar);
+      if (kind == null) {
+        throw new IOException("Illegal inclusion kind '" + qchar + "'");
+      }
+      inclusions.add(new Inclusion(name, kind));
     }
     return inclusions;
   }
 
+  /** Processes the output generated by an auxiliary include-scanning binary stored in a file. */
+  public static List<Inclusion> processIncludes(Path file) throws IOException {
+    try {
+      byte[] data = FileSystemUtils.readContent(file);
+      return IncludeParser.processIncludes(Arrays.asList(new String(data, ISO_8859_1).split("\n")));
+    } catch (IOException e) {
+      throw new IOException("Error reading include file " + file + ": " + e.getMessage());
+    }
+  }
+
+  /**
+   * Processes the output generated by an auxiliary include-scanning binary read from a stream.
+   * Closes the stream upon completion.
+   */
+  public static List<Inclusion> processIncludes(Object streamName, InputStream is)
+      throws IOException {
+    try (InputStreamReader reader = new InputStreamReader(is, ISO_8859_1)) {
+      return processIncludes(CharStreams.readLines(reader));
+    } catch (IOException e) {
+      throw new IOException("Error reading include file " + streamName + ": " + e.getMessage());
+    }
+  }
+
+
   @VisibleForTesting
   Inclusion extractInclusion(String line) {
     return extractInclusion(line.getBytes(ISO_8859_1), 0, line.length());
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java b/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
index 6252111..c666498 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
@@ -312,8 +312,9 @@
             actionExecutionContext,
             grepIncludes,
             fileType);
-    return IncludeParser.processIncludes(
-        output, dotIncludeStream == null ? output.getInputStream() : dotIncludeStream);
+    return dotIncludeStream == null
+        ? IncludeParser.processIncludes(output)
+        : IncludeParser.processIncludes(output, dotIncludeStream);
   }
 
   /**