All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.couchbase.lite.internal.fleece.MArray Maven / Gradle / Ivy

//
// Copyright (c) 2020, 2017 Couchbase, Inc All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.couchbase.lite.internal.fleece;

import java.util.ArrayList;
import java.util.List;


public class MArray extends MCollection {
    private List values = new ArrayList<>();

    private FLArray baseArray;

    public void initInSlot(MValue mv, MCollection parent) {
        initInSlot(mv, parent, parent != null && parent.hasMutableChildren());
    }

    @Override
    protected void initInSlot(MValue mv, MCollection parent, boolean isMutable) {
        super.initInSlot(mv, parent, isMutable);
        if (baseArray != null) { throw new IllegalStateException("base array is not null."); }

        final FLValue value = mv.getValue();
        if (value != null) {
            baseArray = value.asFLArray();
            resize(baseArray.count());
        }
        else {
            baseArray = null;
            resize(0);
        }
    }

    public void initAsCopyOf(MArray array, boolean isMutable) {
        super.initAsCopyOf(array, isMutable);
        baseArray = array != null ? array.getBaseArray() : null;
        values = array != null ? new ArrayList<>(array.values) : new ArrayList<>();
    }

    /* Properties */

    public long count() {
        return values.size();
    }


    public FLArray getBaseArray() {
        return baseArray;
    }

    /* Public Methods */

    /**
     * Returns a reference to the MValue of the item at the given index.
     * If the index is out of range, returns an empty MValue.
     */
    public MValue get(long index) {
        if (index < 0 || index >= values.size()) { return MValue.EMPTY; }

        MValue value = values.get((int) index);
        if (value.isEmpty() && (baseArray != null)) {
            value = new MValue(baseArray.get(index));
            values.set((int) index, value);
        }

        return value;
    }

    public boolean set(long index, Object value) {
        if (!isMutable()) { throw new IllegalStateException("Cannot set items in a non-mutable MArray"); }

        if (index < 0 || index >= count()) { return false; }

        mutate();
        values.set((int) index, new MValue(value));
        return true;
    }

    public boolean insert(long index, Object value) {
        if (!isMutable()) { throw new IllegalStateException("Cannot insert items in a non-mutable MArray"); }

        if (index < 0 || index > count()) { return false; }

        if (index < count()) { populateValues(); }

        mutate();
        values.add((int) index, new MValue(value));
        return true;
    }

    public boolean append(Object value) {
        return insert(count(), value);
    }

    public boolean remove(long start, long num) {
        if (!isMutable()) { throw new IllegalStateException("Cannot remove items in a non-mutable MArray"); }

        final long end = start + num;
        if (end <= start) { return end == start; }

        final long count = count();
        if (end > count) { return false; }

        if (end < count) { populateValues(); }

        mutate();
        values.subList((int) start, (int) end).clear();
        return true;
    }

    public boolean remove(long index) {
        return remove(index, 1);
    }

    public boolean clear() {
        if (!isMutable()) { throw new IllegalStateException("Cannot clear items in a non-mutable MArray"); }

        if (values.isEmpty()) { return true; }

        mutate();
        values.clear();
        return true;
    }

    /* Private Methods */

    void resize(long newSize) {
        final int count = values.size();
        if (newSize < count) { values.subList((int) newSize, count).clear(); }
        else if (newSize > count) {
            for (int i = 0; i < newSize - count; i++) { values.add(MValue.EMPTY); }
        }
    }

    void populateValues() {
        if (baseArray == null) { return; }

        final int size = values.size();
        for (int i = 0; i < size; i++) {
            if (values.get(i).isEmpty()) {
                values.set(i, new MValue(baseArray.get(i)));
            }
        }
    }

    public void encodeTo(FLEncoder enc) {
        if (!isMutated()) {
            if (baseArray == null) {
                enc.beginArray(0);
                enc.endArray();
            }
            else { enc.writeValue(baseArray); }
        }
        else {
            enc.beginArray(count());
            long i = 0;
            for (MValue value : values) {
                if (value.isEmpty()) { enc.writeValue(baseArray.get(i)); }
                else { value.encodeTo(enc); }
                i++;
            }
            enc.endArray();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy