// ex: se sts=4 sw=4 expandtab:
/**
* Yeti core library - with structure implementation.
*
* Copyright (c) 2010 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.Serializable;
public class WithStruct extends AStruct {
private final Object[] values;
private final int[] index;
private final int size;
public WithStruct(Struct src, Struct override,
String[] names, boolean allowNew) {
super(null, null);
int ac = src.count(), bc = override.count();
index = new int[(allowNew ? ac + names.length : ac) << 1];
values = new Object[index.length];
int i = 0, j = -1, k = 0, n = 0;
String an = src.name(0), bn;
while ((bn = override.name(++j)) != names[0]);
while (an != null || bn != null) {
int c = an == null ? 1 : bn == null ? -1 : an.compareTo(bn);
if (c >= 0) { // src >= override - take override
values[n] = bn;
values[n + 1] = override.ref(j, index, n);
if (++k >= names.length)
bn = null;
else
while ((bn = override.name(++j)) != names[k]);
} else { // src < override - take super
values[n] = an;
values[n + 1] = src.ref(i, index, n);
}
if (c <= 0)
an = ++i >= ac ? null : src.name(i);
n += 2;
}
size = n >>> 1;
}
public int count() {
return size;
}
public String name(int i) {
return values[i << 1].toString();
}
public String eqName(int i) {
return index[(i <<= 1) + 1] == 0 ? values[i].toString() : "";
}
public Object get(int i) {
return values[(i << 1) + 1];
}
public Object get(String field) {
int id, i = -2;
while (values[i += 2] != field);
if ((id = index[i]) < 0)
return values[i + 1];
return ((Struct) values[i + 1]).get(id);
}
public void set(String field, Object value) {
int i = -2;
while (values[i += 2] != field);
((Struct) values[i + 1]).set(field, value);
}
public Object ref(int field, int[] index, int at) {
index[at] = this.index[field <<= 1];
index[at + 1] = this.index[++field];
return values[field];
}
}