PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/bsh/org/objectweb/asm/Type.java

#
Java | 693 lines | 303 code | 104 blank | 286 comment | 95 complexity | 93f78ab683f33c2a34d1fde7c3b77a0d MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /***
  2. * ASM: a very small and fast Java bytecode manipulation framework
  3. * Copyright (C) 2000 INRIA, France Telecom
  4. * Copyright (C) 2002 France Telecom
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. * Contact: Eric.Bruneton@rd.francetelecom.com
  21. *
  22. * Author: Eric Bruneton
  23. */
  24. package org.gjt.sp.jedit.bsh.org.objectweb.asm;
  25. import java.lang.reflect.Method;
  26. /**
  27. * A Java type. This class can be used to make it easier to manipulate type
  28. * and method descriptors.
  29. */
  30. public class Type {
  31. /**
  32. * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
  33. */
  34. public final static int VOID = 0;
  35. /**
  36. * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
  37. */
  38. public final static int BOOLEAN = 1;
  39. /**
  40. * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
  41. */
  42. public final static int CHAR = 2;
  43. /**
  44. * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
  45. */
  46. public final static int BYTE = 3;
  47. /**
  48. * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
  49. */
  50. public final static int SHORT = 4;
  51. /**
  52. * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
  53. */
  54. public final static int INT = 5;
  55. /**
  56. * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
  57. */
  58. public final static int FLOAT = 6;
  59. /**
  60. * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
  61. */
  62. public final static int LONG = 7;
  63. /**
  64. * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
  65. */
  66. public final static int DOUBLE = 8;
  67. /**
  68. * The sort of array reference types. See {@link #getSort getSort}.
  69. */
  70. public final static int ARRAY = 9;
  71. /**
  72. * The sort of object reference type. See {@link #getSort getSort}.
  73. */
  74. public final static int OBJECT = 10;
  75. /**
  76. * The <tt>void</tt> type.
  77. */
  78. public final static Type VOID_TYPE = new Type(VOID);
  79. /**
  80. * The <tt>boolean</tt> type.
  81. */
  82. public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
  83. /**
  84. * The <tt>char</tt> type.
  85. */
  86. public final static Type CHAR_TYPE = new Type(CHAR);
  87. /**
  88. * The <tt>byte</tt> type.
  89. */
  90. public final static Type BYTE_TYPE = new Type(BYTE);
  91. /**
  92. * The <tt>short</tt> type.
  93. */
  94. public final static Type SHORT_TYPE = new Type(SHORT);
  95. /**
  96. * The <tt>int</tt> type.
  97. */
  98. public final static Type INT_TYPE = new Type(INT);
  99. /**
  100. * The <tt>float</tt> type.
  101. */
  102. public final static Type FLOAT_TYPE = new Type(FLOAT);
  103. /**
  104. * The <tt>long</tt> type.
  105. */
  106. public final static Type LONG_TYPE = new Type(LONG);
  107. /**
  108. * The <tt>double</tt> type.
  109. */
  110. public final static Type DOUBLE_TYPE = new Type(DOUBLE);
  111. // --------------------------------------------------------------------------
  112. // Fields
  113. // --------------------------------------------------------------------------
  114. /**
  115. * The sort of this Java type.
  116. */
  117. private final int sort;
  118. /**
  119. * A buffer containing the descriptor of this Java type.
  120. * This field is only used for reference types.
  121. */
  122. private char[] buf;
  123. /**
  124. * The offset of the descriptor of this Java type in {@link #buf buf}.
  125. * This field is only used for reference types.
  126. */
  127. private int off;
  128. /**
  129. * The length of the descriptor of this Java type.
  130. */
  131. private int len;
  132. // --------------------------------------------------------------------------
  133. // Constructors
  134. // --------------------------------------------------------------------------
  135. /**
  136. * Constructs a primitive type.
  137. *
  138. * @param sort the sort of the primitive type to be constructed.
  139. */
  140. private Type (final int sort) {
  141. this.sort = sort;
  142. this.len = 1;
  143. }
  144. /**
  145. * Constructs a reference type.
  146. *
  147. * @param sort the sort of the reference type to be constructed.
  148. * @param buf a buffer containing the descriptor of the previous type.
  149. * @param off the offset of this descriptor in the previous buffer.
  150. * @param len the length of this descriptor.
  151. */
  152. private Type (
  153. final int sort,
  154. final char[] buf,
  155. final int off,
  156. final int len)
  157. {
  158. this.sort = sort;
  159. this.buf = buf;
  160. this.off = off;
  161. this.len = len;
  162. }
  163. /**
  164. * Returns the Java type corresponding to the given type descriptor.
  165. *
  166. * @param typeDescriptor a type descriptor.
  167. * @return the Java type corresponding to the given type descriptor.
  168. */
  169. public static Type getType (final String typeDescriptor) {
  170. return getType(typeDescriptor.toCharArray(), 0);
  171. }
  172. /**
  173. * Returns the Java type corresponding to the given class.
  174. *
  175. * @param c a class.
  176. * @return the Java type corresponding to the given class.
  177. */
  178. public static Type getType (final Class c) {
  179. if (c.isPrimitive()) {
  180. if (c == Integer.TYPE) {
  181. return INT_TYPE;
  182. } else if (c == Void.TYPE) {
  183. return VOID_TYPE;
  184. } else if (c == Boolean.TYPE) {
  185. return BOOLEAN_TYPE;
  186. } else if (c == Byte.TYPE) {
  187. return BYTE_TYPE;
  188. } else if (c == Character.TYPE) {
  189. return CHAR_TYPE;
  190. } else if (c == Short.TYPE) {
  191. return SHORT_TYPE;
  192. } else if (c == Double.TYPE) {
  193. return DOUBLE_TYPE;
  194. } else if (c == Float.TYPE) {
  195. return FLOAT_TYPE;
  196. } else /*if (c == Long.TYPE)*/ {
  197. return LONG_TYPE;
  198. }
  199. } else {
  200. return getType(getDescriptor(c));
  201. }
  202. }
  203. /**
  204. * Returns the Java types corresponding to the argument types of the given
  205. * method descriptor.
  206. *
  207. * @param methodDescriptor a method descriptor.
  208. * @return the Java types corresponding to the argument types of the given
  209. * method descriptor.
  210. */
  211. public static Type[] getArgumentTypes (final String methodDescriptor) {
  212. char[] buf = methodDescriptor.toCharArray();
  213. int off = 1;
  214. int size = 0;
  215. while (true) {
  216. char car = buf[off++];
  217. if (car == ')') {
  218. break;
  219. } else if (car == 'L') {
  220. while (buf[off++] != ';') {
  221. }
  222. ++size;
  223. } else if (car != '[') {
  224. ++size;
  225. }
  226. }
  227. Type[] args = new Type[size];
  228. off = 1;
  229. size = 0;
  230. while (buf[off] != ')') {
  231. args[size] = getType(buf, off);
  232. off += args[size].len;
  233. size += 1;
  234. }
  235. return args;
  236. }
  237. /**
  238. * Returns the Java types corresponding to the argument types of the given
  239. * method.
  240. *
  241. * @param method a method.
  242. * @return the Java types corresponding to the argument types of the given
  243. * method.
  244. */
  245. public static Type[] getArgumentTypes (final Method method) {
  246. Class[] classes = method.getParameterTypes();
  247. Type[] types = new Type[classes.length];
  248. for (int i = classes.length - 1; i >= 0; --i) {
  249. types[i] = getType(classes[i]);
  250. }
  251. return types;
  252. }
  253. /**
  254. * Returns the Java type corresponding to the return type of the given
  255. * method descriptor.
  256. *
  257. * @param methodDescriptor a method descriptor.
  258. * @return the Java type corresponding to the return type of the given
  259. * method descriptor.
  260. */
  261. public static Type getReturnType (final String methodDescriptor) {
  262. char[] buf = methodDescriptor.toCharArray();
  263. return getType(buf, methodDescriptor.indexOf(')') + 1);
  264. }
  265. /**
  266. * Returns the Java type corresponding to the return type of the given
  267. * method.
  268. *
  269. * @param method a method.
  270. * @return the Java type corresponding to the return type of the given
  271. * method.
  272. */
  273. public static Type getReturnType (final Method method) {
  274. return getType(method.getReturnType());
  275. }
  276. /**
  277. * Returns the Java type corresponding to the given type descriptor.
  278. *
  279. * @param buf a buffer containing a type descriptor.
  280. * @param off the offset of this descriptor in the previous buffer.
  281. * @return the Java type corresponding to the given type descriptor.
  282. */
  283. private static Type getType (final char[] buf, final int off) {
  284. int len;
  285. switch (buf[off]) {
  286. case 'V': return VOID_TYPE;
  287. case 'Z': return BOOLEAN_TYPE;
  288. case 'C': return CHAR_TYPE;
  289. case 'B': return BYTE_TYPE;
  290. case 'S': return SHORT_TYPE;
  291. case 'I': return INT_TYPE;
  292. case 'F': return FLOAT_TYPE;
  293. case 'J': return LONG_TYPE;
  294. case 'D': return DOUBLE_TYPE;
  295. case '[':
  296. len = 1;
  297. while (buf[off + len] == '[') {
  298. ++len;
  299. }
  300. if (buf[off + len] == 'L') {
  301. ++len;
  302. while (buf[off + len] != ';') {
  303. ++len;
  304. }
  305. }
  306. return new Type(ARRAY, buf, off, len + 1);
  307. //case 'L':
  308. default:
  309. len = 1;
  310. while (buf[off + len] != ';') {
  311. ++len;
  312. }
  313. return new Type(OBJECT, buf, off, len + 1);
  314. }
  315. }
  316. // --------------------------------------------------------------------------
  317. // Accessors
  318. // --------------------------------------------------------------------------
  319. /**
  320. * Returns the sort of this Java type.
  321. *
  322. * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
  323. * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, {@link
  324. * #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, {@link
  325. * #ARRAY ARRAY} or {@link #OBJECT OBJECT}.
  326. */
  327. public int getSort () {
  328. return sort;
  329. }
  330. /**
  331. * Returns the number of dimensions of this array type.
  332. * This method should only be used for an array type.
  333. *
  334. * @return the number of dimensions of this array type.
  335. */
  336. public int getDimensions () {
  337. int i = 1;
  338. while (buf[off + i] == '[') {
  339. ++i;
  340. }
  341. return i;
  342. }
  343. /**
  344. * Returns the type of the elements of this array type.
  345. * This method should only be used for an array type.
  346. *
  347. * @return Returns the type of the elements of this array type.
  348. */
  349. public Type getElementType () {
  350. return getType(buf, off + getDimensions());
  351. }
  352. /**
  353. * Returns the name of the class corresponding to this object type.
  354. * This method should only be used for an object type.
  355. *
  356. * @return the fully qualified name of the class corresponding to this object
  357. * type.
  358. */
  359. public String getClassName () {
  360. return new String(buf, off + 1, len - 2).replace('/', '.');
  361. }
  362. /**
  363. * Returns the internal name of the class corresponding to this object type.
  364. * The internal name of a class is its fully qualified name, where '.' are
  365. * replaced by '/'. * This method should only be used for an object type.
  366. *
  367. * @return the internal name of the class corresponding to this object type.
  368. */
  369. public String getInternalName () {
  370. return new String(buf, off + 1, len - 2);
  371. }
  372. // --------------------------------------------------------------------------
  373. // Conversion to type descriptors
  374. // --------------------------------------------------------------------------
  375. /**
  376. * Returns the descriptor corresponding to this Java type.
  377. *
  378. * @return the descriptor corresponding to this Java type.
  379. */
  380. public String getDescriptor () {
  381. StringBuilder buf = new StringBuilder();
  382. getDescriptor(buf);
  383. return buf.toString();
  384. }
  385. /**
  386. * Returns the descriptor corresponding to the given argument and return
  387. * types.
  388. *
  389. * @param returnType the return type of the method.
  390. * @param argumentTypes the argument types of the method.
  391. * @return the descriptor corresponding to the given argument and return
  392. * types.
  393. */
  394. public static String getMethodDescriptor (
  395. final Type returnType,
  396. final Type[] argumentTypes)
  397. {
  398. StringBuilder buf = new StringBuilder();
  399. buf.append('(');
  400. for (int i = 0; i < argumentTypes.length; ++i) {
  401. argumentTypes[i].getDescriptor(buf);
  402. }
  403. buf.append(')');
  404. returnType.getDescriptor(buf);
  405. return buf.toString();
  406. }
  407. /**
  408. * Appends the descriptor corresponding to this Java type to the given string
  409. * buffer.
  410. *
  411. * @param buf the string buffer to which the descriptor must be appended.
  412. */
  413. private void getDescriptor(final StringBuilder buf) {
  414. switch (sort) {
  415. case VOID: buf.append('V'); return;
  416. case BOOLEAN: buf.append('Z'); return;
  417. case CHAR: buf.append('C'); return;
  418. case BYTE: buf.append('B'); return;
  419. case SHORT: buf.append('S'); return;
  420. case INT: buf.append('I'); return;
  421. case FLOAT: buf.append('F'); return;
  422. case LONG: buf.append('J'); return;
  423. case DOUBLE: buf.append('D'); return;
  424. //case ARRAY:
  425. //case OBJECT:
  426. default: buf.append(this.buf, off, len);
  427. }
  428. }
  429. // --------------------------------------------------------------------------
  430. // Direct conversion from classes to type descriptors,
  431. // without intermediate Type objects
  432. // --------------------------------------------------------------------------
  433. /**
  434. * Returns the internal name of the given class. The internal name of a class
  435. * is its fully qualified name, where '.' are replaced by '/'.
  436. *
  437. * @param c an object class.
  438. * @return the internal name of the given class.
  439. */
  440. public static String getInternalName (final Class c) {
  441. return c.getName().replace('.', '/');
  442. }
  443. /**
  444. * Returns the descriptor corresponding to the given Java type.
  445. *
  446. * @param c an object class, a primitive class or an array class.
  447. * @return the descriptor corresponding to the given class.
  448. */
  449. public static String getDescriptor (final Class c) {
  450. StringBuilder buf = new StringBuilder();
  451. getDescriptor(buf, c);
  452. return buf.toString();
  453. }
  454. /**
  455. * Returns the descriptor corresponding to the given method.
  456. *
  457. * @param m a {@link Method Method} object.
  458. * @return the descriptor of the given method.
  459. */
  460. public static String getMethodDescriptor (final Method m) {
  461. Class[] parameters = m.getParameterTypes();
  462. StringBuilder buf = new StringBuilder();
  463. buf.append('(');
  464. for (int i = 0; i < parameters.length; ++i) {
  465. getDescriptor(buf, parameters[i]);
  466. }
  467. buf.append(')');
  468. getDescriptor(buf, m.getReturnType());
  469. return buf.toString();
  470. }
  471. /**
  472. * Appends the descriptor of the given class to the given string buffer.
  473. *
  474. * @param buf the string buffer to which the descriptor must be appended.
  475. * @param c the class whose descriptor must be computed.
  476. */
  477. private static void getDescriptor (final StringBuilder buf, final Class c) {
  478. Class d = c;
  479. while (true) {
  480. if (d.isPrimitive()) {
  481. char car;
  482. if (d == Integer.TYPE) {
  483. car = 'I';
  484. } else if (d == Void.TYPE) {
  485. car = 'V';
  486. } else if (d == Boolean.TYPE) {
  487. car = 'Z';
  488. } else if (d == Byte.TYPE) {
  489. car = 'B';
  490. } else if (d == Character.TYPE) {
  491. car = 'C';
  492. } else if (d == Short.TYPE) {
  493. car = 'S';
  494. } else if (d == Double.TYPE) {
  495. car = 'D';
  496. } else if (d == Float.TYPE) {
  497. car = 'F';
  498. } else /*if (d == Long.TYPE)*/ {
  499. car = 'J';
  500. }
  501. buf.append(car);
  502. return;
  503. } else if (d.isArray()) {
  504. buf.append('[');
  505. d = d.getComponentType();
  506. } else {
  507. buf.append('L');
  508. String name = d.getName();
  509. int len = name.length();
  510. for (int i = 0; i < len; ++i) {
  511. char car = name.charAt(i);
  512. buf.append(car == '.' ? '/' : car);
  513. }
  514. buf.append(';');
  515. return;
  516. }
  517. }
  518. }
  519. // --------------------------------------------------------------------------
  520. // Corresponding size and opcodes
  521. // --------------------------------------------------------------------------
  522. /**
  523. * Returns the size of values of this type.
  524. *
  525. * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
  526. * <tt>double</tt>, and 1 otherwise.
  527. */
  528. public int getSize () {
  529. return (sort == LONG || sort == DOUBLE ? 2 : 1);
  530. }
  531. /**
  532. * Returns a JVM instruction opcode adapted to this Java type.
  533. *
  534. * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
  535. * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
  536. * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
  537. * @return an opcode that is similar to the given opcode, but adapted to this
  538. * Java type. For example, if this type is <tt>float</tt> and
  539. * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
  540. */
  541. public int getOpcode (final int opcode) {
  542. if (opcode == Constants.IALOAD || opcode == Constants.IASTORE) {
  543. switch (sort) {
  544. case VOID:
  545. return opcode + 5;
  546. case BOOLEAN:
  547. case BYTE:
  548. return opcode + 6;
  549. case CHAR:
  550. return opcode + 7;
  551. case SHORT:
  552. return opcode + 8;
  553. case INT:
  554. return opcode;
  555. case FLOAT:
  556. return opcode + 2;
  557. case LONG:
  558. return opcode + 1;
  559. case DOUBLE:
  560. return opcode + 3;
  561. //case ARRAY:
  562. //case OBJECT:
  563. default:
  564. return opcode + 4;
  565. }
  566. } else {
  567. switch (sort) {
  568. case VOID:
  569. return opcode + 5;
  570. case BOOLEAN:
  571. case CHAR:
  572. case BYTE:
  573. case SHORT:
  574. case INT:
  575. return opcode;
  576. case FLOAT:
  577. return opcode + 2;
  578. case LONG:
  579. return opcode + 1;
  580. case DOUBLE:
  581. return opcode + 3;
  582. //case ARRAY:
  583. //case OBJECT:
  584. default:
  585. return opcode + 4;
  586. }
  587. }
  588. }
  589. }