Add third_party/base/containers/adapters.h.

Add pdfium::base::Reversed(), and use it to convert many for-loops that
run in the reverse direction to range-based for-loops. adapters.h is a
copy of the one in Chromium.

Change-Id: I098268094cd8df72da0f789d6687bb3fa3c94ec6
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70795
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp b/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
index 3f2a4f7..8e226e4 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
@@ -15,6 +15,7 @@
 #include "core/fpdfapi/parser/cpdf_document.h"
 #include "core/fpdfapi/parser/cpdf_reference.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
+#include "third_party/base/containers/adapters.h"
 
 CPDF_PageContentManager::CPDF_PageContentManager(
     const CPDF_PageObjectHolder* obj_holder)
@@ -123,9 +124,7 @@
 
     // In reverse order so as to not change the indexes in the middle of the
     // loop, remove the streams.
-    for (auto it = streams_to_remove_.rbegin(); it != streams_to_remove_.rend();
-         ++it) {
-      size_t stream_index = *it;
+    for (size_t stream_index : pdfium::base::Reversed(streams_to_remove_)) {
       contents_array_->RemoveAt(stream_index);
       streams_left.erase(streams_left.begin() + stream_index);
     }
diff --git a/core/fxcrt/css/cfx_csscomputedstyle.cpp b/core/fxcrt/css/cfx_csscomputedstyle.cpp
index 8c37321..98ad15c 100644
--- a/core/fxcrt/css/cfx_csscomputedstyle.cpp
+++ b/core/fxcrt/css/cfx_csscomputedstyle.cpp
@@ -8,6 +8,7 @@
 
 #include "core/fxcrt/css/cfx_cssstringvalue.h"
 #include "core/fxcrt/css/cfx_cssvaluelist.h"
+#include "third_party/base/containers/adapters.h"
 
 CFX_CSSComputedStyle::CFX_CSSComputedStyle() = default;
 
@@ -15,10 +16,9 @@
 
 bool CFX_CSSComputedStyle::GetCustomStyle(const WideString& wsName,
                                           WideString* pValue) const {
-  for (auto iter = m_CustomProperties.rbegin();
-       iter != m_CustomProperties.rend(); ++iter) {
-    if (wsName == iter->name()) {
-      *pValue = iter->value();
+  for (const auto& prop : pdfium::base::Reversed(m_CustomProperties)) {
+    if (wsName == prop.name()) {
+      *pValue = prop.value();
       return true;
     }
   }
diff --git a/core/fxcrt/css/cfx_cssstyleselector.cpp b/core/fxcrt/css/cfx_cssstyleselector.cpp
index 7766d8e..48f573d 100644
--- a/core/fxcrt/css/cfx_cssstyleselector.cpp
+++ b/core/fxcrt/css/cfx_cssstyleselector.cpp
@@ -19,6 +19,7 @@
 #include "core/fxcrt/css/cfx_cssstylesheet.h"
 #include "core/fxcrt/css/cfx_csssyntaxparser.h"
 #include "core/fxcrt/css/cfx_cssvaluelist.h"
+#include "third_party/base/containers/adapters.h"
 #include "third_party/base/logging.h"
 
 CFX_CSSStyleSelector::CFX_CSSStyleSelector() = default;
@@ -560,13 +561,12 @@
 uint32_t CFX_CSSStyleSelector::ToTextDecoration(
     const RetainPtr<CFX_CSSValueList>& pValue) {
   uint32_t dwDecoration = 0;
-  for (auto it = pValue->values().rbegin(); it != pValue->values().rend();
-       ++it) {
-    const RetainPtr<CFX_CSSValue> pVal = *it;
-    if (pVal->GetType() != CFX_CSSPrimitiveType::Enum)
+  for (const RetainPtr<CFX_CSSValue>& val :
+       pdfium::base::Reversed(pValue->values())) {
+    if (val->GetType() != CFX_CSSPrimitiveType::Enum)
       continue;
 
-    switch (pVal.As<CFX_CSSEnumValue>()->Value()) {
+    switch (val.As<CFX_CSSEnumValue>()->Value()) {
       case CFX_CSSPropertyValue::Underline:
         dwDecoration |= CFX_CSSTEXTDECORATION_Underline;
         break;
diff --git a/core/fxge/android/cfpf_skiafontmgr.cpp b/core/fxge/android/cfpf_skiafontmgr.cpp
index 5f58e4b..b75d12f 100644
--- a/core/fxge/android/cfpf_skiafontmgr.cpp
+++ b/core/fxge/android/cfpf_skiafontmgr.cpp
@@ -17,6 +17,7 @@
 #include "core/fxge/android/cfpf_skiapathfont.h"
 #include "core/fxge/fx_font.h"
 #include "core/fxge/fx_freetype.h"
+#include "third_party/base/containers/adapters.h"
 #include "third_party/base/stl_util.h"
 
 namespace {
@@ -278,27 +279,26 @@
   const CFPF_SkiaPathFont* pBestFont = nullptr;
   int32_t nMax = -1;
   int32_t nGlyphNum = 0;
-  for (auto face_iter = m_FontFaces.rbegin(); face_iter != m_FontFaces.rend();
-       ++face_iter) {
-    const CFPF_SkiaPathFont* pFont = face_iter->get();
-    if (!(pFont->charsets() & FPF_SkiaGetCharset(uCharset)))
+  for (const std::unique_ptr<CFPF_SkiaPathFont>& font :
+       pdfium::base::Reversed(m_FontFaces)) {
+    if (!(font->charsets() & FPF_SkiaGetCharset(uCharset)))
       continue;
     int32_t nFind = 0;
-    uint32_t dwSysFontName = FPF_SKIANormalizeFontName(pFont->family());
+    uint32_t dwSysFontName = FPF_SKIANormalizeFontName(font->family());
     if (dwFaceName == dwSysFontName)
       nFind += FPF_SKIAMATCHWEIGHT_NAME1;
     bool bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1);
-    if (FontStyleIsForceBold(dwStyle) == FontStyleIsForceBold(pFont->style()))
+    if (FontStyleIsForceBold(dwStyle) == FontStyleIsForceBold(font->style()))
       nFind += FPF_SKIAMATCHWEIGHT_1;
-    if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(pFont->style()))
+    if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(font->style()))
       nFind += FPF_SKIAMATCHWEIGHT_1;
     if (FontStyleIsFixedPitch(dwStyle) ==
-        FontStyleIsFixedPitch(pFont->style())) {
+        FontStyleIsFixedPitch(font->style())) {
       nFind += FPF_SKIAMATCHWEIGHT_2;
     }
-    if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(pFont->style()))
+    if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(font->style()))
       nFind += FPF_SKIAMATCHWEIGHT_1;
-    if (FontStyleIsScript(dwStyle) == FontStyleIsScript(pFont->style()))
+    if (FontStyleIsScript(dwStyle) == FontStyleIsScript(font->style()))
       nFind += FPF_SKIAMATCHWEIGHT_2;
     if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) {
       nFind += FPF_SKIAMATCHWEIGHT_NAME2;
@@ -307,33 +307,33 @@
     if (uCharset == FX_CHARSET_Default || bMaybeSymbol) {
       if (nFind > nMax && bMatchedName) {
         nMax = nFind;
-        pBestFont = face_iter->get();
+        pBestFont = font.get();
       }
     } else if (FPF_SkiaIsCJK(uCharset)) {
-      if (bMatchedName || pFont->glyph_num() > nGlyphNum) {
-        pBestFont = face_iter->get();
-        nGlyphNum = pFont->glyph_num();
+      if (bMatchedName || font->glyph_num() > nGlyphNum) {
+        pBestFont = font.get();
+        nGlyphNum = font->glyph_num();
       }
     } else if (nFind > nMax) {
       nMax = nFind;
-      pBestFont = face_iter->get();
+      pBestFont = font.get();
     }
     if (nExpectVal <= nFind) {
-      pBestFont = face_iter->get();
+      pBestFont = font.get();
       break;
     }
   }
   if (!pBestFont)
     return nullptr;
 
-  auto pFont =
+  auto font =
       std::make_unique<CFPF_SkiaFont>(this, pBestFont, dwStyle, uCharset);
-  if (!pFont->IsValid())
+  if (!font->IsValid())
     return nullptr;
 
-  CFPF_SkiaFont* pRet = pFont.get();
-  m_FamilyFonts[dwHash] = std::move(pFont);
-  return pRet;
+  CFPF_SkiaFont* ret = font.get();
+  m_FamilyFonts[dwHash] = std::move(font);
+  return ret;
 }
 
 RetainPtr<CFX_Face> CFPF_SkiaFontMgr::GetFontFace(ByteStringView bsFile,
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index 9d88d9c..277a6c3 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -586,6 +586,7 @@
     "base/base_export.h",
     "base/bits.h",
     "base/compiler_specific.h",
+    "base/containers/adapters.h",
     "base/debug/alias.cc",
     "base/debug/alias.h",
     "base/immediate_crash.h",
diff --git a/third_party/base/containers/adapters.h b/third_party/base/containers/adapters.h
new file mode 100644
index 0000000..0f65ea0
--- /dev/null
+++ b/third_party/base/containers/adapters.h
@@ -0,0 +1,54 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BASE_CONTAINERS_ADAPTERS_H_
+#define THIRD_PARTY_BASE_CONTAINERS_ADAPTERS_H_
+
+#include <stddef.h>
+
+#include <iterator>
+#include <utility>
+
+namespace pdfium {
+namespace base {
+
+namespace internal {
+
+// Internal adapter class for implementing base::Reversed.
+template <typename T>
+class ReversedAdapter {
+ public:
+  using Iterator = decltype(std::rbegin(std::declval<T&>()));
+
+  explicit ReversedAdapter(T& t) : t_(t) {}
+  ReversedAdapter(const ReversedAdapter& ra) : t_(ra.t_) {}
+  ReversedAdapter& operator=(const ReversedAdapter&) = delete;
+
+  Iterator begin() const { return std::rbegin(t_); }
+  Iterator end() const { return std::rend(t_); }
+
+ private:
+  T& t_;
+};
+
+}  // namespace internal
+
+// Reversed returns a container adapter usable in a range-based "for" statement
+// for iterating a reversible container in reverse order.
+//
+// Example:
+//
+//   std::vector<int> v = ...;
+//   for (int i : base::Reversed(v)) {
+//     // iterates through v from back to front
+//   }
+template <typename T>
+internal::ReversedAdapter<T> Reversed(T& t) {
+  return internal::ReversedAdapter<T>(t);
+}
+
+}  // namespace base
+}  // namespace pdfium
+
+#endif  // THIRD_PARTY_BASE_CONTAINERS_ADAPTERS_H_
diff --git a/xfa/fgas/layout/cfx_rtfbreak.cpp b/xfa/fgas/layout/cfx_rtfbreak.cpp
index 05724d3..d294f80 100644
--- a/xfa/fgas/layout/cfx_rtfbreak.cpp
+++ b/xfa/fgas/layout/cfx_rtfbreak.cpp
@@ -11,6 +11,7 @@
 #include "build/build_config.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxge/text_char_pos.h"
+#include "third_party/base/containers/adapters.h"
 #include "third_party/base/numerics/safe_math.h"
 #include "third_party/base/stl_util.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
@@ -510,8 +511,8 @@
   int32_t iNetWidth = m_pCurLine->m_iWidth;
   int32_t iGapChars = 0;
   bool bFind = false;
-  for (auto it = tpos.rbegin(); it != tpos.rend(); it++) {
-    CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index];
+  for (const FX_TPO& pos : pdfium::base::Reversed(tpos)) {
+    const CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[pos.index];
     if (!bFind)
       iNetWidth = ttp.GetEndPos();
 
diff --git a/xfa/fgas/layout/cfx_txtbreak.cpp b/xfa/fgas/layout/cfx_txtbreak.cpp
index 6e8e89c..97a3be5 100644
--- a/xfa/fgas/layout/cfx_txtbreak.cpp
+++ b/xfa/fgas/layout/cfx_txtbreak.cpp
@@ -11,6 +11,7 @@
 #include "build/build_config.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxge/text_char_pos.h"
+#include "third_party/base/containers/adapters.h"
 #include "third_party/base/stl_util.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
 #include "xfa/fgas/layout/cfx_char.h"
@@ -415,8 +416,8 @@
   int32_t iNetWidth = m_pCurLine->m_iWidth;
   int32_t iGapChars = 0;
   bool bFind = false;
-  for (auto it = tpos.rbegin(); it != tpos.rend(); ++it) {
-    CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[it->index];
+  for (const FX_TPO& pos : pdfium::base::Reversed(tpos)) {
+    const CFX_BreakPiece& ttp = m_pCurLine->m_LinePieces[pos.index];
     if (!bFind)
       iNetWidth = ttp.GetEndPos();
 
diff --git a/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp
index ad5ecb3..51c07e9 100644
--- a/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_contentlayoutprocessor.cpp
@@ -13,6 +13,7 @@
 
 #include "fxjs/xfa/cjx_object.h"
 #include "third_party/base/compiler_specific.h"
+#include "third_party/base/containers/adapters.h"
 #include "third_party/base/logging.h"
 #include "third_party/base/stl_util.h"
 #include "xfa/fxfa/cxfa_ffdoc.h"
@@ -1376,10 +1377,10 @@
   }
 
   float fTotalHeight = 0;
-  for (auto iter = m_ArrayKeepItems.rbegin(); iter != m_ArrayKeepItems.rend();
-       iter++) {
-    AddLeaderAfterSplit(*iter);
-    fTotalHeight += (*iter)->m_sSize.height;
+  for (const RetainPtr<CXFA_ContentLayoutItem>& item :
+       pdfium::base::Reversed(m_ArrayKeepItems)) {
+    AddLeaderAfterSplit(item);
+    fTotalHeight += item->m_sSize.height;
   }
   m_ArrayKeepItems.clear();