1package org.bouncycastle.asn1;
2
3import java.io.FilterOutputStream;
4import java.io.IOException;
5import java.io.OutputStream;
6
7public class DEROutputStream
8    extends FilterOutputStream implements DERTags
9{
10    public DEROutputStream(
11        OutputStream    os)
12    {
13        super(os);
14    }
15
16    private void writeLength(
17        int length)
18        throws IOException
19    {
20        if (length > 127)
21        {
22            int size = 1;
23            int val = length;
24
25            while ((val >>>= 8) != 0)
26            {
27                size++;
28            }
29
30            write((byte)(size | 0x80));
31
32            for (int i = (size - 1) * 8; i >= 0; i -= 8)
33            {
34                write((byte)(length >> i));
35            }
36        }
37        else
38        {
39            write((byte)length);
40        }
41    }
42
43    void writeEncoded(
44        int     tag,
45        byte[]  bytes)
46        throws IOException
47    {
48        write(tag);
49        writeLength(bytes.length);
50        write(bytes);
51    }
52
53    void writeTag(int flags, int tagNo)
54        throws IOException
55    {
56        if (tagNo < 31)
57        {
58            write(flags | tagNo);
59        }
60        else
61        {
62            write(flags | 0x1f);
63            if (tagNo < 128)
64            {
65                write(tagNo);
66            }
67            else
68            {
69                byte[] stack = new byte[5];
70                int pos = stack.length;
71
72                stack[--pos] = (byte)(tagNo & 0x7F);
73
74                do
75                {
76                    tagNo >>= 7;
77                    stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
78                }
79                while (tagNo > 127);
80
81                write(stack, pos, stack.length - pos);
82            }
83        }
84    }
85
86    void writeEncoded(int flags, int tagNo, byte[] bytes)
87        throws IOException
88    {
89        writeTag(flags, tagNo);
90        writeLength(bytes.length);
91        write(bytes);
92    }
93
94    protected void writeNull()
95        throws IOException
96    {
97        write(NULL);
98        write(0x00);
99    }
100
101    public void write(byte[] buf)
102        throws IOException
103    {
104        out.write(buf, 0, buf.length);
105    }
106
107    public void write(byte[] buf, int offSet, int len)
108        throws IOException
109    {
110        out.write(buf, offSet, len);
111    }
112
113    public void writeObject(
114        Object    obj)
115        throws IOException
116    {
117        if (obj == null)
118        {
119            writeNull();
120        }
121        else if (obj instanceof DERObject)
122        {
123            ((DERObject)obj).encode(this);
124        }
125        else if (obj instanceof DEREncodable)
126        {
127            ((DEREncodable)obj).getDERObject().encode(this);
128        }
129        else
130        {
131            throw new IOException("object not DEREncodable");
132        }
133    }
134}
135