001: /*
002: * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.javac.util;
027:
028: import java.lang.ref.SoftReference;
029:
030: /** An abstraction for internal compiler strings. For efficiency reasons,
031: * GJC uses hashed strings that are stored in a common large buffer.
032: *
033: * <p>Names represent unique hashable strings. Two names are equal
034: * if their indices are equal. Utf8 representation is used
035: * for storing names internally.
036: *
037: * <p><b>This is NOT part of any API supported by Sun Microsystems. If
038: * you write code that depends on this, you do so at your own risk.
039: * This code and its internal interfaces are subject to change or
040: * deletion without notice.</b>
041: */
042: @Version("@(#)Name.java 1.58 07/05/05")
043: public class Name implements javax.lang.model.element.Name {
044:
045: /** The table structure where the name is stored
046: */
047: public Table table;
048:
049: /** The index where the bytes of this name are stored in the global name
050: * buffer `names'.
051: */
052: public int index;
053:
054: /** The number of bytes in this name.
055: */
056: public int len;
057:
058: /** The next name occupying the same hash bucket.
059: */
060: Name next;
061:
062: /** The hashcode of a name.
063: */
064: private static int hashValue(byte cs[], int start, int len) {
065: int h = 0;
066: int off = start;
067:
068: for (int i = 0; i < len; i++) {
069: h = (h << 5) - h + cs[off++];
070: }
071: return h;
072: }
073:
074: /** Is (the utf8 representation of) name equal to
075: * cs[start..start+len-1]?
076: */
077: private static boolean equals(byte[] names, int index, byte cs[],
078: int start, int len) {
079: int i = 0;
080: while (i < len && names[index + i] == cs[start + i])
081: i++;
082: return i == len;
083: }
084:
085: /** Create a name from the bytes in cs[start..start+len-1].
086: * Assume that bytes are in utf8 format.
087: */
088: public static Name fromUtf(Table table, byte cs[], int start,
089: int len) {
090: int h = hashValue(cs, start, len) & table.hashMask;
091: Name n = table.hashes[h];
092: byte[] names = table.names;
093: while (n != null
094: && (n.len != len || !equals(names, n.index, cs, start,
095: len)))
096: n = n.next;
097: if (n == null) {
098: int nc = table.nc;
099: while (nc + len > names.length) {
100: // System.err.println("doubling name buffer of length + " + names.length + " to fit " + len + " bytes");//DEBUG
101: byte[] newnames = new byte[names.length * 2];
102: System.arraycopy(names, 0, newnames, 0, names.length);
103: names = table.names = newnames;
104: }
105: System.arraycopy(cs, start, names, nc, len);
106: n = new Name();
107: n.table = table;
108: n.index = nc;
109: n.len = len;
110: n.next = table.hashes[h];
111: table.hashes[h] = n;
112: table.nc = nc + len;
113: if (len == 0)
114: table.nc++;
115: }
116: return n;
117: }
118:
119: /** Create a name from the bytes in array cs.
120: * Assume that bytes are in utf8 format.
121: */
122: public static Name fromUtf(Table table, byte cs[]) {
123: return fromUtf(table, cs, 0, cs.length);
124: }
125:
126: /** Create a name from the characters in cs[start..start+len-1].
127: */
128: public static Name fromChars(Table table, char[] cs, int start,
129: int len) {
130: int nc = table.nc;
131: byte[] names = table.names;
132: while (nc + len * 3 >= names.length) {
133: // System.err.println("doubling name buffer of length " + names.length + " to fit " + len + " chars");//DEBUG
134: byte[] newnames = new byte[names.length * 2];
135: System.arraycopy(names, 0, newnames, 0, names.length);
136: names = table.names = newnames;
137: }
138: int nbytes = Convert.chars2utf(cs, start, names, nc, len) - nc;
139: int h = hashValue(names, nc, nbytes) & table.hashMask;
140: Name n = table.hashes[h];
141: while (n != null
142: && (n.len != nbytes || !equals(names, n.index, names,
143: nc, nbytes)))
144: n = n.next;
145: if (n == null) {
146: n = new Name();
147: n.table = table;
148: n.index = nc;
149: n.len = nbytes;
150: n.next = table.hashes[h];
151: table.hashes[h] = n;
152: table.nc = nc + nbytes;
153: if (nbytes == 0)
154: table.nc++;
155: }
156: return n;
157: }
158:
159: /** Create a name from the characters in string s.
160: */
161: public static Name fromString(Table table, String s) {
162: char[] cs = s.toCharArray();
163: return fromChars(table, cs, 0, cs.length);
164: }
165:
166: /** Create a name from the characters in char sequence s.
167: */
168: public static Name fromString(Table table, CharSequence s) {
169: return fromString(table, s.toString());
170: }
171:
172: /** Return the Utf8 representation of this name.
173: */
174: public byte[] toUtf() {
175: byte[] bs = new byte[len];
176: System.arraycopy(table.names, index, bs, 0, len);
177: return bs;
178: }
179:
180: /** Return the string representation of this name.
181: */
182: public String toString() {
183: return Convert.utf2string(table.names, index, len);
184: }
185:
186: /** Copy all bytes of this name to buffer cs, starting at start.
187: */
188: public void getBytes(byte cs[], int start) {
189: System.arraycopy(table.names, index, cs, start, len);
190: }
191:
192: /** Return the hash value of this name.
193: */
194: public int hashCode() {
195: return index;
196: }
197:
198: /** Is this name equal to other?
199: */
200: public boolean equals(Object other) {
201: if (other instanceof Name)
202: return table == ((Name) other).table
203: && index == ((Name) other).index;
204: else
205: return false;
206: }
207:
208: /** Compare this name to other name, yielding -1 if smaller, 0 if equal,
209: * 1 if greater.
210: */
211: public boolean less(Name that) {
212: int i = 0;
213: while (i < this .len && i < that.len) {
214: byte this b = this .table.names[this .index + i];
215: byte thatb = that.table.names[that.index + i];
216: if (this b < thatb)
217: return true;
218: else if (this b > thatb)
219: return false;
220: else
221: i++;
222: }
223: return this .len < that.len;
224: }
225:
226: /** Returns the length of this name.
227: */
228: public int length() {
229: return toString().length();
230: }
231:
232: /** Returns i'th byte of this name.
233: */
234: public byte byteAt(int i) {
235: return table.names[index + i];
236: }
237:
238: /** Returns first occurrence of byte b in this name, len if not found.
239: */
240: public int indexOf(byte b) {
241: byte[] names = table.names;
242: int i = 0;
243: while (i < len && names[index + i] != b)
244: i++;
245: return i;
246: }
247:
248: /** Returns last occurrence of byte b in this name, -1 if not found.
249: */
250: public int lastIndexOf(byte b) {
251: byte[] names = table.names;
252: int i = len - 1;
253: while (i >= 0 && names[index + i] != b)
254: i--;
255: return i;
256: }
257:
258: /** Does this name start with prefix?
259: */
260: public boolean startsWith(Name prefix) {
261: int i = 0;
262: while (i < prefix.len
263: && i < len
264: && table.names[index + i] == prefix.table.names[prefix.index
265: + i])
266: i++;
267: return i == prefix.len;
268: }
269:
270: /** Does this name end with suffix?
271: */
272: public boolean endsWith(Name suffix) {
273: int i = len - 1;
274: int j = suffix.len - 1;
275: while (j >= 0
276: && i >= 0
277: && table.names[index + i] == suffix.table.names[suffix.index
278: + j]) {
279: i--;
280: j--;
281: }
282: return j < 0;
283: }
284:
285: /** Returns the sub-name starting at position start, up to and
286: * excluding position end.
287: */
288: public Name subName(int start, int end) {
289: if (end < start)
290: end = start;
291: return fromUtf(table, table.names, index + start, end - start);
292: }
293:
294: /** Replace all `from' bytes in this name with `to' bytes.
295: */
296: public Name replace(byte from, byte to) {
297: byte[] names = table.names;
298: int i = 0;
299: while (i < len) {
300: if (names[index + i] == from) {
301: byte[] bs = new byte[len];
302: System.arraycopy(names, index, bs, 0, i);
303: bs[i] = to;
304: i++;
305: while (i < len) {
306: byte b = names[index + i];
307: bs[i] = b == from ? to : b;
308: i++;
309: }
310: return fromUtf(table, bs, 0, len);
311: }
312: i++;
313: }
314: return this ;
315: }
316:
317: /** Return the concatenation of this name and name `n'.
318: */
319: public Name append(Name n) {
320: byte[] bs = new byte[len + n.len];
321: getBytes(bs, 0);
322: n.getBytes(bs, len);
323: return fromUtf(table, bs, 0, bs.length);
324: }
325:
326: /** Return the concatenation of this name, the given ASCII
327: * character, and name `n'.
328: */
329: public Name append(char c, Name n) {
330: byte[] bs = new byte[len + n.len + 1];
331: getBytes(bs, 0);
332: bs[len] = (byte) c;
333: n.getBytes(bs, len + 1);
334: return fromUtf(table, bs, 0, bs.length);
335: }
336:
337: /** An arbitrary but consistent complete order among all Names.
338: */
339: public int compareTo(Name other) {
340: return other.index - this .index;
341: }
342:
343: /** Return the concatenation of all names in the array `ns'.
344: */
345: public static Name concat(Table table, Name ns[]) {
346: int len = 0;
347: for (int i = 0; i < ns.length; i++)
348: len = len + ns[i].len;
349: byte[] bs = new byte[len];
350: len = 0;
351: for (int i = 0; i < ns.length; i++) {
352: ns[i].getBytes(bs, len);
353: len = len + ns[i].len;
354: }
355: return fromUtf(table, bs, 0, len);
356: }
357:
358: public char charAt(int index) {
359: return toString().charAt(index);
360: }
361:
362: public CharSequence subSequence(int start, int end) {
363: return toString().subSequence(start, end);
364: }
365:
366: public boolean contentEquals(CharSequence cs) {
367: return this .toString().equals(cs.toString());
368: }
369:
370: public static class Table {
371: // maintain a freelist of recently used name tables for reuse.
372: private static List<SoftReference<Table>> freelist = List.nil();
373:
374: static private synchronized Table make() {
375: while (freelist.nonEmpty()) {
376: Table t = freelist.head.get();
377: freelist = freelist.tail;
378: if (t != null)
379: return t;
380: }
381: return new Table();
382: }
383:
384: static private synchronized void dispose(Table t) {
385: freelist = freelist.prepend(new SoftReference<Table>(t));
386: }
387:
388: public void dispose() {
389: dispose(this );
390: }
391:
392: public static final Context.Key<Table> namesKey = new Context.Key<Table>();
393:
394: public static Table instance(Context context) {
395: Table instance = context.get(namesKey);
396: if (instance == null) {
397: instance = make();
398: context.put(namesKey, instance);
399: }
400: return instance;
401: }
402:
403: /** The hash table for names.
404: */
405: private Name[] hashes;
406:
407: /** The array holding all encountered names.
408: */
409: public byte[] names;
410:
411: /** The mask to be used for hashing
412: */
413: private int hashMask;
414:
415: /** The number of filled bytes in `names'.
416: */
417: private int nc = 0;
418:
419: /** Allocator
420: * @param hashSize the (constant) size to be used for the hash table
421: * needs to be a power of two.
422: * @param nameSize the initial size of the name table.
423: */
424: public Table(int hashSize, int nameSize) {
425: hashMask = hashSize - 1;
426: hashes = new Name[hashSize];
427: names = new byte[nameSize];
428:
429: slash = fromString("/");
430: hyphen = fromString("-");
431: T = fromString("T");
432: slashequals = fromString("/=");
433: deprecated = fromString("deprecated");
434:
435: init = fromString("<init>");
436: clinit = fromString("<clinit>");
437: error = fromString("<error>");
438: any = fromString("<any>");
439: empty = fromString("");
440: one = fromString("1");
441: period = fromString(".");
442: comma = fromString(",");
443: semicolon = fromString(";");
444: asterisk = fromString("*");
445: _this = fromString("this");
446: _super = fromString("super");
447: _default = fromString("default");
448:
449: _class = fromString("class");
450: java_lang = fromString("java.lang");
451: java_lang_Object = fromString("java.lang.Object");
452: java_lang_Class = fromString("java.lang.Class");
453: java_lang_Cloneable = fromString("java.lang.Cloneable");
454: java_io_Serializable = fromString("java.io.Serializable");
455: java_lang_Enum = fromString("java.lang.Enum");
456: package_info = fromString("package-info");
457: serialVersionUID = fromString("serialVersionUID");
458: ConstantValue = fromString("ConstantValue");
459: LineNumberTable = fromString("LineNumberTable");
460: LocalVariableTable = fromString("LocalVariableTable");
461: LocalVariableTypeTable = fromString("LocalVariableTypeTable");
462: CharacterRangeTable = fromString("CharacterRangeTable");
463: StackMap = fromString("StackMap");
464: StackMapTable = fromString("StackMapTable");
465: SourceID = fromString("SourceID");
466: CompilationID = fromString("CompilationID");
467: Code = fromString("Code");
468: Exceptions = fromString("Exceptions");
469: SourceFile = fromString("SourceFile");
470: InnerClasses = fromString("InnerClasses");
471: Synthetic = fromString("Synthetic");
472: Bridge = fromString("Bridge");
473: Deprecated = fromString("Deprecated");
474: Enum = fromString("Enum");
475: _name = fromString("name");
476: Signature = fromString("Signature");
477: Varargs = fromString("Varargs");
478: Annotation = fromString("Annotation");
479: RuntimeVisibleAnnotations = fromString("RuntimeVisibleAnnotations");
480: RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
481: RuntimeVisibleParameterAnnotations = fromString("RuntimeVisibleParameterAnnotations");
482: RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
483: Value = fromString("Value");
484: EnclosingMethod = fromString("EnclosingMethod");
485:
486: desiredAssertionStatus = fromString("desiredAssertionStatus");
487:
488: append = fromString("append");
489: family = fromString("family");
490: forName = fromString("forName");
491: toString = fromString("toString");
492: length = fromString("length");
493: valueOf = fromString("valueOf");
494: value = fromString("value");
495: getMessage = fromString("getMessage");
496: getClass = fromString("getClass");
497:
498: TYPE = fromString("TYPE");
499: FIELD = fromString("FIELD");
500: METHOD = fromString("METHOD");
501: PARAMETER = fromString("PARAMETER");
502: CONSTRUCTOR = fromString("CONSTRUCTOR");
503: LOCAL_VARIABLE = fromString("LOCAL_VARIABLE");
504: ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
505: PACKAGE = fromString("PACKAGE");
506:
507: SOURCE = fromString("SOURCE");
508: CLASS = fromString("CLASS");
509: RUNTIME = fromString("RUNTIME");
510:
511: Array = fromString("Array");
512: Method = fromString("Method");
513: Bound = fromString("Bound");
514: clone = fromString("clone");
515: getComponentType = fromString("getComponentType");
516: getClassLoader = fromString("getClassLoader");
517: initCause = fromString("initCause");
518: values = fromString("values");
519: iterator = fromString("iterator");
520: hasNext = fromString("hasNext");
521: next = fromString("next");
522: AnnotationDefault = fromString("AnnotationDefault");
523: ordinal = fromString("ordinal");
524: equals = fromString("equals");
525: hashCode = fromString("hashCode");
526: compareTo = fromString("compareTo");
527: getDeclaringClass = fromString("getDeclaringClass");
528: ex = fromString("ex");
529: finalize = fromString("finalize");
530: }
531:
532: public Table() {
533: this (0x8000, 0x20000);
534: }
535:
536: /** Create a name from the bytes in cs[start..start+len-1].
537: * Assume that bytes are in utf8 format.
538: */
539: public Name fromUtf(byte cs[], int start, int len) {
540: return Name.fromUtf(this , cs, start, len);
541: }
542:
543: /** Create a name from the bytes in array cs.
544: * Assume that bytes are in utf8 format.
545: */
546: public Name fromUtf(byte cs[]) {
547: return Name.fromUtf(this , cs, 0, cs.length);
548: }
549:
550: /** Create a name from the characters in cs[start..start+len-1].
551: */
552: public Name fromChars(char[] cs, int start, int len) {
553: return Name.fromChars(this , cs, start, len);
554: }
555:
556: /** Create a name from the characters in string s.
557: */
558: public Name fromString(CharSequence s) {
559: return Name.fromString(this , s);
560: }
561:
562: public final Name slash;
563: public final Name hyphen;
564: public final Name T;
565: public final Name slashequals;
566: public final Name deprecated;
567:
568: public final Name init;
569: public final Name clinit;
570: public final Name error;
571: public final Name any;
572: public final Name empty;
573: public final Name one;
574: public final Name period;
575: public final Name comma;
576: public final Name semicolon;
577: public final Name asterisk;
578: public final Name _this ;
579: public final Name _super ;
580: public final Name _default;
581:
582: public final Name _class;
583: public final Name java_lang;
584: public final Name java_lang_Object;
585: public final Name java_lang_Class;
586: public final Name java_lang_Cloneable;
587: public final Name java_io_Serializable;
588: public final Name serialVersionUID;
589: public final Name java_lang_Enum;
590: public final Name package_info;
591: public final Name ConstantValue;
592: public final Name LineNumberTable;
593: public final Name LocalVariableTable;
594: public final Name LocalVariableTypeTable;
595: public final Name CharacterRangeTable;
596: public final Name StackMap;
597: public final Name StackMapTable;
598: public final Name SourceID;
599: public final Name CompilationID;
600: public final Name Code;
601: public final Name Exceptions;
602: public final Name SourceFile;
603: public final Name InnerClasses;
604: public final Name Synthetic;
605: public final Name Bridge;
606: public final Name Deprecated;
607: public final Name Enum;
608: public final Name _name;
609: public final Name Signature;
610: public final Name Varargs;
611: public final Name Annotation;
612: public final Name RuntimeVisibleAnnotations;
613: public final Name RuntimeInvisibleAnnotations;
614: public final Name RuntimeVisibleParameterAnnotations;
615: public final Name RuntimeInvisibleParameterAnnotations;
616:
617: public final Name Value;
618: public final Name EnclosingMethod;
619:
620: public final Name desiredAssertionStatus;
621:
622: public final Name append;
623: public final Name family;
624: public final Name forName;
625: public final Name toString;
626: public final Name length;
627: public final Name valueOf;
628: public final Name value;
629: public final Name getMessage;
630: public final Name getClass;
631:
632: public final Name TYPE;
633: public final Name FIELD;
634: public final Name METHOD;
635: public final Name PARAMETER;
636: public final Name CONSTRUCTOR;
637: public final Name LOCAL_VARIABLE;
638: public final Name ANNOTATION_TYPE;
639: public final Name PACKAGE;
640:
641: public final Name SOURCE;
642: public final Name CLASS;
643: public final Name RUNTIME;
644:
645: public final Name Array;
646: public final Name Method;
647: public final Name Bound;
648: public final Name clone;
649: public final Name getComponentType;
650: public final Name getClassLoader;
651: public final Name initCause;
652: public final Name values;
653: public final Name iterator;
654: public final Name hasNext;
655: public final Name next;
656: public final Name AnnotationDefault;
657: public final Name ordinal;
658: public final Name equals;
659: public final Name hashCode;
660: public final Name compareTo;
661: public final Name getDeclaringClass;
662: public final Name ex;
663: public final Name finalize;
664: }
665:
666: public boolean isEmpty() {
667: return len == 0;
668: }
669: }
|