OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2014, the Dart project authors. |
| 3 * |
| 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
| 5 * in compliance with the License. You may obtain a copy of the License at |
| 6 * |
| 7 * http://www.eclipse.org/legal/epl-v10.html |
| 8 * |
| 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
| 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
| 11 * or implied. See the License for the specific language governing permissions a
nd limitations under |
| 12 * the License. |
| 13 */ |
| 14 package com.google.dart.engine.internal.index.file; |
| 15 |
| 16 import com.google.common.collect.Lists; |
| 17 import com.google.dart.engine.context.AnalysisContext; |
| 18 import com.google.dart.engine.element.Element; |
| 19 import com.google.dart.engine.element.ElementLocation; |
| 20 import com.google.dart.engine.internal.element.ElementLocationImpl; |
| 21 |
| 22 import org.apache.commons.lang3.ArrayUtils; |
| 23 |
| 24 import java.util.List; |
| 25 |
| 26 /** |
| 27 * A helper that encodes/decodes {@link Element}s to/from integers. |
| 28 * |
| 29 * @coverage dart.engine.index |
| 30 */ |
| 31 public class ElementCodec { |
| 32 private final StringCodec stringCodec; |
| 33 |
| 34 /** |
| 35 * A table mapping element locations (in form of integer arrays) into a single
integer. |
| 36 */ |
| 37 private final IntArrayToIntMap pathToIndex = new IntArrayToIntMap(10000, 0.75f
); |
| 38 |
| 39 /** |
| 40 * A list that works as a mapping of integers to element encodings (in form of
integer arrays). |
| 41 */ |
| 42 private final List<int[]> indexToPath = Lists.newArrayList(); |
| 43 |
| 44 public ElementCodec(StringCodec stringCodec) { |
| 45 this.stringCodec = stringCodec; |
| 46 } |
| 47 |
| 48 /** |
| 49 * Returns an {@link Element} that corresponds to the given location. |
| 50 * |
| 51 * @param context the {@link AnalysisContext} to find {@link Element} in |
| 52 * @param index an integer corresponding to the {@link Element} |
| 53 * @return the {@link Element} or {@code null} |
| 54 */ |
| 55 public Element decode(AnalysisContext context, int index) { |
| 56 int[] path = indexToPath.get(index); |
| 57 String[] components = getLocationComponents(path); |
| 58 ElementLocation location = new ElementLocationImpl(components); |
| 59 return context.getElement(location); |
| 60 } |
| 61 |
| 62 /** |
| 63 * Returns a unique integer that corresponds to the given {@link Element}. |
| 64 */ |
| 65 public int encode(Element element) { |
| 66 int[] path = getLocationPath(element); |
| 67 int index = pathToIndex.get(path, -1); |
| 68 if (index == -1) { |
| 69 index = indexToPath.size(); |
| 70 pathToIndex.put(path, index); |
| 71 indexToPath.add(path); |
| 72 } |
| 73 return index; |
| 74 } |
| 75 |
| 76 private String[] getLocationComponents(int[] path) { |
| 77 int length = path.length; |
| 78 String[] components = new String[length]; |
| 79 int componentCount = 0; |
| 80 for (int i = 0; i < length; i++) { |
| 81 int componentId = path[i]; |
| 82 String component = stringCodec.decode(componentId); |
| 83 if (i < length - 1 && path[i + 1] < 0) { |
| 84 component += "@" + (-path[i + 1]); |
| 85 i++; |
| 86 } |
| 87 components[componentCount++] = component; |
| 88 } |
| 89 components = ArrayUtils.subarray(components, 0, componentCount); |
| 90 return components; |
| 91 } |
| 92 |
| 93 private int[] getLocationPath(Element element) { |
| 94 String[] components = element.getLocation().getComponents(); |
| 95 int length = components.length; |
| 96 if (hasLocalOffset(components)) { |
| 97 int[] path = new int[2 * length]; |
| 98 int pathLength = 0; |
| 99 for (String component : components) { |
| 100 int atOffset = component.indexOf('@'); |
| 101 if (atOffset == -1) { |
| 102 path[pathLength++] = stringCodec.encode(component); |
| 103 } else { |
| 104 String preAtString = component.substring(0, atOffset); |
| 105 String atString = component.substring(atOffset + 1); |
| 106 path[pathLength++] = stringCodec.encode(preAtString); |
| 107 path[pathLength++] = -1 * Integer.parseInt(atString); |
| 108 } |
| 109 } |
| 110 path = ArrayUtils.subarray(path, 0, pathLength); |
| 111 return path; |
| 112 } else { |
| 113 int[] path = new int[length]; |
| 114 for (int i = 0; i < length; i++) { |
| 115 String component = components[i]; |
| 116 path[i] = stringCodec.encode(component); |
| 117 } |
| 118 return path; |
| 119 } |
| 120 } |
| 121 |
| 122 private boolean hasLocalOffset(String[] components) { |
| 123 for (String component : components) { |
| 124 if (component.indexOf('@') != -1) { |
| 125 return true; |
| 126 } |
| 127 } |
| 128 return false; |
| 129 } |
| 130 } |
OLD | NEW |