[set] Optimize add_array() / add_sorted_array()

Does page lookup as needed.
diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 4b6f7fb..74a22a0 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -225,8 +225,7 @@
   {
     if (unlikely (in_error)) return;
     if (unlikely (g == INVALID)) return;
-    page_t *page = page_for_insert (g);
-    if (unlikely (!page)) return;
+    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
     page->add (g);
   }
   inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
@@ -236,25 +235,21 @@
     unsigned int mb = get_major (b);
     if (ma == mb)
     {
-      page_t *page = page_for_insert (a);
-      if (unlikely (!page)) return false;
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
       page->add_range (a, b);
     }
     else
     {
-      page_t *page = page_for_insert (a);
-      if (unlikely (!page)) return false;
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
       page->add_range (a, major_start (ma + 1) - 1);
 
       for (unsigned int m = ma + 1; m < mb; m++)
       {
-	page = page_for_insert (major_start (m));
-	if (unlikely (!page)) return false;
+	page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
 	page->init1 ();
       }
 
-      page = page_for_insert (b);
-      if (unlikely (!page)) return false;
+      page = page_for_insert (b); if (unlikely (!page)) return false;
       page->add_range (major_start (mb), b);
     }
     return true;
@@ -263,21 +258,48 @@
   template <typename T>
   inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
-    for (unsigned int i = 0; i < count; i++)
+    if (unlikely (in_error)) return;
+    if (!count) return;
+    hb_codepoint_t g = *array;
+    while (count)
     {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+      unsigned int start = major_start (m);
+      unsigned int end = major_start (m + 1);
+      do
+      {
+	page->add (g);
+
+	array++;
+	count--;
+      }
+      while (count && (g = *array, start <= g && g < end));
     }
   }
+
   /* Might return false if array looks unsorted.
    * Used for faster rejection of corrupt data. */
   template <typename T>
   inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
   {
-    for (unsigned int i = 0; i < count; i++)
+    if (unlikely (in_error)) return true;//XXXfalse
+    if (!count) return true;
+    hb_codepoint_t g = *array;
+    while (count)
     {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
+      unsigned int start = major_start (m);
+      unsigned int end = major_start (m + 1);
+      do
+      {
+	page->add (g);
+
+	array++;
+	count--;
+      }
+      while (count && (g = *array, start <= g && g < end));
     }
     return true;
   }