1 /* 2 * BasicVector_IntBuffer.java 3 * 4 * Copyright (C) 2020 @easye 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program 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 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 20 * As a special exception, the copyright holders of this library give you 21 * permission to link this library with independent modules to produce an 22 * executable, regardless of the license terms of these independent 23 * modules, and to copy and distribute the resulting executable under 24 * terms of your choice, provided that you also meet, for each linked 25 * independent module, the terms and conditions of the license of that 26 * module. An independent module is a module which is not derived from 27 * or based on this library. If you modify this library, you may extend 28 * this exception to your version of the library, but you are not 29 * obligated to do so. If you do not wish to do so, delete this 30 * exception statement from your version. 31 */ 32 33 package org.armedbear.lisp; 34 35 import static org.armedbear.lisp.Lisp.*; 36 37 import java.nio.IntBuffer; 38 import java.nio.ByteBuffer; 39 40 // A basic vector is a specialized vector that is not displaced to another 41 // array, has no fill pointer, and is not expressly adjustable. 42 public final class BasicVector_IntBuffer 43 extends AbstractVector 44 { 45 private int capacity; 46 private IntBuffer elements; 47 private boolean directAllocation; 48 BasicVector_IntBuffer(int capacity)49 public BasicVector_IntBuffer(int capacity) { 50 this(capacity, false); 51 } 52 BasicVector_IntBuffer(int capacity, boolean directAllocation)53 public BasicVector_IntBuffer(int capacity, boolean directAllocation) { 54 this.directAllocation = directAllocation; 55 if (directAllocation) { 56 ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4); 57 elements = b.asIntBuffer(); 58 } else { 59 elements = IntBuffer.allocate(capacity); 60 } 61 this.capacity = capacity; 62 } 63 BasicVector_IntBuffer(LispObject[] array, boolean directAllocation)64 public BasicVector_IntBuffer(LispObject[] array, boolean directAllocation) { 65 capacity = array.length; 66 this.directAllocation = directAllocation; 67 if (directAllocation) { 68 ByteBuffer b = ByteBuffer.allocateDirect(capacity * 4); 69 elements = b.asIntBuffer(); 70 } else { 71 elements = IntBuffer.allocate(capacity); 72 } 73 for (int i = array.length; i-- > 0;) { 74 // FIXME: if LispObeject is a number that can't fit into an int 75 elements.put(i, (int)(array[i].longValue() & 0xffffffffL)); 76 } 77 } 78 BasicVector_IntBuffer(ByteBuffer buffer, boolean directAllocation)79 public BasicVector_IntBuffer(ByteBuffer buffer, boolean directAllocation) { 80 this.directAllocation = directAllocation; 81 elements = buffer.asIntBuffer(); 82 capacity = ((java.nio.Buffer)buffer).limit() / 4; 83 } 84 BasicVector_IntBuffer(IntBuffer buffer)85 public BasicVector_IntBuffer(IntBuffer buffer) { 86 this(buffer, false); 87 } 88 BasicVector_IntBuffer(IntBuffer buffer, boolean directAllocation)89 public BasicVector_IntBuffer(IntBuffer buffer, boolean directAllocation) { 90 this.directAllocation = directAllocation; 91 elements = buffer; 92 capacity = ((java.nio.Buffer)buffer).limit(); 93 } 94 95 @Override typeOf()96 public LispObject typeOf() { 97 return list(Symbol.SIMPLE_ARRAY, UNSIGNED_BYTE_32, 98 new Cons(Fixnum.getInstance(capacity))); 99 } 100 101 @Override classOf()102 public LispObject classOf() { 103 return BuiltInClass.VECTOR; 104 } 105 106 @Override typep(LispObject type)107 public LispObject typep(LispObject type) { 108 if (type == Symbol.SIMPLE_ARRAY) 109 return T; 110 if (type == BuiltInClass.SIMPLE_ARRAY) 111 return T; 112 return super.typep(type); 113 } 114 115 @Override getElementType()116 public LispObject getElementType() { 117 return UNSIGNED_BYTE_32; 118 } 119 120 @Override isSimpleVector()121 public boolean isSimpleVector() { 122 return false; 123 } 124 125 @Override hasFillPointer()126 public boolean hasFillPointer() { 127 return false; 128 } 129 130 @Override isAdjustable()131 public boolean isAdjustable() { 132 return false; 133 } 134 135 @Override capacity()136 public int capacity() { 137 return capacity; 138 } 139 140 @Override length()141 public int length() { 142 return capacity; 143 } 144 145 @Override elt(int index)146 public LispObject elt(int index) { 147 try { 148 return number(((long)elements.get(index)) & 0xffffffffL); 149 } catch (IndexOutOfBoundsException e) { 150 badIndex(index, capacity); 151 return NIL; // Not reached. 152 } 153 } 154 155 @Override aref(int index)156 public int aref(int index) { 157 try { 158 // FIXME: this shouldn't be used? 159 return number(((long)elements.get(index)) & 0xffffffffL).intValue(); 160 } catch (IndexOutOfBoundsException e) { 161 badIndex(index, ((java.nio.Buffer)elements).limit()); 162 return -1; // Not reached. 163 } 164 } 165 166 @Override aref_long(int index)167 public long aref_long(int index) { 168 try { 169 return ((long)elements.get(index)) & 0xffffffffL; 170 } catch (IndexOutOfBoundsException e) { 171 badIndex(index, ((java.nio.Buffer)elements).limit()); 172 return -1; // Not reached. 173 } 174 } 175 176 @Override AREF(int index)177 public LispObject AREF(int index) { 178 try { 179 return number(((long)elements.get(index)) & 0xffffffffL); 180 } catch (IndexOutOfBoundsException e) { 181 badIndex(index, ((java.nio.Buffer)elements).limit()); 182 return NIL; // Not reached. 183 } 184 } 185 186 @Override aset(int index, LispObject newValue)187 public void aset(int index, LispObject newValue) { 188 try { 189 if (newValue.isLessThan(Fixnum.ZERO) || newValue.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { 190 type_error(newValue, UNSIGNED_BYTE_32); 191 } 192 elements.put(index, (int)(newValue.longValue() & 0xffffffffL)); 193 } catch (IndexOutOfBoundsException e) { 194 badIndex(index, capacity); 195 } 196 } 197 198 @Override subseq(int start, int end)199 public LispObject subseq(int start, int end) { 200 BasicVector_IntBuffer v = new BasicVector_IntBuffer(end - start); 201 int i = start, j = 0; 202 try { 203 while (i < end) { 204 v.elements.put(j++, elements.get(i++)); 205 } 206 return v; 207 } catch (IndexOutOfBoundsException e) { 208 // FIXME 209 return error(new TypeError("Array index out of bounds: " + i + ".")); 210 } 211 } 212 213 @Override fill(LispObject obj)214 public void fill(LispObject obj) { 215 if (!(obj instanceof LispInteger)) { 216 type_error(obj, Symbol.INTEGER); 217 // Not reached. 218 return; 219 } 220 if (obj.isLessThan(Fixnum.ZERO) || obj.isGreaterThan(UNSIGNED_BYTE_32_MAX_VALUE)) { 221 type_error(obj, UNSIGNED_BYTE_32); 222 } 223 for (int i = capacity; i-- > 0;) { 224 elements.put(i, (int)(obj.longValue() & 0xffffffffL)); 225 } 226 } 227 228 @Override shrink(int n)229 public void shrink(int n) { 230 if (n < length()) { 231 // One cannot shrink the underlying ByteBuffer physically, and 232 // the elements field may refer to malloc()d memory that we 233 // shouldn't touch, so use the java.nio.Buffer limit pointer. 234 // Not totally sure that this strategy will work out… 235 ((java.nio.Buffer)elements).limit(n); 236 capacity = n; 237 return; 238 } 239 if (n == capacity) { 240 return; 241 } 242 error(new LispError()); 243 } 244 245 @Override reverse()246 public LispObject reverse() { 247 BasicVector_IntBuffer result = new BasicVector_IntBuffer(capacity); 248 int i, j; 249 for (i = 0, j = capacity - 1; i < capacity; i++, j--) { 250 result.elements.put(i, elements.get(j)); 251 } 252 return result; 253 } 254 255 @Override nreverse()256 public LispObject nreverse() { 257 int i = 0; 258 int j = capacity - 1; 259 while (i < j) { 260 int temp = elements.get(i); 261 elements.put(i, elements.get(j)); 262 elements.put(j, temp); 263 ++i; 264 --j; 265 } 266 return this; 267 } 268 269 @Override adjustArray(int newCapacity, LispObject initialElement, LispObject initialContents)270 public AbstractVector adjustArray(int newCapacity, 271 LispObject initialElement, 272 LispObject initialContents) { 273 if (initialContents != null) { 274 LispObject[] newElements = new LispObject[newCapacity]; 275 if (initialContents.listp()) { 276 LispObject list = initialContents; 277 for (int i = 0; i < newCapacity; i++) { 278 newElements[i] = list.car(); 279 list = list.cdr(); 280 } 281 } else if (initialContents.vectorp()) { 282 for (int i = 0; i < newCapacity; i++) { 283 newElements[i] = initialContents.elt(i); 284 } 285 } else { 286 type_error(initialContents, Symbol.SEQUENCE); 287 } 288 return new BasicVector_IntBuffer(newElements, directAllocation); 289 } 290 if (capacity != newCapacity) { 291 LispObject[] newElements = new LispObject[newCapacity]; 292 System.arraycopy(elements.array(), 0, newElements, 0, 293 Math.min(capacity, newCapacity)); 294 if (initialElement != null) { 295 for (int i = capacity; i < newCapacity; i++) { 296 newElements[i] = initialElement; 297 } 298 } 299 return new BasicVector_IntBuffer(newElements, directAllocation); 300 } 301 // No change. 302 return this; 303 } 304 305 @Override adjustArray(int newCapacity, AbstractArray displacedTo, int displacement)306 public AbstractVector adjustArray(int newCapacity, 307 AbstractArray displacedTo, 308 int displacement) { 309 return new ComplexVector(newCapacity, displacedTo, displacement); 310 } 311 } 312