SimpleVector.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Copyright (c) 2001, 2002, 2003, 2008, 2016 Per M.A. Bothner and Brainfood Inc.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.lists;
  4. import java.io.*;
  5. import java.util.*;
  6. /** A generic simple vector.
  7. * This is normally a wrapper around a plain Java array, the "data buffer",
  8. * which is the value of code{@code getBuffer()}.
  9. * (FUTURE: could be a wrapper around a String?)
  10. * The elements of the vector (viewed as a java.util.List)
  11. * are stored in order, in the array, in one of these modes:
  12. * <p>
  13. * <em>Very-simple mode:</em> All of elements of the data buffer are used.
  14. * Normally {@code get(i)} is the @code{i}'th element of the data buffer.
  15. * An exception: For a CharSequence (FString), the value of {@code get(i)}
  16. * is a Unicode code point, so it is found at offset computed by
  17. * {@code Character.offsetByCodePoints(i)}.
  18. * <p>
  19. * <em>Sub-range mode:</em> The elements of this vector are a
  20. * contiguous sub-range of the data buffer, given by a start offset
  21. * and a size. This is used for creating a read-only sub-list
  22. * with sharing of the data buffer.
  23. * The original is made copy-on-write.
  24. * <p>
  25. * <em>Gap-buffer mode:</em> The elements of this vector are in <em>two</em>
  26. * contiguous sub-range of the data buffer, one at the very start of the
  27. * buffer, and one at the very end, with an unused gap between them.
  28. * (The gap and either sub-range may be empty.)
  29. */
  30. public abstract class SimpleVector<E> extends AbstractSequence<E>
  31. implements AVector<E>, Externalizable, RandomAccess
  32. {
  33. // 1-bit sign; 25-bit offset; 6-bit flags; 32-bit size;
  34. protected long info = VERY_SIMPLE_FLAG;
  35. public static final int MAX_GAP_SIZE = (1 << 25) - 1;
  36. /** If isSimple(), the values are all the values of the buffer.
  37. * In this case getSize() == getBufferLength(); */
  38. protected final boolean isVerySimple() { return info < 0; }
  39. /** The values are {@code buffer[offset <: offset+size]}. */
  40. protected final boolean isSubRange() {
  41. return (info & SUBRANGE_FLAG) != 0; }
  42. /** The values are {@code buffer[0 <: size] ++ buffer[gapEnd <: ]},
  43. * where gapEnd = size + offset */
  44. protected final boolean isGapBuffer() {
  45. return (info & GAP_FLAG) != 0; }
  46. protected final void setInfoField(int size, int offset, long flags) {
  47. info = (0xFFFFFFFFL & (long) size) | ((long) offset << 38) | flags;
  48. }
  49. protected final int getGapStart() { return getSizeBits(); }
  50. protected final int getGapEnd() { return getSizeBits()+getOffsetBits(); }
  51. protected final int getGapSize() { return getOffsetBits(); }
  52. protected final void setGapBounds(int gapStart, int gapEnd, long flags) {
  53. setInfoField(gapStart, gapEnd-gapStart, flags|GAP_FLAG);
  54. }
  55. protected final void setGapBounds(int gapStart, int gapEnd) {
  56. setInfoField(gapStart, gapEnd-gapStart, (info & 0x3F00000000l) | GAP_FLAG);
  57. }
  58. protected final int getSizeBits() { return (int) info; }
  59. protected final int getOffsetBits() { return (int) (info >> 38); }
  60. protected static final long READ_ONLY_FLAG = 0x100000000L;
  61. protected static final long SHARED_FLAG = 0x200000000L;
  62. protected static final long COPY_ON_WRITE = 0x400000000L;
  63. // Could define GAP_FLAG in terms ! SUBRANGE_FLAG && !isVerySimple()
  64. protected static final long SUBRANGE_FLAG = 0x1000000000L;
  65. protected static final long GAP_FLAG = 0x2000000000L;
  66. protected static final long VERY_SIMPLE_FLAG = 0x8000000000000000L;
  67. public boolean isReadOnly() {
  68. return (info & READ_ONLY_FLAG) != 0;
  69. }
  70. public void setReadOnly() {
  71. info |= READ_ONLY_FLAG;
  72. }
  73. public int size() { return length(); }
  74. protected int length() {
  75. int len = getBufferLength();
  76. if (isVerySimple())
  77. return len;
  78. if ((info & SUBRANGE_FLAG) != 0)
  79. return getSizeBits();
  80. else // gap
  81. return len - getOffsetBits();
  82. }
  83. public int effectiveIndex(int index) {
  84. if (isVerySimple())
  85. return index;
  86. if ((info & SUBRANGE_FLAG) != 0) {
  87. // offset is start index
  88. if (index >= getSizeBits())
  89. throw new IndexOutOfBoundsException();
  90. return index + getOffsetBits();
  91. } else {
  92. // gapStart is 32-bit size "size"; gapSize is 24-bit offset
  93. if (index >= getSizeBits())
  94. index += getOffsetBits();
  95. return index;
  96. }
  97. }
  98. protected void gapReserve(int where, int needed) {
  99. gapReserveGeneric(where, needed);
  100. }
  101. protected final void gapReserveGeneric(int where, int needed) {
  102. if ((info & (READ_ONLY_FLAG|SHARED_FLAG)) != 0) {
  103. String msg = (info & (READ_ONLY_FLAG)) != 0 ?
  104. "can't adjust size of constant vector" :
  105. "can't adjust size of indirect vector";
  106. throw new UnsupportedOperationException(msg+" info:"+Long.toHexString(info));
  107. }
  108. int sz = size();
  109. int blen = getBufferLength();
  110. if ((info & (COPY_ON_WRITE)) != 0) // FIXME handled by checkCanWrite ?
  111. doCopyOnWrite(size()); // FIXME does needless moves
  112. if (isVerySimple()) {
  113. setGapBounds(sz, sz);
  114. } else if ((info & SUBRANGE_FLAG) != 0) {
  115. // FIXME
  116. }
  117. int gapStart = getSizeBits();
  118. int gapSize = getOffsetBits();
  119. int gapEnd = gapStart + gapSize;
  120. if (needed > gapEnd - gapStart) {
  121. // Need to resize.
  122. int oldLength = getBufferLength();
  123. int newLength = oldLength < 16 ? 16 : 2 * oldLength; // FIXME
  124. int size = oldLength - (gapEnd - gapStart);
  125. int minLength = size + needed;
  126. if (newLength < minLength)
  127. newLength = minLength;
  128. int newGapEnd = newLength - size + where;
  129. resizeShift(gapStart, gapEnd, where, newGapEnd);
  130. setGapBounds(where, newGapEnd);
  131. }
  132. else if (where != gapStart) {
  133. int delta = where - gapStart;
  134. if (delta > 0)
  135. shift(gapEnd, gapStart, delta);
  136. else if (delta < 0)
  137. shift(where, gapEnd + delta, - delta);
  138. else
  139. return;
  140. setGapBounds(where, gapEnd+delta);
  141. }
  142. }
  143. /** Used to grow and maybe move gap. */
  144. void resizeShift(int oldGapStart, int oldGapEnd,
  145. int newGapStart, int newGapEnd) {
  146. //base.checkCanWrite();
  147. int oldGapSize = oldGapEnd - oldGapStart;
  148. int newGapSize = newGapEnd - newGapStart;
  149. int oldLength = getBufferLength();
  150. int newLength = oldLength - oldGapSize + newGapSize;
  151. if (newLength > oldLength) {
  152. copyBuffer(newLength);
  153. //size = newLength; // ???
  154. }
  155. int gapDelta = oldGapStart - newGapStart;
  156. if (gapDelta >= 0) {
  157. int endLength = oldLength - oldGapEnd;
  158. shift(oldGapEnd, newLength - endLength, endLength);
  159. if (gapDelta > 0)
  160. shift(newGapStart, newGapEnd, gapDelta);
  161. } else {
  162. int endLength = newLength - newGapEnd;
  163. shift(oldLength-endLength, newGapEnd, endLength);
  164. shift(oldGapEnd, oldGapStart, newGapStart-oldGapStart);
  165. }
  166. clearBuffer(newGapStart, newGapSize);
  167. }
  168. protected abstract void setBuffer(Object obj);
  169. public abstract int getBufferLength();
  170. public abstract void copyBuffer(int length);
  171. protected abstract SimpleVector newInstance(int newSize);
  172. public SimpleVector<E> asImmutable() {
  173. if ((info & READ_ONLY_FLAG) != 0)
  174. return this;
  175. if (isVerySimple()) {
  176. SimpleVector<E> tmp = newInstance(-1);
  177. this.info |= COPY_ON_WRITE;
  178. tmp.info |= READ_ONLY_FLAG;
  179. return tmp;
  180. }
  181. return Arrays.flattenCopy(this, false);
  182. }
  183. protected void checkCanWrite () {
  184. long fl = info;
  185. if ((fl & COPY_ON_WRITE) != 0) {
  186. doCopyOnWrite(size());
  187. }
  188. if ((fl & READ_ONLY_FLAG) != 0)
  189. throw new UnsupportedOperationException("write not allowed to read-only "+(rank()==1 ? "sequence" : "array"));
  190. }
  191. protected void doCopyOnWrite(int sz) {
  192. long fl = info;
  193. Object old = getBuffer();
  194. // FIXME inefficient copy
  195. copyBuffer(sz);
  196. if ((fl & SUBRANGE_FLAG) != 0) {
  197. System.arraycopy(old, getOffsetBits(),
  198. getBuffer(), 0, sz);
  199. info = -1;
  200. }
  201. fl &= ~COPY_ON_WRITE;
  202. info = fl;
  203. }
  204. /** Get sub-range of this vector, starting at given index.
  205. * @return {@code (size<<32)|where}
  206. * such that {@code get(i)} is {@code data[where]};
  207. * {@code get(i+1)} is {@code data[where+1]};
  208. * until {@code get(i+size-1)}.
  209. * The {@code size} is at least 1 (unless {@code index==size()}),
  210. * but we try to do better.
  211. */
  212. public long getSegment(int index) {
  213. int sz = length();
  214. int where, size;
  215. if (isVerySimple()) {
  216. where = index;
  217. size = sz - index;
  218. } else if ((info & SUBRANGE_FLAG) != 0) {
  219. // values are buffer[offset <: offset+size]
  220. int istart = getOffsetBits();
  221. where = istart + index;
  222. size = sz - index;
  223. } else {
  224. int gapStart = getGapStart();
  225. int gEnd = getGapEnd();
  226. if (index < gapStart) {
  227. where = index;
  228. size = gapStart - index;
  229. } else {
  230. where = index + getGapEnd() - gapStart;
  231. size = getBufferLength() - where;
  232. }
  233. }
  234. return ((long) size << 32) | (long) where;
  235. }
  236. public int getSegment(int index, int len) {
  237. if (isGapBuffer()) {
  238. int sz = length();
  239. if (index < 0 || index > sz)
  240. return -1;
  241. if (index < 0)
  242. index = 0;
  243. else if (index + len > sz)
  244. len = sz - index;
  245. // if (len < 0 || index + len > size)
  246. // return -1;
  247. int gapStart = getGapStart();
  248. if (index + len <= gapStart)
  249. return index;
  250. if (index >= gapStart)
  251. return index + (getGapEnd() - gapStart);
  252. if ((info & READ_ONLY_FLAG) != 0)
  253. return -1;
  254. // Shift the gap depending in which direction needs least copying.
  255. if (gapStart - index > (len >> 1)) {
  256. gapReserve(index + len, 0);
  257. return index;
  258. } else {
  259. gapReserve(index, 0);
  260. return index + (getGapEnd() - gapStart);
  261. }
  262. }
  263. return getSegmentReadOnly(index, len);
  264. }
  265. public int getSegmentReadOnly(int start, int len) {
  266. int sz = length();
  267. if (start < 0 || len < 0 || start + len > sz)
  268. return -1;
  269. long result = getSegment(start);
  270. int where = (int) result;
  271. int size = (int) (result >> 32);
  272. return size >= len ? where : -1;
  273. }
  274. // Should isAfterPos, nextPos, getPosNext ... be moved to
  275. // AbstractSequence? FIXME
  276. protected boolean isAfterPos(int ipos) {
  277. return (ipos & 1) != 0;
  278. }
  279. protected abstract Object getBuffer();
  280. public E getRowMajor (int i)
  281. {
  282. return get(i);
  283. }
  284. /* #ifdef JAVA8 */
  285. @Override
  286. public void forEach(java.util.function.Consumer<? super E> action) {
  287. int len = size();
  288. int index = 0;
  289. while (len > 0) {
  290. long result = getSegment(index);
  291. int where = (int) result;
  292. int size = (int) (result >> 32);
  293. for (int i = 0; i < size; i++)
  294. action.accept(getRaw(where+i));
  295. len -= size;
  296. index += size;
  297. }
  298. }
  299. /* #endif */
  300. public void fill(E value) {
  301. checkCanWrite();
  302. for (int i = size(); --i >= 0; )
  303. setRaw(effectiveIndex(i), value);
  304. }
  305. public void shift(int srcStart, int dstStart, int count)
  306. {
  307. checkCanWrite();
  308. Object data = getBuffer();
  309. System.arraycopy(data, srcStart, data, dstStart, count);
  310. }
  311. @Override
  312. public boolean add(E o) {
  313. add(size(), o);
  314. return true;
  315. }
  316. @Override
  317. public void add(int index, E o) {
  318. addSpace(index, 1);
  319. setRaw(index, o);
  320. }
  321. protected int addPos(int ipos, E value) {
  322. int index = nextIndex(ipos);
  323. add(index, value);
  324. // FIXME should use a 'adjustPos' method
  325. int ret = createPos(index+1, true);
  326. releasePos(ipos);
  327. return ret;
  328. }
  329. /** Insert count unspecified elements at index. */
  330. protected void addSpace(int index, int count) {
  331. gapReserve(index, count);
  332. setGapBounds(getGapStart() + count, getGapEnd());
  333. }
  334. public void delete(int start, int end) {
  335. gapReserve(start, 0);
  336. int gapStart = getSizeBits();
  337. int gapSize = getOffsetBits();
  338. int gapEnd = gapStart + gapSize;
  339. int count = end-start;
  340. setGapBounds(start, gapEnd + count);
  341. clearBuffer(start, count);
  342. }
  343. protected abstract void clearBuffer(int start, int count);
  344. public Object toDataArray() {
  345. Object buffer = getBuffer();
  346. Class componentType = buffer.getClass().getComponentType();
  347. int count = size();
  348. int index = 0;
  349. Object copy = java.lang.reflect.Array.newInstance(componentType, count);
  350. while (count > 0) {
  351. long result = getSegment(index);
  352. int where = (int) result;
  353. int size = (int) (result >> 32);
  354. if (size > count)
  355. size = count;
  356. System.arraycopy(buffer, where, copy, index, size);
  357. index += size;
  358. count -= size;
  359. }
  360. return copy;
  361. }
  362. /** This is convenience hack for printing "uniform vectors" (srfi 4).
  363. * It may go away without notice! */
  364. public String getTag() { return null; }
  365. public void writeExternal(ObjectOutput out) throws IOException {
  366. out.writeObject(getBuffer());
  367. }
  368. public void readExternal(ObjectInput in)
  369. throws IOException, ClassNotFoundException {
  370. setBuffer(in.readObject());
  371. }
  372. }