blob: 9ebfe1481bfefac91e8555826545a5807be492d0 [file] [log] [blame]
slowr60d4d102017-08-16 18:33:58 -07001/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4package org.onosproject.xran.codecs.ber.types;
5
6import com.fasterxml.jackson.annotation.JsonIgnore;
7import com.fasterxml.jackson.annotation.JsonValue;
8import org.onosproject.xran.codecs.ber.BerByteArrayOutputStream;
9import org.onosproject.xran.codecs.ber.BerLength;
10import org.onosproject.xran.codecs.ber.BerTag;
11import org.onosproject.xran.codecs.ber.internal.Util;
12import org.onosproject.xran.codecs.util.HexConverter;
13
14import javax.xml.bind.DatatypeConverter;
15import java.io.EOFException;
16import java.io.IOException;
17import java.io.InputStream;
18import java.io.Serializable;
19
20public class BerBitString implements Serializable {
21
22 public final static BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.BIT_STRING_TAG);
23 private static final long serialVersionUID = 1L;
24 @JsonIgnore
25 public byte[] code = null;
26
27 public byte[] value;
28 public int numBits;
29
30 public BerBitString() {
31 }
32
33 public BerBitString(byte[] value, int numBits) {
34
35 if (value == null) {
36 throw new NullPointerException("value cannot be null");
37 }
38 if (numBits < 0) {
39 throw new IllegalArgumentException("numBits cannot be negative.");
40 }
41 if (numBits > (value.length * 8)) {
42 throw new IllegalArgumentException("'value' is too short to hold all bits.");
43 }
44
45 this.value = value;
46 this.numBits = numBits;
47
48 }
49
50 public BerBitString(byte[] code) {
51 this.code = code;
52 }
53
54 public int encode(BerByteArrayOutputStream os) throws IOException {
55 return encode(os, true);
56 }
57
58 public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
59
60 if (code != null) {
61 for (int i = code.length - 1; i >= 0; i--) {
62 os.write(code[i]);
63 }
64 if (withTag) {
65 return tag.encode(os) + code.length;
66 }
67 return code.length;
68 }
69
70 for (int i = (value.length - 1); i >= 0; i--) {
71 os.write(value[i]);
72 }
73 os.write(value.length * 8 - numBits);
74
75 int codeLength = value.length + 1;
76
77 codeLength += BerLength.encodeLength(os, codeLength);
78
79 if (withTag) {
80 codeLength += tag.encode(os);
81 }
82
83 return codeLength;
84 }
85
86 public int decode(InputStream is) throws IOException {
87 return decode(is, true);
88 }
89
90 public int decode(InputStream is, boolean withTag) throws IOException {
91 // could be encoded in primitiv and constructed mode
92 // only primitiv mode is implemented
93
94 int codeLength = 0;
95
96 if (withTag) {
97 codeLength += tag.decodeAndCheck(is);
98 }
99
100 BerLength length = new BerLength();
101 codeLength += length.decode(is);
102
103 value = new byte[length.val - 1];
104
105 int unusedBits = is.read();
106 if (unusedBits == -1) {
107 throw new EOFException("Unexpected end of input stream.");
108 }
109 if (unusedBits > 7) {
110 throw new IOException(
111 "Number of unused bits in bit string expected to be less than 8 but is: " + unusedBits);
112 }
113
114 numBits = (value.length * 8) - unusedBits;
115
116 if (value.length > 0) {
117 Util.readFully(is, value);
118 }
119
120 codeLength += value.length + 1;
121
122 return codeLength;
123
124 }
125
126 @JsonValue
127 @Override
128 public String toString() {
129 return DatatypeConverter.printHexBinary(value);
130 }
131}