View Javadoc
1   /*
2    * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.tools.javac.util;
27  
28  /** An abstraction for internal compiler strings. They are stored in
29   *  Utf8 format. Names are stored in a Name.Table, and are unique within
30   *  that table.
31   *
32   *  <p><b>This is NOT part of any supported API.
33   *  If you write code that depends on this, you do so at your own risk.
34   *  This code and its internal interfaces are subject to change or
35   *  deletion without notice.</b>
36   */
37  public abstract class Name implements javax.lang.model.element.Name {
38  
39      public final Table table;
40  
41      protected Name(Table table) {
42          this.table = table;
43      }
44  
45      /**
46       * {@inheritDoc}
47       */
48      public boolean contentEquals(CharSequence cs) {
49          return toString().equals(cs.toString());
50      }
51  
52      /**
53       * {@inheritDoc}
54       */
55      public int length() {
56          return toString().length();
57      }
58  
59      /**
60       * {@inheritDoc}
61       */
62      public char charAt(int index) {
63          return toString().charAt(index);
64      }
65  
66      /**
67       * {@inheritDoc}
68       */
69      public CharSequence subSequence(int start, int end) {
70          return toString().subSequence(start, end);
71      }
72  
73      /** Return the concatenation of this name and name `n'.
74       */
75      public Name append(Name n) {
76          int len = getByteLength();
77          byte[] bs = new byte[len + n.getByteLength()];
78          getBytes(bs, 0);
79          n.getBytes(bs, len);
80          return table.fromUtf(bs, 0, bs.length);
81      }
82  
83      /** Return the concatenation of this name, the given ASCII
84       *  character, and name `n'.
85       */
86      public Name append(char c, Name n) {
87          int len = getByteLength();
88          byte[] bs = new byte[len + 1 + n.getByteLength()];
89          getBytes(bs, 0);
90          bs[len] = (byte) c;
91          n.getBytes(bs, len+1);
92          return table.fromUtf(bs, 0, bs.length);
93      }
94  
95      /** An arbitrary but consistent complete order among all Names.
96       */
97      public int compareTo(Name other) {
98          return other.getIndex() - this.getIndex();
99      }
100 
101     /** Return true if this is the empty name.
102      */
103     public boolean isEmpty() {
104         return getByteLength() == 0;
105     }
106 
107     /** Returns last occurrence of byte b in this name, -1 if not found.
108      */
109     public int lastIndexOf(byte b) {
110         byte[] bytes = getByteArray();
111         int offset = getByteOffset();
112         int i = getByteLength() - 1;
113         while (i >= 0 && bytes[offset + i] != b) i--;
114         return i;
115     }
116 
117     /** Does this name start with prefix?
118      */
119     public boolean startsWith(Name prefix) {
120         byte[] thisBytes = this.getByteArray();
121         int thisOffset   = this.getByteOffset();
122         int thisLength   = this.getByteLength();
123         byte[] prefixBytes = prefix.getByteArray();
124         int prefixOffset   = prefix.getByteOffset();
125         int prefixLength   = prefix.getByteLength();
126 
127         int i = 0;
128         while (i < prefixLength &&
129                i < thisLength &&
130                thisBytes[thisOffset + i] == prefixBytes[prefixOffset + i])
131             i++;
132         return i == prefixLength;
133     }
134 
135     /** Returns the sub-name starting at position start, up to and
136      *  excluding position end.
137      */
138     public Name subName(int start, int end) {
139         if (end < start) end = start;
140         return table.fromUtf(getByteArray(), getByteOffset() + start, end - start);
141     }
142 
143     /** Return the string representation of this name.
144      */
145     @Override
146     public String toString() {
147         return Convert.utf2string(getByteArray(), getByteOffset(), getByteLength());
148     }
149 
150     /** Return the Utf8 representation of this name.
151      */
152     public byte[] toUtf() {
153         byte[] bs = new byte[getByteLength()];
154         getBytes(bs, 0);
155         return bs;
156     }
157 
158     /* Get a "reasonably small" value that uniquely identifies this name
159      * within its name table.
160      */
161     public abstract int getIndex();
162 
163     /** Get the length (in bytes) of this name.
164      */
165     public abstract int getByteLength();
166 
167     /** Returns i'th byte of this name.
168      */
169     public abstract byte getByteAt(int i);
170 
171     /** Copy all bytes of this name to buffer cs, starting at start.
172      */
173     public void getBytes(byte cs[], int start) {
174         System.arraycopy(getByteArray(), getByteOffset(), cs, start, getByteLength());
175     }
176 
177     /** Get the underlying byte array for this name. The contents of the
178      * array must not be modified.
179      */
180     public abstract byte[] getByteArray();
181 
182     /** Get the start offset of this name within its byte array.
183      */
184     public abstract int getByteOffset();
185 
186     /** An abstraction for the hash table used to create unique Name instances.
187      */
188     public static abstract class Table {
189         /** Standard name table.
190          */
191         public final Names names;
192 
193         Table(Names names) {
194             this.names = names;
195         }
196 
197         /** Get the name from the characters in cs[start..start+len-1].
198          */
199         public abstract Name fromChars(char[] cs, int start, int len);
200 
201         /** Get the name for the characters in string s.
202          */
203         public Name fromString(String s) {
204             char[] cs = s.toCharArray();
205             return fromChars(cs, 0, cs.length);
206         }
207 
208         /** Get the name for the bytes in array cs.
209          *  Assume that bytes are in utf8 format.
210          */
211         public Name fromUtf(byte[] cs) {
212             return fromUtf(cs, 0, cs.length);
213         }
214 
215         /** get the name for the bytes in cs[start..start+len-1].
216          *  Assume that bytes are in utf8 format.
217          */
218         public abstract Name fromUtf(byte[] cs, int start, int len);
219 
220         /** Release any resources used by this table.
221          */
222         public abstract void dispose();
223 
224         /** The hashcode of a name.
225          */
226         protected static int hashValue(byte bytes[], int offset, int length) {
227             int h = 0;
228             int off = offset;
229 
230             for (int i = 0; i < length; i++) {
231                 h = (h << 5) - h + bytes[off++];
232             }
233             return h;
234         }
235 
236         /** Compare two subarrays
237          */
238         protected static boolean equals(byte[] bytes1, int offset1,
239                 byte[] bytes2, int offset2, int length) {
240             int i = 0;
241             while (i < length && bytes1[offset1 + i] == bytes2[offset2 + i]) {
242                 i++;
243             }
244             return i == length;
245         }
246     }
247 }