Bug 1754423 - Same code for counting and storing. r=benc a=wsmwk
authorKai Engert <kaie@kuix.de>
Wed, 09 Feb 2022 19:41:52 +0200
changeset 45633 fd92eb889d7f8fadebc04f132fc5574ed2c5c74a
parent 45632 4b4b5c95d5a3859e4c1751792129a7e3b46b15d7
child 45634 e29e702ed88f5cf4763758d12726f4714150ddb4
push id3522
push userthunderbird@calypsoblue.org
push dateMon, 28 Feb 2022 14:56:52 +0000
treeherdercomm-beta@df392b04bba7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbenc, wsmwk
bugs1754423
Bug 1754423 - Same code for counting and storing. r=benc a=wsmwk Differential Revision: https://phabricator.services.mozilla.com/D137658
mailnews/mime/src/mimehdrs.cpp
mailnews/mime/src/modlmime.h
--- a/mailnews/mime/src/mimehdrs.cpp
+++ b/mailnews/mime/src/mimehdrs.cpp
@@ -158,75 +158,28 @@ MimeHeaders* MimeHeaders_copy(MimeHeader
     for (i = 0; i < hdrs->heads_size; i++) {
       hdrs2->heads[i] =
           (hdrs2->all_headers + (hdrs->heads[i] - hdrs->all_headers));
     }
   }
   return hdrs2;
 }
 
-int MimeHeaders_build_heads_list(MimeHeaders* hdrs) {
-  char* s;
-  char* end;
-  int i;
-  NS_ASSERTION(hdrs, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
-  if (!hdrs) return -1;
-
-  NS_ASSERTION(hdrs->done_p && !hdrs->heads,
-               "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
-  if (!hdrs->done_p || hdrs->heads) return -1;
-
-  if (hdrs->all_headers_fp == 0) {
-    /* Must not have been any headers (we got the blank line right away.) */
-    PR_FREEIF(hdrs->all_headers);
-    hdrs->all_headers_size = 0;
-    return 0;
-  }
+static bool find_header_starts(MimeHeaders* hdrs, bool counting) {
+  const char* end = hdrs->all_headers + hdrs->all_headers_fp;
+  char* s = hdrs->all_headers;
+  int i = 0;
 
-  /* At this point, we might as well realloc all_headers back down to the
-   minimum size it must be (it could be up to 1k bigger.)  But don't
-   bother if we're only off by a tiny bit. */
-  NS_ASSERTION(hdrs->all_headers_fp <= hdrs->all_headers_size,
-               "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
-  if (hdrs->all_headers_fp + 60 <= hdrs->all_headers_size) {
-    char* ls = (char*)PR_Realloc(hdrs->all_headers, hdrs->all_headers_fp);
-    if (ls) /* can this ever fail?  we're making it smaller... */
-    {
-      hdrs->all_headers = ls; /* in case it got relocated */
-      hdrs->all_headers_size = hdrs->all_headers_fp;
-    }
+  if (counting) {
+    // For the start pointer
+    hdrs->heads_size = 1;
+  } else {
+    hdrs->heads[i++] = hdrs->all_headers;
   }
 
-  /* First go through and count up the number of headers in the block.
-   */
-  end = hdrs->all_headers + hdrs->all_headers_fp;
-  for (s = hdrs->all_headers; s < end; s++) {
-    if (s < (end - 1) && s[0] == '\r' && s[1] == '\n') /* CRLF -> LF */
-      s++;
-
-    if ((s[0] == '\r' || s[0] == '\n') && /* we're at a newline, and */
-        (s >= (end - 1) ||                /* we're at EOF, or */
-         !(s[1] == ' ' || s[1] == '\t'))) /* next char is nonwhite */
-      hdrs->heads_size++;
-  }
-
-  /* Now allocate storage for the pointers to each of those headers.
-   */
-  hdrs->heads = (char**)PR_MALLOC((hdrs->heads_size + 1) * sizeof(char*));
-  if (!hdrs->heads) return MIME_OUT_OF_MEMORY;
-  memset(hdrs->heads, 0, (hdrs->heads_size + 1) * sizeof(char*));
-
-  /* Now make another pass through the headers, and this time, record the
-   starting position of each header.
-   */
-
-  i = 0;
-  hdrs->heads[i++] = hdrs->all_headers;
-  s = hdrs->all_headers;
-
   while (s < end) {
   SEARCH_NEWLINE:
     while (s < end && *s != '\r' && *s != '\n') s++;
 
     if (s >= end) break;
 
     /* If "\r\n " or "\r\n\t" is next, that doesn't terminate the header. */
     else if (s + 2 < end && (s[0] == '\r' && s[1] == '\n') &&
@@ -247,22 +200,75 @@ int MimeHeaders_build_heads_list(MimeHea
      */
     if (*s == '\r') s++;
 
     if (s >= end) break;
 
     if (*s == '\n') s++;
 
     if (s < end) {
-      NS_ASSERTION(!(i > hdrs->heads_size),
-                   "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
-      if (i > hdrs->heads_size) return -1;
-      hdrs->heads[i++] = s;
+      if (counting) {
+        hdrs->heads_size++;
+      } else {
+        NS_ASSERTION(i < hdrs->heads_size,
+                     "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
+        if (i >= hdrs->heads_size) return false;
+        hdrs->heads[i++] = s;
+      }
     }
   }
+  if (!counting) {
+    NS_ASSERTION(i == hdrs->heads_size, "unexpected");
+  }
+  return true;
+}
+
+int MimeHeaders_build_heads_list(MimeHeaders* hdrs) {
+  NS_ASSERTION(hdrs, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
+  if (!hdrs) return -1;
+
+  NS_ASSERTION(hdrs->done_p && !hdrs->heads,
+               "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
+  if (!hdrs->done_p || hdrs->heads) return -1;
+
+  if (hdrs->all_headers_fp == 0) {
+    /* Must not have been any headers (we got the blank line right away.) */
+    PR_FREEIF(hdrs->all_headers);
+    hdrs->all_headers_size = 0;
+    return 0;
+  }
+
+  /* At this point, we might as well realloc all_headers back down to the
+   minimum size it must be (it could be up to 1k bigger.)  But don't
+   bother if we're only off by a tiny bit. */
+  NS_ASSERTION(hdrs->all_headers_fp <= hdrs->all_headers_size,
+               "1.1 <rhp@netscape.com> 19 Mar 1999 12:00");
+  if (hdrs->all_headers_fp + 60 <= hdrs->all_headers_size) {
+    char* ls = (char*)PR_Realloc(hdrs->all_headers, hdrs->all_headers_fp);
+    if (ls) /* can this ever fail?  we're making it smaller... */
+    {
+      hdrs->all_headers = ls; /* in case it got relocated */
+      hdrs->all_headers_size = hdrs->all_headers_fp;
+    }
+  }
+
+  find_header_starts(hdrs, true);
+
+  /* Now allocate storage for the pointers to each of those headers.
+   */
+  hdrs->heads = (char**)PR_MALLOC((hdrs->heads_size) * sizeof(char*));
+  if (!hdrs->heads) return MIME_OUT_OF_MEMORY;
+  memset(hdrs->heads, 0, (hdrs->heads_size) * sizeof(char*));
+
+  /* Now make another pass through the headers, and this time, record the
+   starting position of each header.
+   */
+  if (!find_header_starts(hdrs, false)) {
+    return -1;
+  }
 
   return 0;
 }
 
 char* MimeHeaders_get(MimeHeaders* hdrs, const char* header_name, bool strip_p,
                       bool all_p) {
   int i;
   int name_length;
--- a/mailnews/mime/src/modlmime.h
+++ b/mailnews/mime/src/modlmime.h
@@ -28,24 +28,25 @@
 typedef struct MimeHeaders {
   char* all_headers;        /* A char* of the entire header section. */
   int32_t all_headers_fp;   /* The length (it is not NULL-terminated.) */
   int32_t all_headers_size; /* The size of the allocated block. */
 
   bool done_p; /* Whether we've read the end-of-headers marker
                  (the terminating blank line.) */
 
-  char** heads;       /* An array of length n_headers which points
+  char** heads;       /* An array of length heads_size which points
                         to the beginning of each distinct header:
                         just after the newline which terminated
                         the previous one.  This is to speed search.
                         This is not initialized until all the
                         headers have been read.
                       */
-  int32_t heads_size; /* The length (and consequently, how many
+  int32_t heads_size; /* The number of entries (pointers) in the heads
+                         array (and consequently, how many
                          distinct headers are in here.) */
 
   char* obuffer; /* This buffer is used for output. */
   int32_t obuffer_size;
   int32_t obuffer_fp;
 
   char* munged_subject; /* What a hack.  This is a place to write down
                            the subject header, after it's been