ArgListImpl.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. package gnu.mapping;
  2. import gnu.lists.Pair;
  3. import java.util.List;
  4. import java.util.Map;
  5. public class ArgListImpl implements ArgList, ArgListBuilder {
  6. /*
  7. public Object value0;
  8. public Object value1;
  9. public Object value2;
  10. public Object value3;
  11. public int ivalue0;
  12. public int ivalue1;
  13. public long lvalue0;
  14. public long lvalue1;
  15. public long lvalue2;
  16. */
  17. Object[] values = new Object[8];
  18. /** Number of arguments.
  19. * Includes keyword arguments but does not include the keywords themselves.
  20. */
  21. protected int count;
  22. public void printArgs() {
  23. System.err.print("args count:"+count);
  24. for (int i = 0; i < count; ) {
  25. System.err.print(" "+i+": "+values[i]);
  26. if (++i != count) System.err.print(';');
  27. }
  28. System.err.println();
  29. }
  30. /*public final static int ARG_IN_VALUE0 = 0;
  31. public final static int ARG_IN_VALUE1 = 1;
  32. public final static int ARG_IN_VALUE2 = 2;
  33. public final static int ARG_IN_VALUE3 = 3;
  34. public final static int ARG_IN_IVALUE0 = 4;
  35. public final static int ARG_IN_IVALUE1 = 5;
  36. //public final static int ARG_IN_LVALUE0 = 6;
  37. //public final static int ARG_IN_LVALUE0 = 7;
  38. //FIXME also handle float and double
  39. */
  40. /* * Encoding of where the arguments are.
  41. * Each argument uses 4 bits.
  42. * Arguments beyond 8 are implicitly ARG_IN_VALUES_ARRAY.
  43. * /
  44. int where;
  45. */
  46. public ArgListImpl() {
  47. }
  48. public ArgListImpl(ArgListImpl args) {
  49. int n = args.count;
  50. this.count = n;
  51. Object[] v = new Object[n];
  52. System.arraycopy(args.values, 0, v, 0, n);
  53. values = v;
  54. int nk = args.numKeywords;
  55. this.firstKeyword = args.firstKeyword;
  56. this.numKeywords = nk;
  57. String[] kw = args.keywords;
  58. if (kw != null && kw.length != nk) {
  59. String[] knew = new String[nk];
  60. System.arraycopy(kw, 0, knew, 0, nk);
  61. kw = knew;
  62. }
  63. this.keywords = kw;
  64. this.sortedKeywords = args.sortedKeywords;
  65. }
  66. public int numArguments() { return count; }
  67. void resetArgCount(int size) {
  68. if (count > values.length) throw new Error("bad count:"+count+" vlen:"+values.length);
  69. int len = values.length;
  70. if (len < size || len > size + 64) {
  71. int nsize = size > 32 ? size : 2 * size;
  72. values = new Object[nsize];
  73. } else {
  74. for (int i = size; i < count; i++)
  75. values[i] = null;
  76. }
  77. count = size;
  78. numKeywords = 0;
  79. keywords = null;
  80. sortedKeywords = null;
  81. }
  82. void ensureSpace(int size) {
  83. int osize = values.length;
  84. if (osize < size) {
  85. int nsize = osize <= 16 ? 32 : osize + (osize >> 1);
  86. if (nsize < size)
  87. nsize = size;
  88. Object[] v = new Object[nsize];
  89. System.arraycopy(values, 0, v, 0, count);
  90. values = v;
  91. }
  92. }
  93. public Object popLast() {
  94. if (count == 0
  95. || (numKeywords > 0 && firstKeyword+numKeywords >= count))
  96. ; // ERROR FIXME
  97. return values[--count];
  98. }
  99. public void shiftArgs(int toDrop) {
  100. count -= toDrop;
  101. firstKeyword -= toDrop;
  102. if (firstKeyword < 0)
  103. if (numKeywords == 0)
  104. firstKeyword = 0;
  105. else
  106. throw new Error("bad shiftArgs with keyword");
  107. System.arraycopy(values, toDrop, values, 0, count);
  108. }
  109. public void clear() {
  110. resetArgCount(0);
  111. }
  112. public void setArgs() {
  113. resetArgCount(0);
  114. }
  115. public void setArgs(Object arg0) {
  116. resetArgCount(1);
  117. values[0] = arg0;
  118. //where = ARG_IN_VALUE0;
  119. }
  120. public void setArgs(Object arg0, Object arg1) {
  121. resetArgCount(2);
  122. values[0] = arg0;
  123. values[1] = arg1;
  124. //where = ARG_IN_VALUE0|(ARG_IN_VALUE0<<4);
  125. }
  126. public void setArgs(Object arg0, Object arg1, Object arg2) {
  127. resetArgCount(3);
  128. values[0] = arg0;
  129. values[1] = arg1;
  130. values[2] = arg2;
  131. }
  132. public void setArgs(Object arg0, Object arg1, Object arg2, Object arg3) {
  133. resetArgCount(4);
  134. values[0] = arg0;
  135. values[1] = arg1;
  136. values[2] = arg2;
  137. values[3] = arg3;
  138. }
  139. public void setArgsAll(Object[] args) {
  140. resetArgCount(args.length);
  141. System.arraycopy(args, 0, values, 0, args.length);
  142. }
  143. public void setArgsAll(Object[] args, int fromIndex, int toIndex) {
  144. int length = toIndex - fromIndex;
  145. resetArgCount(length);
  146. System.arraycopy(args, fromIndex, values, 0, length);
  147. }
  148. public void add(Object arg) {
  149. int n = count;
  150. ensureSpace(n+1);
  151. count = n+1;
  152. values[n] = arg;
  153. }
  154. public void add(Object arg0, Object arg1, Object arg2, Object arg3) {
  155. int n = count;
  156. ensureSpace(n+4);
  157. count = n+4;
  158. values[n] = arg0;
  159. values[n+1] = arg1;
  160. values[n+2] = arg2;
  161. values[n+3] = arg3;
  162. }
  163. public void addAll(ArgList args) {
  164. int sz = args.numArguments();
  165. int k0 = args.firstKeyword();
  166. int nk = args.numKeywords();
  167. ensureSpace(count+sz);
  168. if (args instanceof ArgListImpl) {
  169. // FIXME optimize
  170. }
  171. for (int i = 0; i < sz; i++) {
  172. Object a = args.getArgAsObject(i);
  173. if (i >= k0 && i < k0+nk)
  174. addKey(args.getKeyword(i), a);
  175. else
  176. add(a);
  177. }
  178. }
  179. public void addSequence(Object args) {
  180. // FIXME optimize
  181. List list = gnu.lists.Sequences.coerceToSequence(args);
  182. for (Object v : list)
  183. add(v);
  184. }
  185. public void addArgList(Object args) {
  186. for (;;) {
  187. if (args instanceof ArgList) {
  188. addAll((ArgList) args);
  189. break;
  190. } else if (args instanceof Pair) {
  191. Pair pair = (Pair) args;
  192. add(pair.getCar());
  193. args = pair.getCdr();
  194. } else if (args instanceof Map) {
  195. Map map = (Map) args;
  196. for (Object k : map.keySet()) {
  197. addKey(k.toString(), map.get(k));
  198. }
  199. } else {
  200. addSequence(args);
  201. break;
  202. }
  203. }
  204. }
  205. public void addAll(List<?> args) {
  206. int sz = args.size();
  207. int n = count;
  208. ensureSpace(n+sz);
  209. for (Object a : args) {
  210. values[n++] = a;
  211. }
  212. count = n;
  213. }
  214. public void addKey(String keyword, Object arg) {
  215. if (numKeywords == 0)
  216. firstKeyword = count;
  217. else if (firstKeyword + numKeywords != count)
  218. throw new RuntimeException("keyword arguments must be continuous");
  219. add(arg);
  220. if (keywords == null) {
  221. keywords = new String[16];
  222. } else if (numKeywords == keywords.length) {
  223. String[] knew = new String[2 * numKeywords];
  224. System.arraycopy(keywords, 0, knew, 0, numKeywords);
  225. keywords = knew;
  226. }
  227. keywords[numKeywords++] = keyword;
  228. sortedKeywords = null;
  229. }
  230. public Object getArgAsObject(int i) {
  231. /*
  232. if (i < 8) {
  233. switch ((where >> (4 * i)) & 15) {
  234. case ARG_IN_VALUE0: return value0;
  235. case ARG_IN_VALUE1: return value1;
  236. case ARG_IN_VALUE2: return value2;
  237. case ARG_IN_VALUE3: return value3;
  238. case ARG_IN_IVALUE0: return Integer.make(ivalue0);
  239. case ARG_IN_IVALUE1: return Integer.make(ivalue1);
  240. //case ARG_IN_LVALUE0: return IntNum.make(ivalue0);
  241. //case ARG_IN_LVALUE1: return IntNum.make(ivalue1);
  242. }
  243. }
  244. */
  245. return values[i];
  246. }
  247. /** Index in values array */
  248. int firstKeyword;
  249. int numKeywords;
  250. /** For the i'th keyword in alphabethical order,
  251. * keywords[sortedKeywords[i]] is the actual keyword.
  252. * This array is never modified - it is normally statically allocacted.
  253. */
  254. short[] sortedKeywords;
  255. /** The keywords in the argument list, in encounter order.
  256. * Each keyword is an interned String.
  257. * Normally this array is statically allocated.
  258. */
  259. String[] keywords;
  260. public int firstKeyword() { return firstKeyword; }
  261. public int numKeywords() { return numKeywords; }
  262. public String getKeyword(int index) {
  263. return index < firstKeyword || index >= firstKeyword+numKeywords ? null
  264. : keywords[index-firstKeyword];
  265. }
  266. public static int findKeyword(ArgList args, String key) {
  267. int numK = args.numKeywords();
  268. int firstK = args.firstKeyword();
  269. for (int i = 0; i < numK; i++) {
  270. if (args.getKeyword(firstK+i) == key)
  271. return firstK + i;
  272. }
  273. return -1;
  274. }
  275. public int findKeyword(String key) {
  276. return findKeyword(this, key);
  277. }
  278. public void setKeys(int numKeywords, String[] keys, short[] sorted) {
  279. this.numKeywords = numKeywords;
  280. this.keywords = keys;
  281. this.sortedKeywords = sorted;
  282. this.firstKeyword = count - numKeywords;
  283. }
  284. public ArgList asArgList() { return this; }
  285. public ArgList asFreshArgList() { return new ArgListImpl(this); }
  286. }