Use PODArray<> in a few more places.

Change-Id: I12b4d12c00355aa251e0762dc19242af7b7a3956
Reviewed-on: https://code-review.googlesource.com/c/re2/+/56478
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/dfa.cc b/re2/dfa.cc
index 0c97bdf..9e2276e 100644
--- a/re2/dfa.cc
+++ b/re2/dfa.cc
@@ -599,7 +599,7 @@
   // Only ByteRange, EmptyWidth, and Match instructions are useful to keep:
   // those are the only operators with any effect in
   // RunWorkqOnEmptyString or RunWorkqOnByte.
-  int* inst = new int[q->size()];
+  PODArray<int> inst(q->size());
   int n = 0;
   uint32_t needflags = 0;  // flags needed by kInstEmptyWidth instructions
   bool sawmatch = false;   // whether queue contains guaranteed kInstMatch
@@ -629,7 +629,6 @@
              (it == q->begin() && ip->greedy(prog_))) &&
             (kind_ != Prog::kLongestMatch || !sawmark) &&
             (flag & kFlagMatch)) {
-          delete[] inst;
           if (ExtraDebug)
             fprintf(stderr, " -> FullMatchState\n");
           return FullMatchState;
@@ -676,7 +675,6 @@
   // the execution loop can stop early.  This is only okay
   // if the state is *not* a matching state.
   if (n == 0 && flag == 0) {
-    delete[] inst;
     if (ExtraDebug)
       fprintf(stderr, " -> DeadState\n");
     return DeadState;
@@ -686,7 +684,7 @@
   // unordered state sets separated by Marks.  Sort each set
   // to canonicalize, to reduce the number of distinct sets stored.
   if (kind_ == Prog::kLongestMatch) {
-    int* ip = inst;
+    int* ip = inst.data();
     int* ep = ip + n;
     while (ip < ep) {
       int* markp = ip;
@@ -703,7 +701,7 @@
   // we have an unordered set of states (i.e. we don't have Marks)
   // and sorting will reduce the number of distinct sets stored.
   if (kind_ == Prog::kManyMatch) {
-    int* ip = inst;
+    int* ip = inst.data();
     int* ep = ip + n;
     std::sort(ip, ep);
   }
@@ -722,8 +720,7 @@
   // Save the needed empty-width flags in the top bits for use later.
   flag |= needflags << kFlagNeedShift;
 
-  State* state = CachedState(inst, n, flag);
-  delete[] inst;
+  State* state = CachedState(inst.data(), n, flag);
   return state;
 }
 
diff --git a/re2/nfa.cc b/re2/nfa.cc
index 720f3e0..13686e9 100644
--- a/re2/nfa.cc
+++ b/re2/nfa.cc
@@ -69,7 +69,7 @@
       int ref;
       Thread* next;  // when on free list
     };
-    const char** capture;
+    PODArray<const char*> capture;
   };
 
   // State for explicit stack in AddToThreadq.
@@ -105,22 +105,24 @@
            const char* p);
 
   // Returns text version of capture information, for debugging.
-  std::string FormatCapture(const char** capture);
+  std::string FormatCapture(const PODArray<const char*>& capture);
 
-  inline void CopyCapture(const char** dst, const char** src);
+  void CopyCapture(PODArray<const char*>* dst, PODArray<const char*>* src) {
+    memmove(dst->data(), src->data(), ncapture_*sizeof (*src)[0]);
+  }
 
-  Prog* prog_;                // underlying program
-  int start_;                 // start instruction in program
-  int ncapture_;              // number of submatches to track
-  bool longest_;              // whether searching for longest match
-  bool endmatch_;             // whether match must end at text.end()
-  const char* btext_;         // beginning of text being matched (for FormatSubmatch)
-  const char* etext_;         // end of text being matched (for endmatch_)
-  Threadq q0_, q1_;           // pre-allocated for Search.
-  PODArray<AddState> stack_;  // pre-allocated for AddToThreadq
-  Thread* free_threads_;      // free list
-  const char** match_;        // best match so far
-  bool matched_;              // any match so far?
+  Prog* prog_;                   // underlying program
+  int start_;                    // start instruction in program
+  int ncapture_;                 // number of submatches to track
+  bool longest_;                 // whether searching for longest match
+  bool endmatch_;                // whether match must end at text.end()
+  const char* btext_;            // beginning of text (for FormatSubmatch)
+  const char* etext_;            // end of text (for endmatch_)
+  Threadq q0_, q1_;              // pre-allocated for Search.
+  PODArray<AddState> stack_;     // pre-allocated for AddToThreadq
+  Thread* free_threads_;         // free list
+  PODArray<const char*> match_;  // best match so far
+  bool matched_;                 // any match so far?
 
   NFA(const NFA&) = delete;
   NFA& operator=(const NFA&) = delete;
@@ -142,16 +144,13 @@
                prog_->inst_count(kInstNop) + 1;  // + 1 for start inst
   stack_ = PODArray<AddState>(nstack);
   free_threads_ = NULL;
-  match_ = NULL;
   matched_ = false;
 }
 
 NFA::~NFA() {
-  delete[] match_;
   Thread* next;
   for (Thread* t = free_threads_; t; t = next) {
     next = t->next;
-    delete[] t->capture;
     delete t;
   }
 }
@@ -161,7 +160,7 @@
   if (t == NULL) {
     t = new Thread;
     t->ref = 1;
-    t->capture = new const char*[ncapture_];
+    t->capture = PODArray<const char*>(ncapture_);
     return t;
   }
   free_threads_ = t->next;
@@ -186,13 +185,6 @@
   free_threads_ = t;
 }
 
-void NFA::CopyCapture(const char** dst, const char** src) {
-  for (int i = 0; i < ncapture_; i+=2) {
-    dst[i] = src[i];
-    dst[i+1] = src[i+1];
-  }
-}
-
 // Follows all empty arrows from id0 and enqueues all the states reached.
 // Enqueues only the ByteRange instructions that match byte c.
 // context is used (with p) for evaluating empty-width specials.
@@ -278,7 +270,7 @@
 
         // Record capture.
         t = AllocThread();
-        CopyCapture(t->capture, t0->capture);
+        CopyCapture(&t->capture, &t0->capture);
         t->capture[j] = p;
         t0 = t;
       }
@@ -368,7 +360,7 @@
           break;
         // The match is ours if we want it.
         if (ip->greedy(prog_) || longest_) {
-          CopyCapture(match_, t->capture);
+          CopyCapture(&match_, &t->capture);
           matched_ = true;
 
           Decref(t);
@@ -386,7 +378,7 @@
         // by storing p instead of p-1. (What would the latter even mean?!)
         // This complements the special case in NFA::Search().
         if (p == NULL) {
-          CopyCapture(match_, t->capture);
+          CopyCapture(&match_, &t->capture);
           match_[1] = p;
           matched_ = true;
           break;
@@ -401,14 +393,14 @@
           // point but longer than an existing match.
           if (!matched_ || t->capture[0] < match_[0] ||
               (t->capture[0] == match_[0] && p-1 > match_[1])) {
-            CopyCapture(match_, t->capture);
+            CopyCapture(&match_, &t->capture);
             match_[1] = p-1;
             matched_ = true;
           }
         } else {
           // Leftmost-biased mode: this match is by definition
           // better than what we've already found (see next line).
-          CopyCapture(match_, t->capture);
+          CopyCapture(&match_, &t->capture);
           match_[1] = p-1;
           matched_ = true;
 
@@ -430,7 +422,7 @@
   return 0;
 }
 
-std::string NFA::FormatCapture(const char** capture) {
+std::string NFA::FormatCapture(const PODArray<const char*>& capture) {
   std::string s;
   for (int i = 0; i < ncapture_; i+=2) {
     if (capture[i] == NULL)
@@ -488,7 +480,7 @@
     ncapture_ = 2;
   }
 
-  match_ = new const char*[ncapture_];
+  match_ = PODArray<const char*>(ncapture_);
   matched_ = false;
 
   // For debugging prints.
@@ -585,7 +577,7 @@
       }
 
       Thread* t = AllocThread();
-      CopyCapture(t->capture, match_);
+      CopyCapture(&t->capture, &match_);
       t->capture[0] = p;
       AddToThreadq(runq, start_, p < etext_ ? p[0] & 0xFF : -1, context, p,
                    t);
diff --git a/re2/parse.cc b/re2/parse.cc
index b353bba..e741603 100644
--- a/re2/parse.cc
+++ b/re2/parse.cc
@@ -1802,14 +1802,13 @@
 
   // Convert the UnicodeSet to a URange32 and UGroup that we can add.
   int nr = uset.getRangeCount();
-  URange32* r = new URange32[nr];
+  PODArray<URange32> r(nr);
   for (int i = 0; i < nr; i++) {
     r[i].lo = uset.getRangeStart(i);
     r[i].hi = uset.getRangeEnd(i);
   }
-  UGroup g = {"", +1, 0, 0, r, nr};
+  UGroup g = {"", +1, 0, 0, r.data(), nr};
   AddUGroup(cc, &g, sign, parse_flags);
-  delete[] r;
 #endif
 
   return kParseOk;
diff --git a/re2/regexp.cc b/re2/regexp.cc
index 9f49ade..b84f371 100644
--- a/re2/regexp.cc
+++ b/re2/regexp.cc
@@ -20,6 +20,7 @@
 #include "util/logging.h"
 #include "util/mutex.h"
 #include "util/utf.h"
+#include "re2/pod_array.h"
 #include "re2/stringpiece.h"
 #include "re2/walker-inl.h"
 
@@ -243,16 +244,15 @@
       return new Regexp(kRegexpEmptyMatch, flags);
   }
 
-  Regexp** subcopy = NULL;
+  PODArray<Regexp*> subcopy;
   if (op == kRegexpAlternate && can_factor) {
     // Going to edit sub; make a copy so we don't step on caller.
-    subcopy = new Regexp*[nsub];
-    memmove(subcopy, sub, nsub * sizeof sub[0]);
-    sub = subcopy;
+    subcopy = PODArray<Regexp*>(nsub);
+    memmove(subcopy.data(), sub, nsub * sizeof sub[0]);
+    sub = subcopy.data();
     nsub = FactorAlternation(sub, nsub, flags);
     if (nsub == 1) {
       Regexp* re = sub[0];
-      delete[] subcopy;
       return re;
     }
   }
@@ -269,7 +269,6 @@
     subs[nbigsub - 1] = ConcatOrAlternate(op, sub+(nbigsub-1)*kMaxNsub,
                                           nsub - (nbigsub-1)*kMaxNsub, flags,
                                           false);
-    delete[] subcopy;
     return re;
   }
 
@@ -278,8 +277,6 @@
   Regexp** subs = re->sub();
   for (int i = 0; i < nsub; i++)
     subs[i] = sub[i];
-
-  delete[] subcopy;
   return re;
 }
 
diff --git a/re2/testing/backtrack.cc b/re2/testing/backtrack.cc
index 3bab1e7..0c89d87 100644
--- a/re2/testing/backtrack.cc
+++ b/re2/testing/backtrack.cc
@@ -29,6 +29,7 @@
 
 #include "util/util.h"
 #include "util/logging.h"
+#include "re2/pod_array.h"
 #include "re2/prog.h"
 #include "re2/regexp.h"
 
@@ -53,7 +54,6 @@
 class Backtracker {
  public:
   explicit Backtracker(Prog* prog);
-  ~Backtracker();
 
   bool Search(const StringPiece& text, const StringPiece& context,
               bool anchored, bool longest,
@@ -79,9 +79,8 @@
   int nsubmatch_;           //   # of submatches to fill in
 
   // Search state
-  const char* cap_[64];     // capture registers
-  uint32_t *visited_;       // bitmap: (Inst*, char*) pairs already backtracked
-  size_t nvisited_;         //   # of words in bitmap
+  const char* cap_[64];         // capture registers
+  PODArray<uint32_t> visited_;  // bitmap: (Inst*, char*) pairs visited
 
   Backtracker(const Backtracker&) = delete;
   Backtracker& operator=(const Backtracker&) = delete;
@@ -93,13 +92,7 @@
     longest_(false),
     endmatch_(false),
     submatch_(NULL),
-    nsubmatch_(0),
-    visited_(NULL),
-    nvisited_(0) {
-}
-
-Backtracker::~Backtracker() {
-  delete[] visited_;
+    nsubmatch_(0) {
 }
 
 // Runs a backtracking search.
@@ -133,10 +126,10 @@
 
   // Allocate new visited_ bitmap -- size is proportional
   // to text, so have to reallocate on each call to Search.
-  delete[] visited_;
-  nvisited_ = (prog_->size()*(text.size()+1) + 31)/32;
-  visited_ = new uint32_t[nvisited_];
-  memset(visited_, 0, nvisited_*sizeof visited_[0]);
+  int nvisited = prog_->size() * static_cast<int>(text.size()+1);
+  nvisited = (nvisited + 31) / 32;
+  visited_ = PODArray<uint32_t>(nvisited);
+  memset(visited_.data(), 0, nvisited*sizeof visited_[0]);
 
   // Anchored search must start at text.begin().
   if (anchored_) {
@@ -167,7 +160,6 @@
   // Either way, don't go down that road again.
   CHECK(p <= text_.data() + text_.size());
   size_t n = id*(text_.size()+1) + (p - text_.data());
-  CHECK_LT(n/32, nvisited_);
   if (visited_[n/32] & (1 << (n&31)))
     return false;
   visited_[n/32] |= 1 << (n&31);