File: nsChildIterator.h

package info (click to toggle)
wine-gecko-2.24 2.24%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 740,092 kB
  • ctags: 688,789
  • sloc: cpp: 3,160,639; ansic: 1,619,153; python: 164,084; java: 128,022; asm: 114,527; xml: 69,863; sh: 55,281; makefile: 49,648; perl: 20,454; objc: 2,344; yacc: 2,066; pascal: 995; lex: 982; exp: 449; php: 244; lisp: 228; awk: 211; sed: 61; csh: 21; ada: 16; ruby: 3
file content (161 lines) | stat: -rw-r--r-- 4,522 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:cindent:ts=2:et:sw=2:
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * used by nsCSSFrameConstructor to determine and iterate the child list
 * used to construct frames (normal children or something from XBL)
 */

#include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsINodeList.h"

/**
 * Helper class for iterating children during frame construction.
 * This class should always be used in lieu of the straight content
 * node APIs, since it handles XBL-generated anonymous content as
 * well.
 */
class MOZ_STACK_CLASS ChildIterator
{
protected:
  nsIContent* mContent;
  // If mNodes is non-null (so XBLInvolved() is true), mIndex is the
  // index into mNodes for our current position.  Otherwise, mChild is
  // our current child (which might be null if we're done iterating).
  union {
    uint32_t mIndex;
    nsIContent* mChild;
  };
  nsINodeList* mNodes;

public:
  ChildIterator()
    : mContent(nullptr), mChild(0), mNodes(nullptr) {}

  ChildIterator(const ChildIterator& aOther)
    : mContent(aOther.mContent),
      mNodes(aOther.mNodes) {
    if (XBLInvolved()) {
      mIndex = aOther.mIndex;
    } else {
      mChild = aOther.mChild;
    }
  }

  ChildIterator& operator=(const ChildIterator& aOther) {
    mContent = aOther.mContent;
    mNodes = aOther.mNodes;
    if (XBLInvolved()) {
      mIndex = aOther.mIndex;
    } else {
      mChild = aOther.mChild;
    }
    return *this;
  }

  ChildIterator& operator++() {
    if (XBLInvolved()) {
      ++mIndex;
    } else {
      NS_ASSERTION(mChild, "Walking off end of list?");
      mChild = mChild->GetNextSibling();
    }

    return *this;
  }

  ChildIterator operator++(int) {
    ChildIterator result(*this);
    ++(*this);
    return result;
  }

  ChildIterator& operator--() {
    if (XBLInvolved()) {
      --mIndex;
    } else if (mChild) {
      mChild = mChild->GetPreviousSibling();
      NS_ASSERTION(mChild, "Walking off beginning of list");
    } else {
      mChild = mContent->GetLastChild();
    }
    return *this;
  }

  ChildIterator operator--(int) {
    ChildIterator result(*this);
    --(*this);
    return result;
  }

  nsIContent* get() const {
    if (XBLInvolved()) {
      return mNodes->Item(mIndex);
    }

    return mChild;
  }

  nsIContent* operator*() const { return get(); }

  bool operator==(const ChildIterator& aOther) const {
    if (XBLInvolved()) {
      return mContent == aOther.mContent && mIndex == aOther.mIndex;
    }

    return mContent == aOther.mContent && mChild == aOther.mChild;
  }

  bool operator!=(const ChildIterator& aOther) const {
    return !aOther.operator==(*this);
  }

  void seek(nsIContent* aContent) {
    if (XBLInvolved()) {
      int32_t index = mNodes->IndexOf(aContent);
      // XXXbz I wish we could assert that index != -1, but it seems to not be
      // the case in some XBL cases with filtered insertion points and no
      // default insertion point.  I will now claim that XBL's management of
      // its insertion points is broken in those cases, since it's returning an
      // insertion parent for a node that doesn't actually have the node in its
      // child list according to ChildIterator.  See bug 474324.
      if (index != -1) {
        mIndex = index;
      } else {
        // If aContent isn't going to get hit by this iterator, just seek to the
        // end of the list for lack of anything better to do.
        mIndex = length();
      }
    } else if (aContent->GetParent() == mContent) {
      mChild = aContent;
    } else {
      // XXXbz I wish we could assert this doesn't happen, but I think that's
      // not necessarily the case when called from ContentInserted if
      // first-letter frames are about.
      mChild = nullptr;
    }
  }

  bool XBLInvolved() const { return mNodes != nullptr; }

  /**
   * Create a pair of ChildIterators for a content node. aFirst will
   * point to the first child of aContent; aLast will point one past
   * the last child of aContent.
   */
  static nsresult Init(nsIContent*    aContent,
                       ChildIterator* aFirst,
                       ChildIterator* aLast);

private:
  uint32_t length() {
    NS_PRECONDITION(XBLInvolved(), "Don't call me");
    uint32_t l;
    mNodes->GetLength(&l);
    return l;
  }
};