source: trunk/abcl/src/org/armedbear/lisp/ComplexVector_UnsignedByte8.java @ 12458

Last change on this file since 12458 was 12288, checked in by vvoutilainen, 15 years ago

Don't extend Lisp in LispObject, static import Lisp wherever
necessary. Patch by Douglas R. Miles.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.1 KB
Line 
1/*
2 * ComplexVector_UnsignedByte8.java
3 *
4 * Copyright (C) 2002-2005 Peter Graves
5 * $Id: ComplexVector_UnsignedByte8.java 12288 2009-11-29 22:00:12Z vvoutilainen $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38// A specialized vector of element type (UNSIGNED-BYTE 8) that is displaced to
39// another array, has a fill pointer, and/or is expressly adjustable.
40public final class ComplexVector_UnsignedByte8 extends AbstractVector
41{
42    private int capacity;
43    private int fillPointer = -1; // -1 indicates no fill pointer.
44    private boolean isDisplaced;
45
46    // For non-displaced arrays.
47    private byte[] elements;
48
49    // For displaced arrays.
50    private AbstractArray array;
51    private int displacement;
52
53    public ComplexVector_UnsignedByte8(int capacity)
54    {
55        elements = new byte[capacity];
56        this.capacity = capacity;
57    }
58
59    public ComplexVector_UnsignedByte8(int capacity, AbstractArray array,
60                                       int displacement)
61    {
62        this.capacity = capacity;
63        this.array = array;
64        this.displacement = displacement;
65        isDisplaced = true;
66    }
67
68    @Override
69    public LispObject typeOf()
70    {
71        return list(Symbol.VECTOR, UNSIGNED_BYTE_8, Fixnum.getInstance(capacity));
72    }
73
74    @Override
75    public LispObject classOf()
76    {
77        return BuiltInClass.VECTOR;
78    }
79
80    @Override
81    public boolean hasFillPointer()
82    {
83        return fillPointer >= 0;
84    }
85
86    @Override
87    public int getFillPointer()
88    {
89        return fillPointer;
90    }
91
92    @Override
93    public void setFillPointer(int n)
94    {
95        fillPointer = n;
96    }
97
98    @Override
99    public void setFillPointer(LispObject obj)
100    {
101        if (obj == T)
102            fillPointer = capacity();
103        else {
104            int n = Fixnum.getValue(obj);
105            if (n > capacity()) {
106                StringBuffer sb = new StringBuffer("The new fill pointer (");
107                sb.append(n);
108                sb.append(") exceeds the capacity of the vector (");
109                sb.append(capacity());
110                sb.append(").");
111                error(new LispError(sb.toString()));
112            } else if (n < 0) {
113                StringBuffer sb = new StringBuffer("The new fill pointer (");
114                sb.append(n);
115                sb.append(") is negative.");
116                error(new LispError(sb.toString()));
117            } else
118                fillPointer = n;
119        }
120    }
121
122    @Override
123    public boolean isDisplaced()
124    {
125        return isDisplaced;
126    }
127
128    @Override
129    public LispObject arrayDisplacement()
130    {
131        LispObject value1, value2;
132        if (array != null) {
133            value1 = array;
134            value2 = Fixnum.getInstance(displacement);
135        } else {
136            value1 = NIL;
137            value2 = Fixnum.ZERO;
138        }
139        return LispThread.currentThread().setValues(value1, value2);
140    }
141
142    @Override
143    public LispObject getElementType()
144    {
145        return UNSIGNED_BYTE_8;
146    }
147
148    @Override
149    public boolean isSimpleVector()
150    {
151        return false;
152    }
153
154    @Override
155    public int capacity()
156    {
157        return capacity;
158    }
159
160    @Override
161    public int length()
162    {
163        return fillPointer >= 0 ? fillPointer : capacity;
164    }
165
166    @Override
167    public LispObject elt(int index)
168    {
169        final int limit = length();
170        if (index < 0 || index >= limit)
171            badIndex(index, limit);
172        return AREF(index);
173    }
174
175    // Ignores fill pointer.
176    @Override
177    public LispObject AREF(int index)
178    {
179        if (elements != null) {
180            try {
181                return coerceJavaByteToLispObject(elements[index]);
182            }
183            catch (ArrayIndexOutOfBoundsException e) {
184                badIndex(index, elements.length);
185                return NIL; // Not reached.
186            }
187        } else {
188            // Displaced array.
189            if (index < 0 || index >= capacity)
190                badIndex(index, capacity);
191            return array.AREF(index + displacement);
192        }
193    }
194
195    // Ignores fill pointer.
196    // FIXME inline
197    @Override
198    public LispObject AREF(LispObject index)
199    {
200        return AREF(Fixnum.getValue(index));
201    }
202
203    @Override
204    public void aset(int index, int n)
205    {
206        if (elements != null) {
207            try {
208                elements[index] = (byte) n;
209            }
210            catch (ArrayIndexOutOfBoundsException e) {
211                badIndex(index, elements.length);
212            }
213        } else {
214            // Displaced array.
215            if (index < 0 || index >= capacity)
216                badIndex(index, capacity);
217            else
218                array.aset(index + displacement, n);
219        }
220    }
221
222    @Override
223    public void aset(int index, LispObject newValue)
224    {
225        if (elements != null) {
226            try {
227                elements[index] = coerceLispObjectToJavaByte(newValue);
228            }
229            catch (ArrayIndexOutOfBoundsException e) {
230                badIndex(index, elements.length);
231            }
232        } else
233            array.aset(index + displacement, newValue);
234    }
235
236    @Override
237    public LispObject subseq(int start, int end)
238    {
239        SimpleVector v = new SimpleVector(end - start);
240        int i = start, j = 0;
241        try {
242            while (i < end)
243                v.aset(j++, AREF(i++));
244            return v;
245        }
246        catch (ArrayIndexOutOfBoundsException e) {
247            return error(new TypeError("Array index out of bounds: " + i + "."));
248        }
249    }
250
251    @Override
252    public void fill(LispObject obj)
253    {
254        byte b = (byte) Fixnum.getValue(obj);
255        for (int i = capacity; i-- > 0;)
256            elements[i] = b;
257    }
258
259    @Override
260    public void shrink(int n)
261    {
262        if (elements != null) {
263            if (n < elements.length) {
264                byte[] newArray = new byte[n];
265                System.arraycopy(elements, 0, newArray, 0, n);
266                elements = newArray;
267                capacity = n;
268                return;
269            }
270            if (n == elements.length)
271                return;
272        }
273        error(new LispError());
274    }
275
276    @Override
277    public LispObject reverse()
278    {
279        int length = length();
280        BasicVector_UnsignedByte8 result = new BasicVector_UnsignedByte8(length);
281        int i, j;
282        for (i = 0, j = length - 1; i < length; i++, j--)
283            result.aset(i, AREF(j));
284        return result;
285    }
286
287    @Override
288    public LispObject nreverse()
289    {
290        if (elements != null) {
291            int i = 0;
292            int j = length() - 1;
293            while (i < j) {
294                byte temp = elements[i];
295                elements[i] = elements[j];
296                elements[j] = temp;
297                ++i;
298                --j;
299            }
300        } else {
301            // Displaced array.
302            int length = length();
303            byte[] data = new byte[length];
304            int i, j;
305            for (i = 0, j = length - 1; i < length; i++, j--)
306                data[i] = coerceLispObjectToJavaByte(AREF(j));
307            elements = data;
308            capacity = length;
309            array = null;
310            displacement = 0;
311            isDisplaced = false;
312            fillPointer = -1;
313        }
314        return this;
315    }
316
317    @Override
318    public void vectorPushExtend(LispObject element)
319    {
320        if (fillPointer < 0)
321            noFillPointer();
322        if (fillPointer >= capacity) {
323            // Need to extend vector.
324            ensureCapacity(capacity * 2 + 1);
325        }
326        aset(fillPointer, element);
327        ++fillPointer;
328    }
329
330    @Override
331    public LispObject VECTOR_PUSH_EXTEND(LispObject element)
332
333    {
334        vectorPushExtend(element);
335        return Fixnum.getInstance(fillPointer - 1);
336    }
337
338    @Override
339    public LispObject VECTOR_PUSH_EXTEND(LispObject element, LispObject extension)
340
341    {
342        int ext = Fixnum.getValue(extension);
343        if (fillPointer < 0)
344            noFillPointer();
345        if (fillPointer >= capacity) {
346            // Need to extend vector.
347            ext = Math.max(ext, capacity + 1);
348            ensureCapacity(capacity + ext);
349        }
350        aset(fillPointer, element);
351        return Fixnum.getInstance(fillPointer++);
352    }
353
354    private final void ensureCapacity(int minCapacity)
355    {
356        if (elements != null) {
357            if (capacity < minCapacity) {
358                byte[] newArray = new byte[minCapacity];
359                System.arraycopy(elements, 0, newArray, 0, capacity);
360                elements = newArray;
361                capacity = minCapacity;
362            }
363        } else {
364            // Displaced array.
365            Debug.assertTrue(array != null);
366            if (capacity < minCapacity ||
367                array.getTotalSize() - displacement < minCapacity)
368            {
369                // Copy array.
370                elements = new byte[minCapacity];
371                final int limit =
372                    Math.min(capacity, array.getTotalSize() - displacement);
373                for (int i = 0; i < limit; i++)
374                    elements[i] = coerceLispObjectToJavaByte(array.AREF(displacement + i));
375                capacity = minCapacity;
376                array = null;
377                displacement = 0;
378                isDisplaced = false;
379            }
380        }
381    }
382
383    @Override
384    public AbstractVector adjustArray(int newCapacity,
385                                       LispObject initialElement,
386                                       LispObject initialContents)
387
388    {
389        if (initialContents != null) {
390            // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE-
391            // ARRAY. In this case none of the original contents of array
392            // appears in the resulting array."
393            byte[] newElements = new byte[newCapacity];
394            if (initialContents.listp()) {
395                LispObject list = initialContents;
396                for (int i = 0; i < newCapacity; i++) {
397                    newElements[i] = coerceLispObjectToJavaByte(list.car());
398                    list = list.cdr();
399                }
400            } else if (initialContents.vectorp()) {
401                for (int i = 0; i < newCapacity; i++)
402                    newElements[i] = coerceLispObjectToJavaByte(initialContents.elt(i));
403            } else
404                error(new TypeError(initialContents, Symbol.SEQUENCE));
405            elements = newElements;
406        } else {
407            if (elements == null) {
408                // Displaced array. Copy existing elements.
409                elements = new byte[newCapacity];
410                final int limit = Math.min(capacity, newCapacity);
411                for (int i = 0; i < limit; i++)
412                    elements[i] = coerceLispObjectToJavaByte(array.AREF(displacement + i));
413            } else if (capacity != newCapacity) {
414                byte[] newElements = new byte[newCapacity];
415                System.arraycopy(elements, 0, newElements, 0,
416                                 Math.min(capacity, newCapacity));
417                elements = newElements;
418            }
419            // Initialize new elements (if aapplicable).
420            if (initialElement != null) {
421                byte b = coerceLispObjectToJavaByte(initialElement);
422                for (int i = capacity; i < newCapacity; i++)
423                    elements[i] = b;
424            }
425        }
426        capacity = newCapacity;
427        array = null;
428        displacement = 0;
429        isDisplaced = false;
430        return this;
431    }
432
433    @Override
434    public AbstractVector adjustArray(int newCapacity,
435                                       AbstractArray displacedTo,
436                                       int displacement)
437
438    {
439        capacity = newCapacity;
440        array = displacedTo;
441        this.displacement = displacement;
442        elements = null;
443        isDisplaced = true;
444        return this;
445    }
446}
Note: See TracBrowser for help on using the repository browser.