001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.asn1.ber.tlv; 021 022 023import org.apache.directory.api.i18n.I18n; 024import org.apache.directory.api.util.Strings; 025 026 027/** 028 * Parse and decode an Integer value. 029 * 030 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 031 */ 032public final class IntegerDecoder 033{ 034 /** A mask used to get only the necessary bytes */ 035 private static final int[] MASK = new int[] 036 { 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF }; 037 038 039 private IntegerDecoder() 040 { 041 } 042 043 044 /** 045 * Parse a byte buffer and send back an integer, controlling that this number 046 * is in a specified interval. 047 * 048 * @param value The Value containing the byte[] to parse 049 * @param min Lowest value allowed, included 050 * @param max Highest value allowed, included 051 * @return An integer 052 * @throws IntegerDecoderException Thrown if the byte[] does not contains an integer 053 */ 054 public static int parse( BerValue value, int min, int max ) throws IntegerDecoderException 055 { 056 int result = parseInt( value ); 057 058 if ( ( result >= min ) && ( result <= max ) ) 059 { 060 return result; 061 } 062 else 063 { 064 throw new IntegerDecoderException( I18n.err( I18n.ERR_01306_VALUE_NOT_IN_RANGE, min, max ) ); 065 } 066 } 067 068 069 /** 070 * Parse a byte buffer and send back an integer 071 * 072 * @param value The byte buffer to parse 073 * @return An integer 074 * @throws IntegerDecoderException Thrown if the byte stream does not contains an integer 075 */ 076 public static int parse( BerValue value ) throws IntegerDecoderException 077 { 078 return parseInt( value ); 079 } 080 081 082 /** 083 * Helper method used to parse the integer. We don't check any minimal or maximal 084 * bound. 085 * An BER encoded int can be either positive or negative. It uses the minimum 086 * number of byts necessary to encode the value. The high order bit gives the 087 * sign of the integer : if it's 1, then it's a negative value, otherwise it's 088 * a positive value. Integer with a high order bit set to 1 but prefixed by a 0x00 089 * are positive. If the integer is negative, then the 2 complement value is 090 * stored<br> 091 * Here are a few samples : 092 * <ul> 093 * <li>0x02 0x01 0x00 : integer 0</li> 094 * <li>0x02 0x01 0x01 : integer 1</li> 095 * <li>0x02 0x01 0x7F : integer 127</li> 096 * <li>0x02 0x01 0x80 : integer -128</li> 097 * <li>0x02 0x01 0x81 : integer -127</li> 098 * <li>0x02 0x01 0xFF : integer -1</li> 099 * <li>0x02 0x02 0x00 0x80 : integer 128</li> 100 * <li>0x02 0x02 0x00 0x81 : integer 129</li> 101 * <li>0x02 0x02 0x00 0xFF : integer 255</li> 102 * </ul> 103 * and so on... 104 * 105 * @param value the BER PDU to parse 106 * @return The decoded value 107 * @exception IntegerDecoderException If the BER contains an invalid integer value 108 */ 109 private static int parseInt( BerValue value ) throws IntegerDecoderException 110 { 111 int result = 0; 112 113 byte[] bytes = value.getData(); 114 115 if ( Strings.isEmpty( bytes ) ) 116 { 117 throw new IntegerDecoderException( I18n.err( I18n.ERR_01304_0_BYTES_LONG_INTEGER ) ); 118 } 119 120 boolean positive = true; 121 122 switch ( bytes.length ) 123 { 124 case 5: 125 if ( bytes[0] == 0x00 ) 126 { 127 if ( ( bytes[1] & ( byte ) 0x80 ) != ( byte ) 0x80 ) 128 { 129 throw new IntegerDecoderException( I18n.err( I18n.ERR_01304_0_BYTES_LONG_INTEGER ) ); 130 } 131 132 result = bytes[1] & 0x00FF; 133 result = ( result << 8 ) | ( bytes[2] & 0x00FF ); 134 result = ( result << 8 ) | ( bytes[3] & 0x00FF ); 135 result = ( result << 8 ) | ( bytes[4] & 0x00FF ); 136 } 137 else 138 { 139 throw new IntegerDecoderException( I18n.err( I18n.ERR_01304_0_BYTES_LONG_INTEGER ) ); 140 } 141 142 break; 143 144 case 4: 145 if ( bytes[0] == 0x00 ) 146 { 147 result = bytes[1] & 0x00FF; 148 } 149 else 150 { 151 result = bytes[0] & 0x00FF; 152 153 if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 ) 154 { 155 positive = false; 156 } 157 158 result = ( result << 8 ) | ( bytes[1] & 0x00FF ); 159 } 160 161 result = ( result << 8 ) | ( bytes[2] & 0x00FF ); 162 result = ( result << 8 ) | ( bytes[3] & 0x00FF ); 163 164 break; 165 166 case 3: 167 if ( bytes[0] == 0x00 ) 168 { 169 result = bytes[1] & 0x00FF; 170 } 171 else 172 { 173 result = bytes[0] & 0x00FF; 174 175 if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 ) 176 { 177 positive = false; 178 } 179 180 result = ( result << 8 ) | ( bytes[1] & 0x00FF ); 181 } 182 183 result = ( result << 8 ) | ( bytes[2] & 0x00FF ); 184 185 break; 186 187 case 2: 188 if ( bytes[0] == 0x00 ) 189 { 190 result = bytes[1] & 0x00FF; 191 } 192 else 193 { 194 result = bytes[0] & 0x00FF; 195 196 if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 ) 197 { 198 positive = false; 199 } 200 201 result = ( result << 8 ) | ( bytes[1] & 0x00FF ); 202 } 203 204 break; 205 206 case 1: 207 result = ( result << 8 ) | ( bytes[0] & 0x00FF ); 208 209 if ( ( bytes[0] & ( byte ) 0x80 ) == ( byte ) 0x80 ) 210 { 211 positive = false; 212 } 213 214 break; 215 216 default: 217 throw new IntegerDecoderException( I18n.err( I18n.ERR_01305_ABOVE_4_BYTES_INTEGER ) ); 218 } 219 220 if ( !positive ) 221 { 222 result = -( ( ( ~result ) + 1 ) & MASK[bytes.length - 1] ); 223 } 224 225 return result; 226 } 227}