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