Package com.baulsupp.kolja.log.field

Source Code of com.baulsupp.kolja.log.field.MemorySparseIntField

package com.baulsupp.kolja.log.field;

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

import org.apache.commons.collections.primitives.IntList;

import com.baulsupp.kolja.log.util.IntRange;

// TODO easy optimisations by caching range start points
// TODO optimise by returning multiple next() results in array.

public class MemorySparseIntField implements SparseIntField {
  private List<MemoryIntField> knownFields = new ArrayList<MemoryIntField>(100);

  private IntRange totalRange = new IntRange();

  public MemorySparseIntField() {
  }

  public boolean isKnown(IntRange range) {
    MemoryIntField field = findEnclosingField(range);
    return field != null;
  }

  private MemoryIntField findEnclosingField(IntRange range) {
    assert (!range.isEmpty());

    for (MemoryIntField currentField : knownFields) {
      IntRange currentRange = currentField.getRange();

      if (currentRange.isCompletelyBefore(range))
        continue;

      if (currentRange.isCompletelyAfter(range))
        return null;

      if (range.isInclusiveSubsetOf(currentRange))
        return currentField;
    }

    return null;
  }

  public MemoryIntField findEnclosingField(int point) {
    assert (point >= 0);

    for (MemoryIntField currentField : knownFields) {
      IntRange currentRange = currentField.getRange();

      if (currentRange.isBefore(point))
        continue;

      if (currentRange.contains(point)) {
        return currentField;
      }

      if (currentRange.isAfter(point))
        return null;
    }

    return null;
  }

  public void add(MemoryIntField newField) {
    if (!isCompletelyUnknown(newField.getRange())) {
      throw new IllegalArgumentException("not completely unknown" + newField);
    }

    if (totalRange.isEmpty()) {
      knownFields.add(newField);
      totalRange = new IntRange(newField.getRange());
      return;
    }

    IntRange newRange = newField.getRange();

    if (newRange.getFrom() < totalRange.getFrom())
      totalRange.setFrom(newRange.getFrom());

    ListIterator<MemoryIntField> i = knownFields.listIterator();
    while (i.hasNext()) {
      MemoryIntField currentField = i.next();
      IntRange currentRange = currentField.getRange();

      boolean meets = currentRange.meets(newRange);

      if (!meets && newRange.isCompletelyBefore(currentRange)) {
        knownFields.add(i.previousIndex(), newField);
        return;
      }

      if (meets) {
        newField = newField.merge(currentField);
        newRange = newField.getRange();

        if (i.hasNext()) {
          MemoryIntField nextField = i.next();
          if (nextField.getRange().meets(newRange)) {
            newField = newField.merge(nextField);
            i.remove();
          }
          i.previous();
        }

        i.set(newField);

        return;
      }
    }

    knownFields.add(newField);
    totalRange.setTo(newRange.getTo());
  }

  private boolean isCompletelyUnknown(IntRange range) {
    IntRange[] unknown = listUnknownRanges(range);

    if (unknown.length != 1)
      return false;

    return range.equals(unknown[0]);
  }

  public IntRange[] listUnknownRanges(IntRange range) {
    ArrayList<IntRange> list = new ArrayList<IntRange>();

    // log.info("" + range);

    int from = range.getFrom();
    int to = range.getTo();

    for (MemoryIntField currentField : knownFields) {
      IntRange currentRange = currentField.getRange();

      // TODO check this doesn't break things
      if (currentRange.isBefore(range.getFrom())) {
        continue;
      }
      if (currentRange.isAfter(range.getTo())) {
        break;
      }

      if (currentRange.isAfter(from)) {
        // log.info("a from " + from + " to " + currentRange.getFrom());
        list.add(new IntRange(from, currentRange.getFrom()));
      }

      from = currentRange.getTo();

      if (from >= to)
        break;
    }

    if (from < to) {
      // log.info("b from " + from + " to " + to);
      list.add(new IntRange(from, to));
    }

    return list.toArray(new IntRange[list.size()]);
  }

  public IntRange getTotalRange() {
    return totalRange;
  }

  // TODO should this return null
  public IntList get(IntRange region) {
    MemoryIntField field = findEnclosingField(region);
    return field != null ? field.get(region) : null;
  }

  public String toString() {
    return knownFields.toString();
  }
}
TOP

Related Classes of com.baulsupp.kolja.log.field.MemorySparseIntField

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.