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 
17 package android.sax;
18 
19 /**
20  * Contains element children. Using this class instead of HashMap results in
21  * measurably better performance.
22  */
23 class 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      */
getOrCreate(Element parent, String uri, String localName)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      */
get(String uri, String localName)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 
Child(Element parent, String uri, String localName, int depth, int hash)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