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