Package com.redhat.ceylon.compiler.java.language

Source Code of com.redhat.ceylon.compiler.java.language.AbstractArrayIterable

package com.redhat.ceylon.compiler.java.language;

import ceylon.language.AssertionError;
import ceylon.language.Iterator;
import ceylon.language.Null;
import ceylon.language.emptyIterator_;
import ceylon.language.impl.BaseIterable;

import com.redhat.ceylon.compiler.java.metadata.Ignore;
import com.redhat.ceylon.compiler.java.runtime.model.TypeDescriptor;

/**
* Abstract implementation of {@link ceylon.language.Iterable}
* which iterates over an array (it could be an array of
* primitives, or an array of references, we don't know).
* Various methods (such as {@link #take(long)},
* {@link #skip(long)} and {@link #by(long)} are overridden
* so that they iterate over the same array instance.
*
* @param <Element> The element type
* @param <ArrayType> The array type
*/
public abstract class AbstractArrayIterable<Element, ArrayType>
extends BaseIterable<Element, ceylon.language.Null> {
   
    private final TypeDescriptor $reified$Element;
   
    /** The array (could be an array or primitives or references) */
    private final ArrayType array;
    /** The index where iteration starts */
    protected final int start;
    /** The step size of iteration */
    protected final int step;
    /** The number of elements in the iteration */
    protected final int len;

    @Override
    public TypeDescriptor $getType$() {
        return TypeDescriptor.klass(AbstractArrayIterable.class,
                this.$reified$Element);
    }

    @Ignore
    public AbstractArrayIterable(TypeDescriptor $reified$Element,
            ArrayType array, int length) {
        this($reified$Element, array, 0, length, 1);
    }
   
    /**
     * Constructor used internally via
     * {@link #newInstance(Object, int, int, int)}
     */
    @Ignore
    protected AbstractArrayIterable(TypeDescriptor $reified$Element,
            ArrayType array, int start, int len, int step) {
        super($reified$Element, Null.$TypeDescriptor$);
       
        if (start < 0) {
            throw new AssertionError("start must be non-negative");
        }
        if (len < 0) {
            throw new AssertionError("len must be non-negative");
        }
        if (step <= 0) {
            throw new AssertionError("step size must be greater than zero");
        }

        this.array = array;
        this.$reified$Element = $reified$Element;
        this.start = start;
        this.len = len;
        this.step = step;
    }
    /** Factory for creating a new instance */
    protected abstract AbstractArrayIterable<Element, ArrayType>
    newInstance(ArrayType array, int start, int len, int step);
   
    protected abstract Element get(ArrayType array, int index);

    @Ignore
    public ArrayType arrayValue() {
        return array;
    }

    @Override
    public boolean getEmpty() {
        return this.len == 0;
    }
   
    @Override
    public Element getFirst() {
        return this.getEmpty() ?
                null :
                get(this.array, this.start);
    }

    @Override
    public Element getLast() {
        return this.getEmpty() ?
                null :
                get(this.array, this.start+this.step*this.len-1);
    }

    @Override
    public AbstractArrayIterable<Element, ArrayType> getRest() {
        return getEmpty() ?
                this :
                newInstance(this.array,
                    this.start+this.step,
                    this.len-1,
                    this.step);
    }
   
    @Ignore
    @Override
    public long getSize() {
        return Math.max(0, this.len);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Iterator<? extends Element> iterator() {
        if (this.getEmpty()) {
            return (Iterator<? extends Element>)
                emptyIterator_.get_();
        }
        return new AbstractArrayIterator<Element>($reified$Element,
            start, len, step) {
            protected Element get(int index) {
                return AbstractArrayIterable.this.get(array, index);
            }
        };
    }

    @Override
    public boolean longerThan(long length) {
        return this.getSize() > length;
    }
   
    @Override
    public boolean shorterThan(long length) {
        return this.getSize() < length;
    }
   
    @Override
    public AbstractArrayIterable<Element, ArrayType>
    skip(long skip) {
        if (skip <= 0) {
            return this;
        }
        return newInstance(this.array,
                this.start+(int)skip*this.step,
                this.len-(int)skip,
                this.step);
    }
   
    @Override
    public AbstractArrayIterable<Element, ArrayType>
    take(long take) {
        if (take >= this.getSize()) {
            return this;
        }
        return newInstance(this.array,
                this.start,
                (int)take,
                this.step);
    }
   
    @Override
    public AbstractArrayIterable<Element, ArrayType>
    by(long step) {
        return newInstance(this.array,
                this.start,
                (int)((this.len+step-1)/step), //ceiling division
                this.step*(int)step);
    }

}
TOP

Related Classes of com.redhat.ceylon.compiler.java.language.AbstractArrayIterable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.