001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package util;
028:
029: import jcc.Const;
030:
031: public abstract class SignatureIterator {
032:
033: protected String sig;
034: private int sigStart;
035: private int cur;
036: private int end;
037: private int arrayDepth;
038:
039: public boolean isSingleton;
040: protected boolean isReturnType;
041:
042: public SignatureIterator(String sig, int start, int end) {
043: this .sig = sig;
044: this .sigStart = cur = start;
045: this .end = end;
046: isSingleton = sig.charAt(start) != Const.SIGC_METHOD;
047: }
048:
049: public SignatureIterator(String sig) {
050: this (sig, 0, sig.length() - 1);
051: }
052:
053: /*
054: * Override any of these to do something more intelligent
055: */
056: public void do_boolean() {
057: do_scalar(Const.SIGC_BOOLEAN);
058: }
059:
060: public void do_char() {
061: do_scalar(Const.SIGC_CHAR);
062: }
063:
064: public void do_float() {
065: do_scalar(Const.SIGC_FLOAT);
066: }
067:
068: public void do_double() {
069: do_scalar(Const.SIGC_DOUBLE);
070: }
071:
072: public void do_byte() {
073: do_scalar(Const.SIGC_BYTE);
074: }
075:
076: public void do_short() {
077: do_scalar(Const.SIGC_SHORT);
078: }
079:
080: public void do_int() {
081: do_scalar(Const.SIGC_INT);
082: }
083:
084: public void do_long() {
085: do_scalar(Const.SIGC_LONG);
086: }
087:
088: public void do_void() {
089: do_scalar(Const.SIGC_VOID);
090: }
091:
092: public void do_scalar(char c) {
093: return;
094: }
095:
096: //
097: // do_array and do_object are expected to parse the subtype
098: // information themselves.
099: // if its a simple type (do_array only),
100: // then subTypeEnd == subTypeStart
101: // else sig.charAt(subTypeStart) == Const.SIGC_CLASS
102: // and sig.charAt(subTypeEnd) == Const.SIGC_ENDCLASS
103: //
104: public abstract void do_array(int arrayDepth, int subTypeStart,
105: int subTypeEnd);
106:
107: public abstract void do_object(int subTypeStart, int subTypeEnd);
108:
109: public boolean isMethod() {
110: return !isSingleton;
111: }
112:
113: public void iterate_parameters() throws DataFormatException {
114: cur = sigStart;
115: if (isSingleton)
116: throw new DataFormatException(sig.substring(cur - 1, end)
117: + " is not a method signature");
118: cur += 1;
119: isReturnType = false;
120: char c;
121: while ((c = sig.charAt(cur++)) != Const.SIGC_ENDMETHOD) {
122: if (cur > end) {
123: throw new DataFormatException(
124: "unterminated parameter list");
125: }
126: next(c);
127: }
128: }
129:
130: public void iterate_returntype() throws DataFormatException {
131: if (isSingleton)
132: throw new DataFormatException(sig.substring(sigStart, end)
133: + " is not a method signature");
134: int endpos = sig.indexOf(Const.SIGC_ENDMETHOD, sigStart);
135: isReturnType = true;
136: if ((endpos < 0) || (endpos > end))
137: throw new DataFormatException("unterminated parameter list");
138: cur = endpos + 1;
139: next(sig.charAt(cur++));
140: }
141:
142: public void iterate() throws DataFormatException {
143: if (isSingleton) {
144: // trivial case.
145: isReturnType = false;
146: cur = sigStart;
147: next(sig.charAt(cur++));
148: } else {
149: iterate_parameters();
150: iterate_returntype();
151: }
152: }
153:
154: private int delimitClassname() throws DataFormatException {
155: int endpos = sig.indexOf(Const.SIGC_ENDCLASS, cur);
156: if ((endpos < 0) || (endpos > end))
157: throw new DataFormatException("unending class name");
158: return endpos;
159: }
160:
161: private void next(char c) throws DataFormatException {
162: switch (c) {
163: case Const.SIGC_BOOLEAN:
164: do_boolean();
165: return;
166: case Const.SIGC_BYTE:
167: do_byte();
168: return;
169: case Const.SIGC_CHAR:
170: do_char();
171: return;
172: case Const.SIGC_SHORT:
173: do_short();
174: return;
175: case Const.SIGC_INT:
176: do_int();
177: return;
178: case Const.SIGC_FLOAT:
179: do_float();
180: return;
181: case Const.SIGC_LONG:
182: do_long();
183: return;
184: case Const.SIGC_DOUBLE:
185: do_double();
186: return;
187: case Const.SIGC_VOID:
188: do_void();
189: return;
190:
191: case Const.SIGC_CLASS:
192: int startClassName = cur - 1;
193: int endClassName = delimitClassname();
194: cur = endClassName + 1;
195: do_object(startClassName, endClassName);
196: return;
197:
198: case Const.SIGC_ARRAY:
199: arrayDepth = 0;
200: cur -= 1;
201: do {
202: arrayDepth += 1;
203: } while ((cur <= end)
204: && ((c = sig.charAt(++cur)) == Const.SIGC_ARRAY));
205: if (cur > end)
206: throw new DataFormatException("array of nothing");
207: int startBaseType = cur;
208: int endBaseType;
209: // now isolate at the base type.
210: if (c == Const.SIGC_CLASS) {
211: endBaseType = delimitClassname();
212: } else {
213: endBaseType = startBaseType;
214: }
215: cur = endBaseType + 1;
216: do_array(arrayDepth, startBaseType, endBaseType);
217: return;
218:
219: case Const.SIGC_METHOD:
220: // cannot happen here!
221: default:
222: throw new DataFormatException("unparseable signature: "
223: + sig);
224: }
225: }
226:
227: // when the baseType is a class, we have the name stashed away.
228: public String className(int startpos, int endpos) {
229: return sig.substring(startpos + 1, endpos);
230: }
231:
232: public static boolean isPrimitiveType(String sig) {
233: char c = sig.charAt(0);
234: return ((c != Const.SIGC_METHOD) && (c != Const.SIGC_ARRAY) && (c != Const.SIGC_CLASS));
235: }
236: }
|