// ex: se sts=4 sw=4 expandtab:
/*
* Yeti core library.
*
* Copyright (c) 2009-2013 Madis Janson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package yeti.lang;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.Arrays;
public class PArray extends LList {
int start;
final int length;
final Object array;
private boolean iter;
PArray(int start, int length, Object array) {
super(null, null);
this.start = start;
this.length = length;
this.array = array;
}
public Object first() {
return new IntNum(Array.getLong(array, start));
}
public AIter next() {
if (iter)
return ++start >= length ? null : this;
PArray rest = (PArray) rest();
if (rest != null)
rest.iter = true;
return rest;
}
public AIter dup() {
PArray slice = slice(start, length);
slice.iter = true;
return slice;
}
PArray slice(int start, int length) {
return new PArray(start, length, array);
}
public AList rest() {
int n;
return (n = start + 1) >= length ? null : slice(n, length);
}
public AList take(int from, int count) {
if (from < 0)
from = 0;
from += start;
if (count < 0 || (count += from) > length)
count = length;
if (from >= count)
return null;
if (from == start && count == length)
return this;
return slice(from, count);
}
public long length() {
return length - start;
}
public static AList wrap(byte[] array) {
return array == null || array.length == 0
? null : new ByteArray(0, array.length, array);
}
public static AList wrap(short[] array) {
return array == null || array.length == 0
? null : new PArray(0, array.length, array);
}
public static AList wrap(int[] array) {
return array == null || array.length == 0
? null : new PArray(0, array.length, array);
}
public static AList wrap(long[] array) {
return array == null || array.length == 0
? null : new PArray(0, array.length, array);
}
public static AList wrap(float[] array) {
return array == null || array.length == 0
? null : new FloatArray(0, array.length, array);
}
public static AList wrap(double[] array) {
return array == null || array.length == 0
? null : new FloatArray(0, array.length, array);
}
public static AList wrap(boolean[] array) {
return array == null || array.length == 0
? null : new BooleanArray(0, array.length, array);
}
public static AList wrap(char[] array) {
return array == null || array.length == 0
? null : new CharArray(0, array.length, array);
}
}
final class CharArray extends PArray {
CharArray(int start, int length, Object array) {
super(start, length, array);
}
public Object first() {
return new String((char[]) array, start, 1);
}
PArray slice(int start, int length) {
return new CharArray(start, length, array);
}
}
final class FloatArray extends PArray {
FloatArray(int start, int length, Object array) {
super(start, length, array);
}
public Object first() {
return new FloatNum(Array.getDouble(array, start));
}
PArray slice(int start, int length) {
return new FloatArray(start, length, array);
}
}
final class BooleanArray extends PArray {
BooleanArray(int start, int length, Object array) {
super(start, length, array);
}
public Object first() {
return ((boolean[]) array)[start] ? Boolean.TRUE : Boolean.FALSE;
}
PArray slice(int start, int length) {
return new BooleanArray(start, length, array);
}
}
final class ByteArray extends PArray {
private final byte[] a;
ByteArray(int start, int length, byte[] a) {
super(start, length, a);
this.a = a;
}
public Object first() {
return new IntNum(a[start] & 0xff);
}
PArray slice(int start, int length) {
return new ByteArray(start, length, a);
}
public void forEach(Object f_) {
Fun f = (Fun) f_;
for (int i = start, e = length; i < e; ++i)
f.apply(new IntNum(a[i]));
}
public Object fold(Fun f_, Object v) {
Fun f = (Fun) f_;
for (int i = start, e = length; i < e; ++i)
v = f.apply(v, new IntNum(a[i]));
return v;
}
public AList reverse() {
byte[] tmp = new byte[length - start];
for (int i = 0; i < tmp.length; ++i)
tmp[tmp.length - i] = a[i + start];
return new ByteArray(0, tmp.length, tmp);
}
public Num index(Object v) {
int b = ((IntNum) v).intValue();
for (int i = start, e = length; i < e; ++i)
if (a[i] == b)
return new IntNum(i - start);
return null;
}
public AList find(Fun pred) {
for (int i = start, e = length; i < e; ++i)
if (pred.apply(new IntNum(a[i])) == Boolean.TRUE)
return new ByteArray(i, e - i, a);
return null;
}
public AList sort() {
byte[] tmp = new byte[length - start];
System.arraycopy(a, start, tmp, 0, tmp.length);
Arrays.sort(tmp);
return new ByteArray(0, tmp.length, tmp);
}
public long length() {
return length - start;
}
public Object copy() {
byte[] tmp = new byte[length - start];
System.arraycopy(a, start, tmp, 0, tmp.length);
return new ByteArray(0, tmp.length, tmp);
}
AIter write(OutputStream out) throws IOException {
out.write(a, start, length - start);
return null;
}
public AList map(Fun f) {
return smap(f);
}
public AList sort(Fun isLess) {
return new MList(this).asort(isLess);
}
}