14d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Copyright 2016 PDFium Authors. All rights reserved.
24d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Use of this source code is governed by a BSD-style license that can be
34d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// found in the LICENSE file.
44d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
54d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
64d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfdoc/cpdf_nametree.h"
84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
9d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <utility>
10d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <vector>
11d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_array.h"
134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_dictionary.h"
144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_document.h"
15d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fpdfapi/parser/cpdf_string.h"
16d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fpdfapi/parser/fpdf_parser_decode.h"
174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannnamespace {
194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
20d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannconstexpr int kNameTreeMaxRecursion = 32;
21d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
22d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstd::pair<WideString, WideString> GetNodeLimitsMaybeSwap(CPDF_Array* pLimits) {
23d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(pLimits);
24d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  WideString csLeft = pLimits->GetUnicodeTextAt(0);
25d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  WideString csRight = pLimits->GetUnicodeTextAt(1);
26d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // If the lower limit is greater than the upper limit, swap them.
27d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (csLeft.Compare(csRight) > 0) {
28d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->SetNewAt<CPDF_String>(0, csRight);
29d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->SetNewAt<CPDF_String>(1, csLeft);
30d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    csLeft = pLimits->GetUnicodeTextAt(0);
31d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    csRight = pLimits->GetUnicodeTextAt(1);
32d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
33d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return {csLeft, csRight};
34d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
35d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
36d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Get the limit arrays that leaf array |pFind| is under in the tree with root
37d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// |pNode|. |pLimits| will hold all the limit arrays from the leaf up to before
38d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// the root. Return true if successful.
39d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool GetNodeAncestorsLimits(const CPDF_Dictionary* pNode,
40d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            const CPDF_Array* pFind,
41d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            int nLevel,
42d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            std::vector<CPDF_Array*>* pLimits) {
43d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (nLevel > kNameTreeMaxRecursion)
44d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
45d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
46d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (pNode->GetArrayFor("Names") == pFind) {
47d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->push_back(pNode->GetArrayFor("Limits"));
48d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return true;
49d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
50d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
51d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pKids = pNode->GetArrayFor("Kids");
52d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!pKids)
53d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
54d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
55d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (size_t i = 0; i < pKids->GetCount(); ++i) {
56d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Dictionary* pKid = pKids->GetDictAt(i);
57d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!pKid)
58d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      continue;
59d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
60d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (GetNodeAncestorsLimits(pKid, pFind, nLevel + 1, pLimits)) {
61d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pLimits->push_back(pNode->GetArrayFor("Limits"));
62d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return true;
63d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
64d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
65d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return false;
66d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
67d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
68d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Upon the deletion of |csName| from leaf array |pFind|, update the ancestors
69d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// of |pFind|. Specifically, the limits of |pFind|'s ancestors will be updated
70d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// if needed, and any ancestors that are now empty will be removed.
71d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool UpdateNodesAndLimitsUponDeletion(CPDF_Dictionary* pNode,
72d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      const CPDF_Array* pFind,
73d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      const WideString& csName,
74d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      int nLevel) {
75d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (nLevel > kNameTreeMaxRecursion)
76d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
77d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
78d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pLimits = pNode->GetArrayFor("Limits");
79d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  WideString csLeft;
80d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  WideString csRight;
81d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (pLimits)
82d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    std::tie(csLeft, csRight) = GetNodeLimitsMaybeSwap(pLimits);
83d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pNames = pNode->GetArrayFor("Names");
85d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (pNames) {
86d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pNames != pFind)
87d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return false;
88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pNames->IsEmpty() || !pLimits)
89d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return true;
90d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (csLeft != csName && csRight != csName)
91d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return true;
92d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
93d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Since |csName| defines |pNode|'s limits, we need to loop through the
94d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // names to find the new lower and upper limits.
95d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csNewLeft = csRight;
96d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csNewRight = csLeft;
97d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (size_t i = 0; i < pNames->GetCount() / 2; ++i) {
98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      WideString wsName = pNames->GetUnicodeTextAt(i * 2);
99d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (wsName.Compare(csNewLeft) < 0)
100d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        csNewLeft = wsName;
101d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (wsName.Compare(csNewRight) > 0)
102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        csNewRight = wsName;
103d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
104d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->SetNewAt<CPDF_String>(0, csNewLeft);
105d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->SetNewAt<CPDF_String>(1, csNewRight);
106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return true;
107d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
109d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pKids = pNode->GetArrayFor("Kids");
110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!pKids)
111d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
112d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
113d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Loop through the kids to find the leaf array |pFind|.
114d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (size_t i = 0; i < pKids->GetCount(); ++i) {
115d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Dictionary* pKid = pKids->GetDictAt(i);
116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!pKid)
117d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      continue;
118d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!UpdateNodesAndLimitsUponDeletion(pKid, pFind, csName, nLevel + 1))
119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      continue;
120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
121d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Remove this child node if it's empty.
122d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if ((pKid->KeyExist("Names") && pKid->GetArrayFor("Names")->IsEmpty()) ||
123d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        (pKid->KeyExist("Kids") && pKid->GetArrayFor("Kids")->IsEmpty())) {
124d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pKids->RemoveAt(i);
125d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
126d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pKids->IsEmpty() || !pLimits)
127d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return true;
128d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (csLeft != csName && csRight != csName)
129d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return true;
130d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
131d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Since |csName| defines |pNode|'s limits, we need to loop through the
132d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // kids to find the new lower and upper limits.
133d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csNewLeft = csRight;
134d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csNewRight = csLeft;
135d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (size_t j = 0; j < pKids->GetCount(); ++j) {
136d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      CPDF_Array* pKidLimits = pKids->GetDictAt(j)->GetArrayFor("Limits");
137d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      ASSERT(pKidLimits);
138d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (pKidLimits->GetUnicodeTextAt(0).Compare(csNewLeft) < 0)
139d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        csNewLeft = pKidLimits->GetUnicodeTextAt(0);
140d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (pKidLimits->GetUnicodeTextAt(1).Compare(csNewRight) > 0)
141d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        csNewRight = pKidLimits->GetUnicodeTextAt(1);
142d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
143d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->SetNewAt<CPDF_String>(0, csNewLeft);
144d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pLimits->SetNewAt<CPDF_String>(1, csNewRight);
145d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return true;
146d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
147d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return false;
148d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
1494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
150d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Search for |csName| in the tree with root |pNode|. If successful, return the
151d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// value that |csName| points to; |nIndex| will be the index of |csName|,
152d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// |ppFind| will be the leaf array that |csName| is found in, and |pFindIndex|
153d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// will be the index of |csName| in |ppFind|. If |csName| is not found, |ppFind|
154d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// will be the leaf array that |csName| should be added to, and |pFindIndex|
155d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// will be the index that it should be added at.
156d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Object* SearchNameNodeByName(const CPDF_Dictionary* pNode,
157d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  const WideString& csName,
158d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  int nLevel,
159d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  size_t* nIndex,
160d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  CPDF_Array** ppFind,
161d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                  int* pFindIndex) {
162d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (nLevel > kNameTreeMaxRecursion)
1634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
1644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Array* pLimits = pNode->GetArrayFor("Limits");
166d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pNames = pNode->GetArrayFor("Names");
1674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pLimits) {
168d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csLeft;
169d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csRight;
170d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    std::tie(csLeft, csRight) = GetNodeLimitsMaybeSwap(pLimits);
171d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Skip this node if the name to look for is smaller than its lower limit.
172d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (csName.Compare(csLeft) < 0)
173d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return nullptr;
174d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
175d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // Skip this node if the name to look for is greater than its higher limit,
176d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    // and the node itself is a leaf node.
177d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (csName.Compare(csRight) > 0 && pNames) {
178d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (ppFind)
179d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        *ppFind = pNames;
180d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (pFindIndex)
181d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        *pFindIndex = pNames->GetCount() / 2 - 1;
182d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
1834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return nullptr;
1844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
1854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
187d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // If the node is a leaf node, look for the name in its names array.
1884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pNames) {
1894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    size_t dwCount = pNames->GetCount() / 2;
1904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    for (size_t i = 0; i < dwCount; i++) {
191d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      WideString csValue = pNames->GetUnicodeTextAt(i * 2);
192d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      int32_t iCompare = csValue.Compare(csName);
193d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (iCompare > 0)
1944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        break;
195d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (ppFind)
196d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        *ppFind = pNames;
197d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (pFindIndex)
198d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        *pFindIndex = i;
199d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (iCompare < 0)
200d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        continue;
201d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
202d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      *nIndex += i;
2034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return pNames->GetDirectObjectAt(i * 2 + 1);
2044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
205d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    *nIndex += dwCount;
2064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
2074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
209d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Search through the node's children.
2104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Array* pKids = pNode->GetArrayFor("Kids");
2114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pKids)
2124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
2134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (size_t i = 0; i < pKids->GetCount(); i++) {
2154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    CPDF_Dictionary* pKid = pKids->GetDictAt(i);
2164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!pKid)
2174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      continue;
2184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
219d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Object* pFound = SearchNameNodeByName(pKid, csName, nLevel + 1, nIndex,
220d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                               ppFind, pFindIndex);
2214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (pFound)
2224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return pFound;
2234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nullptr;
2254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
227d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Get the key-value pair at |nIndex| in the tree with root |pNode|. If
228d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// successful, return the value object; |csName| will be the key, |ppFind|
229d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// will be the leaf array that this pair is in, and |pFindIndex| will be the
230d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// index of the pair in |pFind|.
231d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Object* SearchNameNodeByIndex(const CPDF_Dictionary* pNode,
232d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   size_t nIndex,
233d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   int nLevel,
234d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   size_t* nCurIndex,
235d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   WideString* csName,
236d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   CPDF_Array** ppFind,
237d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   int* pFindIndex) {
238d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (nLevel > kNameTreeMaxRecursion)
2394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
2404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Array* pNames = pNode->GetArrayFor("Names");
2424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pNames) {
2434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    size_t nCount = pNames->GetCount() / 2;
244d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (nIndex >= *nCurIndex + nCount) {
245d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      *nCurIndex += nCount;
2464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return nullptr;
2474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
2484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (ppFind)
2494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *ppFind = pNames;
250d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pFindIndex)
251d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      *pFindIndex = nIndex - *nCurIndex;
252d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
253d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    *csName = pNames->GetUnicodeTextAt((nIndex - *nCurIndex) * 2);
254d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return pNames->GetDirectObjectAt((nIndex - *nCurIndex) * 2 + 1);
2554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
256d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
2574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Array* pKids = pNode->GetArrayFor("Kids");
2584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pKids)
2594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
260d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
2614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (size_t i = 0; i < pKids->GetCount(); i++) {
2624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    CPDF_Dictionary* pKid = pKids->GetDictAt(i);
2634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!pKid)
2644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      continue;
265d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Object* pFound = SearchNameNodeByIndex(
266d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        pKid, nIndex, nLevel + 1, nCurIndex, csName, ppFind, pFindIndex);
2674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (pFound)
2684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return pFound;
2694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nullptr;
2714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
273d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Get the total number of key-value pairs in the tree with root |pNode|.
274d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannsize_t CountNamesInternal(CPDF_Dictionary* pNode, int nLevel) {
275d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (nLevel > kNameTreeMaxRecursion)
2764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return 0;
2774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Array* pNames = pNode->GetArrayFor("Names");
2794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pNames)
2804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return pNames->GetCount() / 2;
2814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Array* pKids = pNode->GetArrayFor("Kids");
2834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pKids)
2844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return 0;
2854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  size_t nCount = 0;
2874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (size_t i = 0; i < pKids->GetCount(); i++) {
2884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    CPDF_Dictionary* pKid = pKids->GetDictAt(i);
2894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!pKid)
2904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      continue;
2914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
292d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    nCount += CountNamesInternal(pKid, nLevel + 1);
2934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nCount;
2954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}  // namespace
2984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
299d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_NameTree::CPDF_NameTree(CPDF_Dictionary* pRoot) : m_pRoot(pRoot) {}
300d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
301d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_NameTree::CPDF_NameTree(const CPDF_Document* pDoc,
302d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                             const ByteString& category)
3034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    : m_pRoot(nullptr) {
304d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  const CPDF_Dictionary* pRoot = pDoc->GetRoot();
3054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pRoot)
3064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
3074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
3094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pNames)
3104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
3114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pRoot = pNames->GetDictFor(category);
3134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
315d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_NameTree::~CPDF_NameTree() {}
316d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
3174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannsize_t CPDF_NameTree::GetCount() const {
318d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return m_pRoot ? CountNamesInternal(m_pRoot.Get(), 0) : 0;
3194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
321d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannint CPDF_NameTree::GetIndex(const WideString& csName) const {
3224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!m_pRoot)
3234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return -1;
3244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  size_t nIndex = 0;
326d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!SearchNameNodeByName(m_pRoot.Get(), csName, 0, &nIndex, nullptr,
327d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                            nullptr)) {
3284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return -1;
329d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
3304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nIndex;
3314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
333d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool CPDF_NameTree::AddValueAndName(std::unique_ptr<CPDF_Object> pObj,
334d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                    const WideString& name) {
335d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_pRoot)
336d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
337d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
338d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t nIndex = 0;
339d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pFind = nullptr;
340d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  int nFindIndex = -1;
341d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Fail if the tree already contains this name or if the tree is too deep.
342d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (SearchNameNodeByName(m_pRoot.Get(), name, 0, &nIndex, &pFind,
343d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                           &nFindIndex)) {
344d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
345d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
346d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
347d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // If the returned |pFind| is a nullptr, then |name| is smaller than all
348d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // existing entries in the tree, and we did not find a leaf array to place
349d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // |name| into. We instead will find the leftmost leaf array in which to place
350d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // |name| and |pObj|.
351d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!pFind) {
352d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t nCurIndex = 0;
353d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    WideString csName;
354d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    SearchNameNodeByIndex(m_pRoot.Get(), 0, 0, &nCurIndex, &csName, &pFind,
355d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                          nullptr);
356d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
357d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(pFind);
358d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
359d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Insert the name and the object into the leaf array found. Note that the
360d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // insertion position is right after the key-value pair returned by |index|.
361d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t nNameIndex = (nFindIndex + 1) * 2;
362d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t nValueIndex = nNameIndex + 1;
363d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pFind->InsertNewAt<CPDF_String>(nNameIndex, name);
364d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pFind->InsertAt(nValueIndex, std::move(pObj));
365d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
366d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Expand the limits that the newly added name is under, if the name falls
367d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // outside of the limits of its leaf array or any arrays above it.
368d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  std::vector<CPDF_Array*> pLimits;
369d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  GetNodeAncestorsLimits(m_pRoot.Get(), pFind, 0, &pLimits);
370d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (auto* pLimit : pLimits) {
371d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!pLimit)
372d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      continue;
373d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
374d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (name.Compare(pLimit->GetUnicodeTextAt(0)) < 0)
375d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pLimit->SetNewAt<CPDF_String>(0, name);
376d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
377d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (name.Compare(pLimit->GetUnicodeTextAt(1)) > 0)
378d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pLimit->SetNewAt<CPDF_String>(1, name);
379d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
380d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return true;
381d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
382d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
383d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool CPDF_NameTree::DeleteValueAndName(int nIndex) {
384d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_pRoot)
385d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
386d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
387d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t nCurIndex = 0;
388d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  WideString csName;
389d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Array* pFind = nullptr;
390d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  int nFindIndex = -1;
391d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Fail if the tree does not contain |nIndex|.
392d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!SearchNameNodeByIndex(m_pRoot.Get(), nIndex, 0, &nCurIndex, &csName,
393d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                             &pFind, &nFindIndex)) {
394d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return false;
395d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
396d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
397d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Remove the name and the object from the leaf array |pFind|.
398d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pFind->RemoveAt(nFindIndex * 2);
399d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pFind->RemoveAt(nFindIndex * 2);
400d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
401d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Delete empty nodes and update the limits of |pFind|'s ancestors as needed.
402d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  UpdateNodesAndLimitsUponDeletion(m_pRoot.Get(), pFind, csName, 0);
403d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return true;
404d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
405d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
406d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Object* CPDF_NameTree::LookupValueAndName(int nIndex,
407d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                               WideString* csName) const {
408d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  csName->clear();
4094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!m_pRoot)
4104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
411d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
4124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  size_t nCurIndex = 0;
413d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return SearchNameNodeByIndex(m_pRoot.Get(), nIndex, 0, &nCurIndex, csName,
414d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                               nullptr, nullptr);
4154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
417d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Object* CPDF_NameTree::LookupValue(const WideString& csName) const {
4184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!m_pRoot)
4194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
420d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
4214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  size_t nIndex = 0;
422d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return SearchNameNodeByName(m_pRoot.Get(), csName, 0, &nIndex, nullptr,
423d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                              nullptr);
4244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCPDF_Array* CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc,
427d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                           const WideString& sName) {
4284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Object* pValue = LookupValue(sName);
4294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pValue) {
4304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDictFor("Dests");
4314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!pDests)
4324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return nullptr;
433d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pValue = pDests->GetDirectObjectFor(PDF_EncodeText(sName));
4344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
4354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pValue)
4364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
4374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (CPDF_Array* pArray = pValue->AsArray())
4384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return pArray;
4394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (CPDF_Dictionary* pDict = pValue->AsDictionary())
4404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return pDict->GetArrayFor("D");
4414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nullptr;
4424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
443