blob: f4920d05450093cad7305514adbbb59b7015ee1e [file] [log] [blame]
package com.googlecode.prolog_cafe.lang;
import com.googlecode.prolog_cafe.exceptions.SystemException;
import java.util.LinkedList;
/**
* Internal database for dynamic predicates.<br>
*
* @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
* @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
* @version 1.1
*/
public class InternalDatabase {
protected static final int DEFAULT_SIZE = 100000;
/** Maximum size of enties. Initial size is <code>100000</code>. */
protected int maxContents;
/** An array of <code>Term</code> entries. */
protected Term[] buffer;
/* For GC */
/** A list of reusable entry indices. */
protected LinkedList<Integer> reusableIndices;
/** the top index of this <code>InternalDatabase</code>. */
protected int top;
/** Constructs a new internal dababase. */
public InternalDatabase() {
this(DEFAULT_SIZE);
}
/** Constructs a new internal dababase with the given size. */
public InternalDatabase(int n) {
maxContents = n;
buffer = new Term[Math.min(maxContents, DEFAULT_SIZE)];
reusableIndices = new LinkedList<>();
top = -1;
}
InternalDatabase(Prolog engine, InternalDatabase src, boolean deepCopy) {
maxContents = src.maxContents;
buffer = new Term[src.buffer.length];
reusableIndices = new LinkedList<>(src.reusableIndices);
top = src.top;
if (deepCopy) {
for (int i = 0; i <= top; i++) {
Term s = src.buffer[i];
if (s != null) {
buffer[i] = s.copy(engine);
}
}
} else if (0 <= top) {
System.arraycopy(src.buffer, 0, buffer, 0, top + 1);
}
}
/** Inserts an entry to this <code>InternalDatabase</code>. */
public int insert(Term t) {
try {
if (reusableIndices.isEmpty()) {
buffer[++top] = t;
return top;
} else {
int i = reusableIndices.remove();
buffer[i] = t;
return i;
}
} catch (ArrayIndexOutOfBoundsException e) {
if (maxContents <= buffer.length)
throw new SystemException("internal database capacity reached");
int len = buffer.length;
Term[] new_buffer = new Term[Math.min(len+10000, maxContents)];
for(int i=0; i<len; i++){
new_buffer[i] = buffer[i];
}
buffer = new_buffer;
buffer[top] = t;
return top;
}
}
/** Returns an entry with the given index from this <code>InternalDatabase</code>. */
public Term get(int i) {
return buffer[i];
}
/** Erases an entry with the given index from this <code>InternalDatabase</code>. */
public Term erase(int i) {
Term t = buffer[i];
buffer[i] = null;
reusableIndices.add(i);
return t;
}
/** Tests if this has no entry. */
private boolean empty() {
return top == -1;
}
/** Shows the contents of this <code>InternalDatabase</code>. */
public void show() {
if (empty())
System.out.println("{internal database is empty!}");
System.out.println("{reusable indices: " + reusableIndices.toString() + "}");
for (int i=0; i<=top; i++) {
System.out.print("internal database[" + i + "]: ");
System.out.println(buffer[i]);
}
}
}