aboutsummaryrefslogtreecommitdiff
path: root/src/org/xbill/DNS/TypeBitmap.java
blob: 628cc35ea6eb4758872e628809c1136861f54bc2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 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));
}

}