blob: 628cc35ea6eb4758872e628809c1136861f54bc2 [file] [log] [blame]
// Copyright (c) 2004-2009 Brian Wellington (bwelling@xbill.org)
package org.xbill.DNS;
/**
* Routines for deal with the lists of types found in NSEC/NSEC3 records.
*
* @author Brian Wellington
*/
import java.io.*;
import java.util.*;
final class TypeBitmap implements Serializable {
private static final long serialVersionUID = -125354057735389003L;
private TreeSet types;
private
TypeBitmap() {
types = new TreeSet();
}
public
TypeBitmap(int [] array) {
this();
for (int i = 0; i < array.length; i++) {
Type.check(array[i]);
types.add(new Integer(array[i]));
}
}
public
TypeBitmap(DNSInput in) throws WireParseException {
this();
int lastbase = -1;
while (in.remaining() > 0) {
if (in.remaining() < 2)
throw new WireParseException
("invalid bitmap descriptor");
int mapbase = in.readU8();
if (mapbase < lastbase)
throw new WireParseException("invalid ordering");
int maplength = in.readU8();
if (maplength > in.remaining())
throw new WireParseException("invalid bitmap");
for (int i = 0; i < maplength; i++) {
int current = in.readU8();
if (current == 0)
continue;
for (int j = 0; j < 8; j++) {
if ((current & (1 << (7 - j))) == 0)
continue;
int typecode = mapbase * 256 + + i * 8 + j;
types.add(Mnemonic.toInteger(typecode));
}
}
}
}
public
TypeBitmap(Tokenizer st) throws IOException {
this();
while (true) {
Tokenizer.Token t = st.get();
if (!t.isString())
break;
int typecode = Type.value(t.value);
if (typecode < 0) {
throw st.exception("Invalid type: " + t.value);
}
types.add(Mnemonic.toInteger(typecode));
}
st.unget();
}
public int []
toArray() {
int [] array = new int[types.size()];
int n = 0;
for (Iterator it = types.iterator(); it.hasNext(); )
array[n++] = ((Integer)it.next()).intValue();
return array;
}
public String
toString() {
StringBuffer sb = new StringBuffer();
for (Iterator it = types.iterator(); it.hasNext(); ) {
int t = ((Integer)it.next()).intValue();
sb.append(Type.string(t));
if (it.hasNext())
sb.append(' ');
}
return sb.toString();
}
private static void
mapToWire(DNSOutput out, TreeSet map, int mapbase) {
int arraymax = (((Integer)map.last()).intValue()) & 0xFF;
int arraylength = (arraymax / 8) + 1;
int [] array = new int[arraylength];
out.writeU8(mapbase);
out.writeU8(arraylength);
for (Iterator it = map.iterator(); it.hasNext(); ) {
int typecode = ((Integer)it.next()).intValue();
array[(typecode & 0xFF) / 8] |= (1 << ( 7 - typecode % 8));
}
for (int j = 0; j < arraylength; j++)
out.writeU8(array[j]);
}
public void
toWire(DNSOutput out) {
if (types.size() == 0)
return;
int mapbase = -1;
TreeSet map = new TreeSet();
for (Iterator it = types.iterator(); it.hasNext(); ) {
int t = ((Integer)it.next()).intValue();
int base = t >> 8;
if (base != mapbase) {
if (map.size() > 0) {
mapToWire(out, map, mapbase);
map.clear();
}
mapbase = base;
}
map.add(new Integer(t));
}
mapToWire(out, map, mapbase);
}
public boolean
empty() {
return types.isEmpty();
}
public boolean
contains(int typecode) {
return types.contains(Mnemonic.toInteger(typecode));
}
}