blob: 29a8f68d507459b6e5da891621306297b00b9541 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS;
4
5/**
6 * A class for rendering DNS messages.
7 *
8 * @author Brian Wellington
9 */
10
11
12public class DNSOutput {
13
14private byte [] array;
15private int pos;
16private int saved_pos;
17
18/**
19 * Create a new DNSOutput with a specified size.
20 * @param size The initial size
21 */
22public
23DNSOutput(int size) {
24 array = new byte[size];
25 pos = 0;
26 saved_pos = -1;
27}
28
29/**
30 * Create a new DNSOutput
31 */
32public
33DNSOutput() {
34 this(32);
35}
36
37/**
38 * Returns the current position.
39 */
40public int
41current() {
42 return pos;
43}
44
45private void
46check(long val, int bits) {
47 long max = 1;
48 max <<= bits;
49 if (val < 0 || val > max) {
50 throw new IllegalArgumentException(val + " out of range for " +
51 bits + " bit value");
52 }
53}
54
55private void
56need(int n) {
57 if (array.length - pos >= n) {
58 return;
59 }
60 int newsize = array.length * 2;
61 if (newsize < pos + n) {
62 newsize = pos + n;
63 }
64 byte [] newarray = new byte[newsize];
65 System.arraycopy(array, 0, newarray, 0, pos);
66 array = newarray;
67}
68
69/**
70 * Resets the current position of the output stream to the specified index.
71 * @param index The new current position.
72 * @throws IllegalArgumentException The index is not within the output.
73 */
74public void
75jump(int index) {
76 if (index > pos) {
77 throw new IllegalArgumentException("cannot jump past " +
78 "end of data");
79 }
80 pos = index;
81}
82
83/**
84 * Saves the current state of the output stream.
85 * @throws IllegalArgumentException The index is not within the output.
86 */
87public void
88save() {
89 saved_pos = pos;
90}
91
92/**
93 * Restores the input stream to its state before the call to {@link #save}.
94 */
95public void
96restore() {
97 if (saved_pos < 0) {
98 throw new IllegalStateException("no previous state");
99 }
100 pos = saved_pos;
101 saved_pos = -1;
102}
103
104/**
105 * Writes an unsigned 8 bit value to the stream.
106 * @param val The value to be written
107 */
108public void
109writeU8(int val) {
110 check(val, 8);
111 need(1);
112 array[pos++] = (byte)(val & 0xFF);
113}
114
115/**
116 * Writes an unsigned 16 bit value to the stream.
117 * @param val The value to be written
118 */
119public void
120writeU16(int val) {
121 check(val, 16);
122 need(2);
123 array[pos++] = (byte)((val >>> 8) & 0xFF);
124 array[pos++] = (byte)(val & 0xFF);
125}
126
127/**
128 * Writes an unsigned 16 bit value to the specified position in the stream.
129 * @param val The value to be written
130 * @param where The position to write the value.
131 */
132public void
133writeU16At(int val, int where) {
134 check(val, 16);
135 if (where > pos - 2)
136 throw new IllegalArgumentException("cannot write past " +
137 "end of data");
138 array[where++] = (byte)((val >>> 8) & 0xFF);
139 array[where++] = (byte)(val & 0xFF);
140}
141
142/**
143 * Writes an unsigned 32 bit value to the stream.
144 * @param val The value to be written
145 */
146public void
147writeU32(long val) {
148 check(val, 32);
149 need(4);
150 array[pos++] = (byte)((val >>> 24) & 0xFF);
151 array[pos++] = (byte)((val >>> 16) & 0xFF);
152 array[pos++] = (byte)((val >>> 8) & 0xFF);
153 array[pos++] = (byte)(val & 0xFF);
154}
155
156/**
157 * Writes a byte array to the stream.
158 * @param b The array to write.
159 * @param off The offset of the array to start copying data from.
160 * @param len The number of bytes to write.
161 */
162public void
163writeByteArray(byte [] b, int off, int len) {
164 need(len);
165 System.arraycopy(b, off, array, pos, len);
166 pos += len;
167}
168
169/**
170 * Writes a byte array to the stream.
171 * @param b The array to write.
172 */
173public void
174writeByteArray(byte [] b) {
175 writeByteArray(b, 0, b.length);
176}
177
178/**
179 * Writes a counted string from the stream. A counted string is a one byte
180 * value indicating string length, followed by bytes of data.
181 * @param s The string to write.
182 */
183public void
184writeCountedString(byte [] s) {
185 if (s.length > 0xFF) {
186 throw new IllegalArgumentException("Invalid counted string");
187 }
188 need(1 + s.length);
189 array[pos++] = (byte)(s.length & 0xFF);
190 writeByteArray(s, 0, s.length);
191}
192
193/**
194 * Returns a byte array containing the current contents of the stream.
195 */
196public byte []
197toByteArray() {
198 byte [] out = new byte[pos];
199 System.arraycopy(array, 0, out, 0, pos);
200 return out;
201}
202
203}