001    /*
002     * Copyright 1999-2008 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    /** An abstraction for internal compiler strings. They are stored in
029     *  Utf8 format. Names are stored in a Name.Table, and are unique within
030     *  that table.
031     *
032     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
033     *  you write code that depends on this, you do so at your own risk.
034     *  This code and its internal interfaces are subject to change or
035     *  deletion without notice.</b>
036     */
037    public abstract class Name implements javax.lang.model.element.Name {
038    
039        public final Table table;
040    
041        protected Name(Table table) {
042            this.table = table;
043        }
044    
045        /**
046         * @inheritDoc
047         */
048        public boolean contentEquals(CharSequence cs) {
049            return toString().equals(cs.toString());
050        }
051    
052        /**
053         * @inheritDoc
054         */
055        public int length() {
056            return toString().length();
057        }
058    
059        /**
060         * @inheritDoc
061         */
062        public char charAt(int index) {
063            return toString().charAt(index);
064        }
065    
066        /**
067         * @inheritDoc
068         */
069        public CharSequence subSequence(int start, int end) {
070            return toString().subSequence(start, end);
071        }
072    
073        /** Return the concatenation of this name and name `n'.
074         */
075        public Name append(Name n) {
076            int len = getByteLength();
077            byte[] bs = new byte[len + n.getByteLength()];
078            getBytes(bs, 0);
079            n.getBytes(bs, len);
080            return table.fromUtf(bs, 0, bs.length);
081        }
082    
083        /** Return the concatenation of this name, the given ASCII
084         *  character, and name `n'.
085         */
086        public Name append(char c, Name n) {
087            int len = getByteLength();
088            byte[] bs = new byte[len + 1 + n.getByteLength()];
089            getBytes(bs, 0);
090            bs[len] = (byte) c;
091            n.getBytes(bs, len+1);
092            return table.fromUtf(bs, 0, bs.length);
093        }
094    
095        /** An arbitrary but consistent complete order among all Names.
096         */
097        public int compareTo(Name other) {
098            return other.getIndex() - this.getIndex();
099        }
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        public String toString() {
146            return Convert.utf2string(getByteArray(), getByteOffset(), getByteLength());
147        }
148    
149        /** Return the Utf8 representation of this name.
150         */
151        public byte[] toUtf() {
152            byte[] bs = new byte[getByteLength()];
153            getBytes(bs, 0);
154            return bs;
155        }
156    
157        /* Get a "reasonably small" value that uniquely identifies this name
158         * within its name table.
159         */
160        public abstract int getIndex();
161    
162        /** Get the length (in bytes) of this name.
163         */
164        public abstract int getByteLength();
165    
166        /** Returns i'th byte of this name.
167         */
168        public abstract byte getByteAt(int i);
169    
170        /** Copy all bytes of this name to buffer cs, starting at start.
171         */
172        public void getBytes(byte cs[], int start) {
173            System.arraycopy(getByteArray(), getByteOffset(), cs, start, getByteLength());
174        }
175    
176        /** Get the underlying byte array for this name. The contents of the
177         * array must not be modified.
178         */
179        public abstract byte[] getByteArray();
180    
181        /** Get the start offset of this name within its byte array.
182         */
183        public abstract int getByteOffset();
184    
185        /** An abstraction for the hash table used to create unique Name instances.
186         */
187        public static abstract class Table {
188            /** Standard name table.
189             */
190            public final Names names;
191    
192            Table(Names names) {
193                this.names = names;
194            }
195    
196            /** Get the name from the characters in cs[start..start+len-1].
197             */
198            public abstract Name fromChars(char[] cs, int start, int len);
199    
200            /** Get the name for the characters in string s.
201             */
202            public Name fromString(String s) {
203                char[] cs = s.toCharArray();
204                return fromChars(cs, 0, cs.length);
205            }
206    
207            /** Get the name for the bytes in array cs.
208             *  Assume that bytes are in utf8 format.
209             */
210            public Name fromUtf(byte[] cs) {
211                return fromUtf(cs, 0, cs.length);
212            }
213    
214            /** get the name for the bytes in cs[start..start+len-1].
215             *  Assume that bytes are in utf8 format.
216             */
217            public abstract Name fromUtf(byte[] cs, int start, int len);
218    
219            /** Release any resources used by this table.
220             */
221            public abstract void dispose();
222    
223            /** The hashcode of a name.
224             */
225            protected static int hashValue(byte bytes[], int offset, int length) {
226                int h = 0;
227                int off = offset;
228    
229                for (int i = 0; i < length; i++) {
230                    h = (h << 5) - h + bytes[off++];
231                }
232                return h;
233            }
234    
235            /** Compare two subarrays
236             */
237            protected static boolean equals(byte[] bytes1, int offset1,
238                    byte[] bytes2, int offset2, int length) {
239                int i = 0;
240                while (i < length && bytes1[offset1 + i] == bytes2[offset2 + i]) {
241                    i++;
242                }
243                return i == length;
244            }
245        }
246    }