1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.sax;
18
19/**
20 * Contains element children. Using this class instead of HashMap results in
21 * measurably better performance.
22 */
23class Children {
24
25    Child[] children = new Child[16];
26
27    /**
28     * Looks up a child by name and creates a new one if necessary.
29     */
30    Element getOrCreate(Element parent, String uri, String localName) {
31        int hash = uri.hashCode() * 31 + localName.hashCode();
32        int index = hash & 15;
33
34        Child current = children[index];
35        if (current == null) {
36            // We have no children in this bucket yet.
37            current = new Child(parent, uri, localName, parent.depth + 1, hash);
38            children[index] = current;
39            return current;
40        } else {
41            // Search this bucket.
42            Child previous;
43            do {
44                if (current.hash == hash
45                        && current.uri.compareTo(uri) == 0
46                        && current.localName.compareTo(localName) == 0) {
47                    // We already have a child with that name.
48                    return current;
49                }
50
51                previous = current;
52                current = current.next;
53            } while (current != null);
54
55            // Add a new child to the bucket.
56            current = new Child(parent, uri, localName, parent.depth + 1, hash);
57            previous.next = current;
58            return current;
59        }
60    }
61
62    /**
63     * Looks up a child by name.
64     */
65    Element get(String uri, String localName) {
66        int hash = uri.hashCode() * 31 + localName.hashCode();
67        int index = hash & 15;
68
69        Child current = children[index];
70        if (current == null) {
71            return null;
72        } else {
73            do {
74                if (current.hash == hash
75                        && current.uri.compareTo(uri) == 0
76                        && current.localName.compareTo(localName) == 0) {
77                    return current;
78                }
79                current = current.next;
80            } while (current != null);
81
82            return null;
83        }
84    }
85
86    static class Child extends Element {
87
88        final int hash;
89        Child next;
90
91        Child(Element parent, String uri, String localName, int depth,
92                int hash) {
93            super(parent, uri, localName, depth);
94            this.hash = hash;
95        }
96    }
97}
98