| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| package org.onosproject.xran.asn1lib.ber; |
| |
| import java.io.EOFException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Serializable; |
| |
| public class BerTag implements Serializable { |
| |
| public static final int UNIVERSAL_CLASS = 0x00; |
| public static final int APPLICATION_CLASS = 0x40; |
| public static final int CONTEXT_CLASS = 0x80; |
| public static final int PRIVATE_CLASS = 0xc0; |
| public static final int PRIMITIVE = 0x00; |
| public static final int CONSTRUCTED = 0x20; |
| public static final int BOOLEAN_TAG = 1; |
| public static final int INTEGER_TAG = 2; |
| public static final int BIT_STRING_TAG = 3; |
| public static final int OCTET_STRING_TAG = 4; |
| public static final int NULL_TAG = 5; |
| public static final int OBJECT_IDENTIFIER_TAG = 6; |
| public static final int OBJECT_DESCRIPTOR_TAG = 7; |
| public static final int REAL_TAG = 9; |
| public static final int ENUMERATED_TAG = 10; |
| public static final int EMBEDDED_PDV_TAG = 11; |
| public static final int UTF8_STRING_TAG = 12; |
| public static final int TIME_TAG = 14; |
| public static final int NUMERIC_STRING_TAG = 18; |
| public static final int PRINTABLE_STRING_TAG = 19; |
| public static final int TELETEX_STRING_TAG = 20; |
| public static final int VIDEOTEX_STRING_TAG = 21; |
| public static final int IA5_STRING_TAG = 22; |
| public static final int UTC_TIME_TAG = 23; |
| public static final int GENERALIZED_TIME_TAG = 24; |
| public static final int GRAPHIC_STRING_TAG = 25; |
| public static final int VISIBLE_STRING_TAG = 26; |
| public static final int GENERAL_STRING_TAG = 27; |
| public static final int UNIVERSAL_STRING_TAG = 28; |
| public static final int BMP_STRING_TAG = 30; |
| public static final int DATE_TAG = 31; |
| public static final int TIME_OF_DAY_TAG = 32; |
| public static final int DATE_TIME_TAG = 33; |
| public static final int DURATION_TAG = 34; |
| private static final long serialVersionUID = 1L; |
| public byte[] tagBytes = null; |
| public int tagClass; |
| public int primitive; |
| public int tagNumber; |
| |
| public BerTag(int identifierClass, int primitive, int tagNumber) { |
| this.tagClass = identifierClass; |
| this.primitive = primitive; |
| this.tagNumber = tagNumber; |
| code(); |
| } |
| |
| public BerTag() { |
| } |
| |
| private void code() { |
| if (tagNumber < 31) { |
| tagBytes = new byte[1]; |
| tagBytes[0] = (byte) (tagClass | primitive | tagNumber); |
| } else { |
| int tagLength = 1; |
| while (tagNumber > (Math.pow(2, (7 * tagLength)) - 1)) { |
| tagLength++; |
| } |
| |
| tagBytes = new byte[1 + tagLength]; |
| tagBytes[0] = (byte) (tagClass | primitive | 31); |
| |
| for (int j = 1; j <= (tagLength - 1); j++) { |
| tagBytes[j] = (byte) (((tagNumber >> (7 * (tagLength - j))) & 0xff) | 0x80); |
| } |
| |
| tagBytes[tagLength] = (byte) (tagNumber & 0x7f); |
| |
| } |
| } |
| |
| public int encode(BerByteArrayOutputStream os) throws IOException { |
| if (tagBytes == null) { |
| code(); |
| } |
| for (int i = (tagBytes.length - 1); i >= 0; i--) { |
| os.write(tagBytes[i]); |
| } |
| return tagBytes.length; |
| } |
| |
| public int decode(InputStream is) throws IOException { |
| int nextByte = is.read(); |
| if (nextByte == -1) { |
| throw new EOFException("Unexpected end of input stream."); |
| } |
| |
| tagClass = nextByte & 0xC0; |
| primitive = nextByte & 0x20; |
| tagNumber = nextByte & 0x1f; |
| |
| int codeLength = 1; |
| |
| if (tagNumber == 0x1f) { |
| tagNumber = 0; |
| |
| int counter = 0; |
| |
| do { |
| nextByte = is.read(); |
| if (nextByte == -1) { |
| throw new EOFException("Unexpected end of input stream."); |
| } |
| |
| codeLength++; |
| if (counter >= 6) { |
| throw new IOException("Invalid Tag"); |
| } |
| tagNumber = tagNumber << 7; |
| tagNumber |= (nextByte & 0x7f); |
| counter++; |
| } while ((nextByte & 0x80) == 0x80); |
| |
| } |
| |
| return codeLength; |
| } |
| |
| /** |
| * Decodes the Identifier from the ByteArrayInputStream and throws an Exception if it is not equal to itself. |
| * Returns the number of bytes read from the InputStream. |
| * |
| * @param is the input stream to read the identifier from. |
| * @return the length of the identifier read. |
| * @throws IOException if an exception occurs reading the identifier from the stream. |
| */ |
| public int decodeAndCheck(InputStream is) throws IOException { |
| |
| for (Byte identifierByte : tagBytes) { |
| int nextByte = is.read(); |
| if (nextByte == -1) { |
| throw new EOFException("Unexpected end of input stream."); |
| } |
| |
| if (nextByte != (identifierByte & 0xff)) { |
| throw new IOException("Identifier does not match!"); |
| } |
| } |
| return tagBytes.length; |
| } |
| |
| public boolean equals(int identifierClass, int primitive, int tagNumber) { |
| return (this.tagNumber == tagNumber && this.tagClass == identifierClass && this.primitive == primitive); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (!(obj instanceof BerTag)) { |
| return false; |
| } |
| if (obj == this) { |
| return true; |
| } |
| BerTag berIdentifier = (BerTag) obj; |
| return (tagNumber == berIdentifier.tagNumber && tagClass == berIdentifier.tagClass |
| && primitive == berIdentifier.primitive); |
| } |
| |
| @Override |
| public int hashCode() { |
| int hash = 17; |
| hash = hash * 31 + tagNumber; |
| hash = hash * 31 + tagClass; |
| hash = hash * 31 + primitive; |
| return hash; |
| } |
| |
| @Override |
| public String toString() { |
| return "identifier class: " + tagClass + ", primitive: " + primitive + ", tag number: " + tagNumber; |
| } |
| |
| } |