001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.descriptors.serialization; 018 019 import gnu.trove.TObjectHashingStrategy; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.jet.lang.descriptors.*; 022 import org.jetbrains.jet.lang.resolve.name.FqName; 023 import org.jetbrains.jet.lang.resolve.name.Name; 024 025 import java.util.List; 026 027 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.QualifiedNameTable.QualifiedName; 028 029 public class StringTable { 030 public static final TObjectHashingStrategy<QualifiedName.Builder> QUALIFIED_NAME_BUILDER_HASHING = 031 new TObjectHashingStrategy<ProtoBuf.QualifiedNameTable.QualifiedName.Builder>() { 032 @Override 033 public int computeHashCode(QualifiedName.Builder object) { 034 int result = 13; 035 result = 31 * result + object.getParentQualifiedName(); 036 result = 31 * result + object.getShortName(); 037 result = 31 * result + object.getKind().hashCode(); 038 return result; 039 } 040 041 @Override 042 public boolean equals(QualifiedName.Builder o1, QualifiedName.Builder o2) { 043 return o1.getParentQualifiedName() == o2.getParentQualifiedName() 044 && o1.getShortName() == o2.getShortName() 045 && o1.getKind() == o2.getKind(); 046 } 047 }; 048 049 private final Interner<String> strings = new Interner<String>(); 050 private final Interner<QualifiedName.Builder> qualifiedNames = new Interner<QualifiedName.Builder>(QUALIFIED_NAME_BUILDER_HASHING); 051 052 @NotNull 053 public List<String> getStrings() { 054 return strings.getAllInternedObjects(); 055 } 056 057 @NotNull 058 public List<QualifiedName.Builder> getFqNames() { 059 return qualifiedNames.getAllInternedObjects(); 060 } 061 062 public int getSimpleNameIndex(@NotNull Name name) { 063 return getStringIndex(name.asString()); 064 } 065 066 public int getStringIndex(@NotNull String string) { 067 return strings.intern(string); 068 } 069 070 public int getFqNameIndex(@NotNull ClassOrPackageFragmentDescriptor descriptor) { 071 QualifiedName.Builder builder = QualifiedName.newBuilder(); 072 if (descriptor instanceof ClassDescriptor) { 073 builder.setKind(QualifiedName.Kind.CLASS); 074 } 075 builder.setShortName(getSimpleNameIndex(descriptor.getName())); 076 077 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 078 if (containingDeclaration instanceof PackageFragmentDescriptor) { 079 PackageFragmentDescriptor fragment = (PackageFragmentDescriptor) containingDeclaration; 080 if (!fragment.getFqName().isRoot()) { 081 builder.setParentQualifiedName(getFqNameIndex(fragment.getFqName())); 082 } 083 } 084 else if (containingDeclaration instanceof ClassDescriptor) { 085 ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration; 086 builder.setParentQualifiedName(getFqNameIndex(outerClass)); 087 } 088 else { 089 throw new IllegalStateException("FQ names are only stored for top-level or inner classes: " + descriptor); 090 } 091 092 return qualifiedNames.intern(builder); 093 } 094 095 public int getFqNameIndex(@NotNull FqName fqName) { 096 int result = -1; 097 for (Name segment : fqName.pathSegments()) { 098 QualifiedName.Builder builder = QualifiedName.newBuilder(); 099 builder.setShortName(getSimpleNameIndex(segment)); 100 if (result != -1) { 101 builder.setParentQualifiedName(result); 102 } 103 result = qualifiedNames.intern(builder); 104 } 105 return result; 106 } 107 }