android_log_formatLogLine(): don't use strcat().

We're already manually maintaining the insertion point, and we already
know the length of everything we copy in this code, so it can all just
use memcpy() instead. (I've actually gone for mempcpy() because that
lets us maintain the insertion point on the same line by returning a
pointer to the end rather than a pointer to the start.)

Tested on the host, the benchmark goes from 540ns to 520ns. (But the
motivation is actually for the device, where the arm64 strcat() is
currently a very naive implementation, and logcat is the only caller
that's showing up in the fleet-wide sampling.)

Change-Id: I9097aaa3941a0cffe298743ecca514d201f78e04
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index 7bdcd9c..40e2ed4 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -1602,16 +1602,9 @@
 
   /* the following code is tragically unreadable */
 
-  size_t numLines;
-  char* p;
-  size_t bufferSize;
-  const char* pm;
-
-  if (prefixSuffixIsHeaderFooter) {
-    /* we're just wrapping message with a header/footer */
-    numLines = 1;
-  } else {
-    pm = entry->message;
+  size_t numLines = 1;
+  if (!prefixSuffixIsHeaderFooter) {
+    const char* pm = entry->message;
     numLines = 0;
 
     /*
@@ -1629,7 +1622,7 @@
    * this is an upper bound--newlines in message may be counted
    * extraneously
    */
-  bufferSize = (numLines * (prefixLen + suffixLen)) + 1;
+  size_t bufferSize = (numLines * (prefixLen + suffixLen)) + 1;
   if (p_format->printable_output) {
     /* Calculate extra length to convert non-printable to printable */
     bufferSize += convertPrintable(NULL, entry->message, entry->messageLen);
@@ -1647,45 +1640,32 @@
     }
   }
 
-  ret[0] = '\0'; /* to start strcat off */
+  char* p = ret;
 
-  p = ret;
-  pm = entry->message;
+  auto emit_one_line = [&](const char* line, size_t line_length) {
+    p = (char*) mempcpy(p, prefixBuf, prefixLen);
+    if (p_format->printable_output) {
+      p += convertPrintable(p, line, line_length);
+    } else {
+      p = (char*) mempcpy(p, line, line_length);
+    }
+    p = (char*) mempcpy(p, suffixBuf, suffixLen);
+  };
 
   if (prefixSuffixIsHeaderFooter) {
-    strcat(p, prefixBuf);
-    p += prefixLen;
-    if (p_format->printable_output) {
-      p += convertPrintable(p, entry->message, entry->messageLen);
-    } else {
-      strncat(p, entry->message, entry->messageLen);
-      p += entry->messageLen;
-    }
-    strcat(p, suffixBuf);
-    p += suffixLen;
+    emit_one_line(entry->message, entry->messageLen);
   } else {
+    const char* pm = entry->message;
+    const char* message_end = entry->message + entry->messageLen;
     do {
-      const char* lineStart;
-      size_t lineLen;
-      lineStart = pm;
+      // Find the next end-of-line in message.
+      const char* lineStart = pm;
+      while (pm < message_end && *pm != '\n') pm++;
 
-      /* Find the next end-of-line in message */
-      while (pm < (entry->message + entry->messageLen) && *pm != '\n') pm++;
-      lineLen = pm - lineStart;
-
-      strcat(p, prefixBuf);
-      p += prefixLen;
-      if (p_format->printable_output) {
-        p += convertPrintable(p, lineStart, lineLen);
-      } else {
-        strncat(p, lineStart, lineLen);
-        p += lineLen;
-      }
-      strcat(p, suffixBuf);
-      p += suffixLen;
+      emit_one_line(lineStart, pm - lineStart);
 
       if (*pm == '\n') pm++;
-    } while (pm < (entry->message + entry->messageLen));
+    } while (pm < message_end);
   }
 
   if (p_outLength != NULL) {