Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/jmx/snmp/BerEncoder.java
38924 views
/*1* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package com.sun.jmx.snmp;272829/**30* The <CODE>BerEncoder</CODE> class is used for encoding data using BER.31*32* A <CODE>BerEncoder</CODE> needs to be set up with a byte buffer. The encoded33* data are stored in this byte buffer.34* <P>35* NOTE : the buffer is filled from end to start. This means the caller36* needs to encode its data in the reverse order.37*38*39* <p><b>This API is a Sun Microsystems internal API and is subject40* to change without notice.</b></p>41*42* @since 1.543*/4445public class BerEncoder {4647/**48* Constructs a new encoder and attaches it to the specified byte string.49*50* @param b The byte string containing the encoded data.51*/5253public BerEncoder(byte b[]) {54bytes = b ;55start = b.length ;56stackTop = 0 ;57}585960/**61* Trim the encoding data and returns the length of the encoding.62*63* The encoder does backward encoding : so the bytes buffer is64* filled from end to start. The encoded data must be shift before65* the buffer can be used. This is the purpose of the <CODE>trim</CODE> method.66*67* After a call to the <CODE>trim</CODE> method, the encoder is reinitialized and <CODE>putXXX</CODE>68* overwrite any existing encoded data.69*70* @return The length of the encoded data.71*/7273public int trim() {74final int result = bytes.length - start ;7576// for (int i = start ; i < bytes.length ; i++) {77// bytes[i-start] = bytes[i] ;78// }79if (result > 0)80java.lang.System.arraycopy(bytes,start,bytes,0,result);8182start = bytes.length ;83stackTop = 0 ;8485return result ;86}8788/**89* Put an integer.90*91* @param v The integer to encode.92*/9394public void putInteger(int v) {95putInteger(v, IntegerTag) ;96}979899/**100* Put an integer with the specified tag.101*102* @param v The integer to encode.103* @param tag The tag to encode.104*/105106public void putInteger(int v, int tag) {107putIntegerValue(v) ;108putTag(tag) ;109}110111112113/**114* Put an integer expressed as a long.115*116* @param v The long to encode.117*/118119public void putInteger(long v) {120putInteger(v, IntegerTag) ;121}122123124/**125* Put an integer expressed as a long with the specified tag.126*127* @param v The long to encode128* @param tag The tag to encode.129*/130131public void putInteger(long v, int tag) {132putIntegerValue(v) ;133putTag(tag) ;134}135136137138/**139* Put an octet string.140*141* @param s The bytes to encode142*/143144public void putOctetString(byte[] s) {145putOctetString(s, OctetStringTag) ;146}147148149/**150* Put an octet string with a specified tag.151*152* @param s The bytes to encode153* @param tag The tag to encode.154*/155156public void putOctetString(byte[] s, int tag) {157putStringValue(s) ;158putTag(tag) ;159}160161162/**163* Put an object identifier.164*165* @param s The oid to encode.166*/167168public void putOid(long[] s) {169putOid(s, OidTag) ;170}171172173/**174* Put an object identifier with a specified tag.175*176* @param s The integer to encode.177* @param tag The tag to encode.178*/179180public void putOid(long[] s, int tag) {181putOidValue(s) ;182putTag(tag) ;183}184185186/**187* Put a <CODE>NULL</CODE> value.188*/189190public void putNull() {191putNull(NullTag) ;192}193194195/**196* Put a <CODE>NULL</CODE> value with a specified tag.197*198* @param tag The tag to encode.199*/200201public void putNull(int tag) {202putLength(0) ;203putTag(tag) ;204}205206207208/**209* Put an <CODE>ANY</CODE> value. In fact, this method does not encode anything.210* It simply copies the specified bytes into the encoding.211*212* @param s The encoding of the <CODE>ANY</CODE> value.213*/214215public void putAny(byte[] s) {216putAny(s, s.length) ;217}218219220/**221* Put an <CODE>ANY</CODE> value. Only the first <CODE>byteCount</CODE> are considered.222*223* @param s The encoding of the <CODE>ANY</CODE> value.224* @param byteCount The number of bytes of the encoding.225*/226227public void putAny(byte[] s, int byteCount) {228java.lang.System.arraycopy(s,0,bytes,start-byteCount,byteCount);229start -= byteCount;230// for (int i = byteCount - 1 ; i >= 0 ; i--) {231// bytes[--start] = s[i] ;232// }233}234235236/**237* Open a sequence.238* The encoder push the current position on its stack.239*/240241public void openSequence() {242stackBuf[stackTop++] = start ;243}244245246/**247* Close a sequence.248* The decode pull the stack to know the end of the current sequence.249*/250251public void closeSequence() {252closeSequence(SequenceTag) ;253}254255256/**257* Close a sequence with the specified tag.258*/259260public void closeSequence(int tag) {261final int end = stackBuf[--stackTop] ;262putLength(end - start) ;263putTag(tag) ;264}265266267//268// Some standard tags269//270public final static int BooleanTag = 1 ;271public final static int IntegerTag = 2 ;272public final static int OctetStringTag = 4 ;273public final static int NullTag = 5 ;274public final static int OidTag = 6 ;275public final static int SequenceTag = 0x30 ;276277278279280////////////////////////// PROTECTED ///////////////////////////////281282283284/**285* Put a tag and move the current position backward.286*287* @param tag The tag to encode.288*/289290protected final void putTag(int tag) {291if (tag < 256) {292bytes[--start] = (byte)tag ;293}294else {295while (tag != 0) {296bytes[--start] = (byte)(tag & 127) ;297tag = tag << 7 ;298}299}300}301302303/**304* Put a length and move the current position backward.305*306* @param length The length to encode.307*/308309protected final void putLength(final int length) {310if (length < 0) {311throw new IllegalArgumentException() ;312}313else if (length < 128) {314bytes[--start] = (byte)length ;315}316else if (length < 256) {317bytes[--start] = (byte)length ;318bytes[--start] = (byte)0x81 ;319}320else if (length < 65536) {321bytes[--start] = (byte)(length) ;322bytes[--start] = (byte)(length >> 8) ;323bytes[--start] = (byte)0x82 ;324}325else if (length < 16777126) {326bytes[--start] = (byte)(length) ;327bytes[--start] = (byte)(length >> 8) ;328bytes[--start] = (byte)(length >> 16) ;329bytes[--start] = (byte)0x83 ;330}331else {332bytes[--start] = (byte)(length) ;333bytes[--start] = (byte)(length >> 8) ;334bytes[--start] = (byte)(length >> 16) ;335bytes[--start] = (byte)(length >> 24) ;336bytes[--start] = (byte)0x84 ;337}338}339340341/**342* Put an integer value and move the current position backward.343*344* @param v The integer to encode.345*/346347protected final void putIntegerValue(int v) {348final int end = start ;349int mask = 0x7f800000 ;350int byteNeeded = 4 ;351if (v < 0) {352while (((mask & v) == mask) && (byteNeeded > 1)) {353mask = mask >> 8 ;354byteNeeded-- ;355}356}357else {358while (((mask & v) == 0) && (byteNeeded > 1)) {359mask = mask >> 8 ;360byteNeeded-- ;361}362}363for (int i = 0 ; i < byteNeeded ; i++) {364bytes[--start] = (byte)v ;365v = v >> 8 ;366}367putLength(end - start) ;368}369370371/**372* Put an integer value expressed as a long.373*374* @param v The integer to encode.375*/376377protected final void putIntegerValue(long v) {378final int end = start ;379long mask = 0x7f80000000000000L ;380int byteNeeded = 8 ;381if (v < 0) {382while (((mask & v) == mask) && (byteNeeded > 1)) {383mask = mask >> 8 ;384byteNeeded-- ;385}386}387else {388while (((mask & v) == 0) && (byteNeeded > 1)) {389mask = mask >> 8 ;390byteNeeded-- ;391}392}393for (int i = 0 ; i < byteNeeded ; i++) {394bytes[--start] = (byte)v ;395v = v >> 8 ;396}397putLength(end - start) ;398}399400401/**402* Put a byte string and move the current position backward.403*404* @param s The byte string to encode.405*/406407protected final void putStringValue(byte[] s) {408final int datalen = s.length;409java.lang.System.arraycopy(s,0,bytes,start-datalen,datalen);410start -= datalen;411// for (int i = s.length - 1 ; i >= 0 ; i--) {412// bytes[--start] = s[i] ;413// }414putLength(datalen) ;415}416417418419/**420* Put an oid and move the current position backward.421*422* @param s The oid to encode.423*/424425protected final void putOidValue(final long[] s) {426final int end = start ;427final int slength = s.length;428429// bugId 4641746: 0, 1, and 2 are legal values.430if ((slength < 2) || (s[0] > 2) || (s[1] >= 40)) {431throw new IllegalArgumentException() ;432}433for (int i = slength - 1 ; i >= 2 ; i--) {434long c = s[i] ;435if (c < 0) {436throw new IllegalArgumentException() ;437}438else if (c < 128) {439bytes[--start] = (byte)c ;440}441else {442bytes[--start] = (byte)(c & 127) ;443c = c >> 7 ;444while (c != 0) {445bytes[--start] = (byte)(c | 128) ;446c = c >> 7 ;447}448}449}450bytes[--start] = (byte)(s[0] * 40 + s[1]) ;451putLength(end - start) ;452}453454455//456// This is the byte array containing the encoding.457//458protected final byte bytes[];459460//461// This is the index of the first byte of the encoding.462// It is initialized to <CODE>bytes.length</CODE> and decrease each time463// an value is put in the encoder.464//465protected int start = -1 ;466467//468// This is the stack where end of sequences are kept.469// A value is computed and pushed in it each time the <CODE>openSequence</CODE> method470// is invoked.471// A value is pulled and checked each time the <CODE>closeSequence</CODE> method is called.472//473protected final int stackBuf[] = new int[200] ;474protected int stackTop = 0 ;475476}477478479