001 /*
002 * Copyright 2008-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2014 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.asn1;
022
023
024
025
026 import static com.unboundid.asn1.ASN1Constants.*;
027 import static com.unboundid.asn1.ASN1Messages.*;
028 import static com.unboundid.util.Debug.*;
029
030
031
032 /**
033 * This class provides an ASN.1 long element. It is exactly the same as an
034 * ASN.1 integer, but it uses a 64-bit representation for the decoded value
035 * rather than a 32-bit representation.
036 */
037 public final class ASN1Long
038 extends ASN1Element
039 {
040 /**
041 * The serial version UID for this serializable class.
042 */
043 private static final long serialVersionUID = -3445506299288414013L;
044
045
046
047 // The long value for this element.
048 private final long longValue;
049
050
051
052 /**
053 * Creates a new ASN.1 long element with the default BER type and the
054 * provided long value.
055 *
056 * @param longValue The long value to use for this element.
057 */
058 public ASN1Long(final long longValue)
059 {
060 super(UNIVERSAL_INTEGER_TYPE, encodeLongValue(longValue));
061
062 this.longValue = longValue;
063 }
064
065
066
067 /**
068 * Creates a new ASN.1 long element with the specified BER type and the
069 * provided long value.
070 *
071 * @param type The BER type to use for this element.
072 * @param longValue The long value to use for this element.
073 */
074 public ASN1Long(final byte type, final long longValue)
075 {
076 super(type, encodeLongValue(longValue));
077
078 this.longValue = longValue;
079 }
080
081
082
083 /**
084 * Creates a new ASN.1 long element with the specified BER type and the
085 * provided long and pre-encoded values.
086 *
087 * @param type The BER type to use for this element.
088 * @param longValue The long value to use for this element.
089 * @param value The pre-encoded value to use for this element.
090 */
091 private ASN1Long(final byte type, final long longValue, final byte[] value)
092 {
093 super(type, value);
094
095 this.longValue = longValue;
096 }
097
098
099
100 /**
101 * Encodes the provided long value to a byte array suitable for use as the
102 * value of a long element.
103 *
104 * @param longValue The long value to be encoded.
105 *
106 * @return A byte array containing the encoded value.
107 */
108 static byte[] encodeLongValue(final long longValue)
109 {
110 if (longValue < 0)
111 {
112 if ((longValue & 0xFFFFFFFFFFFFFF80L) == 0xFFFFFFFFFFFFFF80L)
113 {
114 return new byte[]
115 {
116 (byte) (longValue & 0xFFL)
117 };
118 }
119 else if ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L)
120 {
121 return new byte[]
122 {
123 (byte) ((longValue >> 8) & 0xFFL),
124 (byte) (longValue & 0xFFL)
125 };
126 }
127 else if ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L)
128 {
129 return new byte[]
130 {
131 (byte) ((longValue >> 16) & 0xFFL),
132 (byte) ((longValue >> 8) & 0xFFL),
133 (byte) (longValue & 0xFFL)
134 };
135 }
136 else if ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L)
137 {
138 return new byte[]
139 {
140 (byte) ((longValue >> 24) & 0xFFL),
141 (byte) ((longValue >> 16) & 0xFFL),
142 (byte) ((longValue >> 8) & 0xFFL),
143 (byte) (longValue & 0xFFL)
144 };
145 }
146 else if ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L)
147 {
148 return new byte[]
149 {
150 (byte) ((longValue >> 32) & 0xFFL),
151 (byte) ((longValue >> 24) & 0xFFL),
152 (byte) ((longValue >> 16) & 0xFFL),
153 (byte) ((longValue >> 8) & 0xFFL),
154 (byte) (longValue & 0xFFL)
155 };
156 }
157 else if ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L)
158 {
159 return new byte[]
160 {
161 (byte) ((longValue >> 40) & 0xFFL),
162 (byte) ((longValue >> 32) & 0xFFL),
163 (byte) ((longValue >> 24) & 0xFFL),
164 (byte) ((longValue >> 16) & 0xFFL),
165 (byte) ((longValue >> 8) & 0xFFL),
166 (byte) (longValue & 0xFFL)
167 };
168 }
169 else if ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L)
170 {
171 return new byte[]
172 {
173 (byte) ((longValue >> 48) & 0xFFL),
174 (byte) ((longValue >> 40) & 0xFFL),
175 (byte) ((longValue >> 32) & 0xFFL),
176 (byte) ((longValue >> 24) & 0xFFL),
177 (byte) ((longValue >> 16) & 0xFFL),
178 (byte) ((longValue >> 8) & 0xFFL),
179 (byte) (longValue & 0xFFL)
180 };
181 }
182 else
183 {
184 return new byte[]
185 {
186 (byte) ((longValue >> 56) & 0xFFL),
187 (byte) ((longValue >> 48) & 0xFFL),
188 (byte) ((longValue >> 40) & 0xFFL),
189 (byte) ((longValue >> 32) & 0xFFL),
190 (byte) ((longValue >> 24) & 0xFFL),
191 (byte) ((longValue >> 16) & 0xFFL),
192 (byte) ((longValue >> 8) & 0xFFL),
193 (byte) (longValue & 0xFFL)
194 };
195 }
196 }
197 else
198 {
199 if ((longValue & 0x000000000000007FL) == longValue)
200 {
201 return new byte[]
202 {
203 (byte) (longValue & 0x7FL)
204 };
205 }
206 else if ((longValue & 0x0000000000007FFFL) == longValue)
207 {
208 return new byte[]
209 {
210 (byte) ((longValue >> 8) & 0x7FL),
211 (byte) (longValue & 0xFFL)
212 };
213 }
214 else if ((longValue & 0x00000000007FFFFFL) == longValue)
215 {
216 return new byte[]
217 {
218 (byte) ((longValue >> 16) & 0x7FL),
219 (byte) ((longValue >> 8) & 0xFFL),
220 (byte) (longValue & 0xFFL)
221 };
222 }
223 else if ((longValue & 0x000000007FFFFFFFL) == longValue)
224 {
225 return new byte[]
226 {
227 (byte) ((longValue >> 24) & 0x7FL),
228 (byte) ((longValue >> 16) & 0xFFL),
229 (byte) ((longValue >> 8) & 0xFFL),
230 (byte) (longValue & 0xFFL)
231 };
232 }
233 else if ((longValue & 0x0000007FFFFFFFFFL) == longValue)
234 {
235 return new byte[]
236 {
237 (byte) ((longValue >> 32) & 0x7FL),
238 (byte) ((longValue >> 24) & 0xFFL),
239 (byte) ((longValue >> 16) & 0xFFL),
240 (byte) ((longValue >> 8) & 0xFFL),
241 (byte) (longValue & 0xFFL)
242 };
243 }
244 else if ((longValue & 0x00007FFFFFFFFFFFL) == longValue)
245 {
246 return new byte[]
247 {
248 (byte) ((longValue >> 40) & 0x7FL),
249 (byte) ((longValue >> 32) & 0xFFL),
250 (byte) ((longValue >> 24) & 0xFFL),
251 (byte) ((longValue >> 16) & 0xFFL),
252 (byte) ((longValue >> 8) & 0xFFL),
253 (byte) (longValue & 0xFFL)
254 };
255 }
256 else if ((longValue & 0x007FFFFFFFFFFFFFL) == longValue)
257 {
258 return new byte[]
259 {
260 (byte) ((longValue >> 48) & 0x7FL),
261 (byte) ((longValue >> 40) & 0xFFL),
262 (byte) ((longValue >> 32) & 0xFFL),
263 (byte) ((longValue >> 24) & 0xFFL),
264 (byte) ((longValue >> 16) & 0xFFL),
265 (byte) ((longValue >> 8) & 0xFFL),
266 (byte) (longValue & 0xFFL)
267 };
268 }
269 else
270 {
271 return new byte[]
272 {
273 (byte) ((longValue >> 56) & 0x7FL),
274 (byte) ((longValue >> 48) & 0xFFL),
275 (byte) ((longValue >> 40) & 0xFFL),
276 (byte) ((longValue >> 32) & 0xFFL),
277 (byte) ((longValue >> 24) & 0xFFL),
278 (byte) ((longValue >> 16) & 0xFFL),
279 (byte) ((longValue >> 8) & 0xFFL),
280 (byte) (longValue & 0xFFL)
281 };
282 }
283 }
284 }
285
286
287
288 /**
289 * Retrieves the long value for this element.
290 *
291 * @return The long value for this element.
292 */
293 public long longValue()
294 {
295 return longValue;
296 }
297
298
299
300 /**
301 * Decodes the contents of the provided byte array as a long element.
302 *
303 * @param elementBytes The byte array to decode as an ASN.1 long element.
304 *
305 * @return The decoded ASN.1 long element.
306 *
307 * @throws ASN1Exception If the provided array cannot be decoded as a long
308 * element.
309 */
310 public static ASN1Long decodeAsLong(final byte[] elementBytes)
311 throws ASN1Exception
312 {
313 try
314 {
315 int valueStartPos = 2;
316 int length = (elementBytes[1] & 0x7F);
317 if (length != elementBytes[1])
318 {
319 final int numLengthBytes = length;
320
321 length = 0;
322 for (int i=0; i < numLengthBytes; i++)
323 {
324 length <<= 8;
325 length |= (elementBytes[valueStartPos++] & 0xFF);
326 }
327 }
328
329 if ((elementBytes.length - valueStartPos) != length)
330 {
331 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length,
332 (elementBytes.length - valueStartPos)));
333 }
334
335 final byte[] value = new byte[length];
336 System.arraycopy(elementBytes, valueStartPos, value, 0, length);
337
338 long longValue;
339 switch (value.length)
340 {
341 case 1:
342 longValue = (value[0] & 0xFFL);
343 if ((value[0] & 0x80L) != 0x00L)
344 {
345 longValue |= 0xFFFFFFFFFFFFFF00L;
346 }
347 break;
348
349 case 2:
350 longValue = ((value[0] & 0xFFL) << 8) | (value[1] & 0xFFL);
351 if ((value[0] & 0x80L) != 0x00L)
352 {
353 longValue |= 0xFFFFFFFFFFFF0000L;
354 }
355 break;
356
357 case 3:
358 longValue = ((value[0] & 0xFFL) << 16) | ((value[1] & 0xFFL) << 8) |
359 (value[2] & 0xFFL);
360 if ((value[0] & 0x80L) != 0x00L)
361 {
362 longValue |= 0xFFFFFFFFFF000000L;
363 }
364 break;
365
366 case 4:
367 longValue = ((value[0] & 0xFFL) << 24) | ((value[1] & 0xFFL) << 16) |
368 ((value[2] & 0xFFL) << 8) | (value[3] & 0xFFL);
369 if ((value[0] & 0x80L) != 0x00L)
370 {
371 longValue |= 0xFFFFFFFF00000000L;
372 }
373 break;
374
375 case 5:
376 longValue = ((value[0] & 0xFFL) << 32) | ((value[1] & 0xFFL) << 24) |
377 ((value[2] & 0xFFL) << 16) | ((value[3] & 0xFFL) << 8) |
378 (value[4] & 0xFFL);
379 if ((value[0] & 0x80L) != 0x00L)
380 {
381 longValue |= 0xFFFFFF0000000000L;
382 }
383 break;
384
385 case 6:
386 longValue = ((value[0] & 0xFFL) << 40) | ((value[1] & 0xFFL) << 32) |
387 ((value[2] & 0xFFL) << 24) | ((value[3] & 0xFFL) << 16) |
388 ((value[4] & 0xFFL) << 8) | (value[5] & 0xFFL);
389 if ((value[0] & 0x80L) != 0x00L)
390 {
391 longValue |= 0xFFFF000000000000L;
392 }
393 break;
394
395 case 7:
396 longValue = ((value[0] & 0xFFL) << 48) | ((value[1] & 0xFFL) << 40) |
397 ((value[2] & 0xFFL) << 32) | ((value[3] & 0xFFL) << 24) |
398 ((value[4] & 0xFFL) << 16) | ((value[5] & 0xFFL) << 8) |
399 (value[6] & 0xFFL);
400 if ((value[0] & 0x80L) != 0x00L)
401 {
402 longValue |= 0xFF00000000000000L;
403 }
404 break;
405
406 case 8:
407 longValue = ((value[0] & 0xFFL) << 56) | ((value[1] & 0xFFL) << 48) |
408 ((value[2] & 0xFFL) << 40) | ((value[3] & 0xFFL) << 32) |
409 ((value[4] & 0xFFL) << 24) | ((value[5] & 0xFFL) << 16) |
410 ((value[6] & 0xFFL) << 8) | (value[7] & 0xFFL);
411 break;
412
413 default:
414 throw new ASN1Exception(ERR_LONG_INVALID_LENGTH.get(value.length));
415 }
416
417 return new ASN1Long(elementBytes[0], longValue, value);
418 }
419 catch (final ASN1Exception ae)
420 {
421 debugException(ae);
422 throw ae;
423 }
424 catch (final Exception e)
425 {
426 debugException(e);
427 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e);
428 }
429 }
430
431
432
433 /**
434 * Decodes the provided ASN.1 element as a long element.
435 *
436 * @param element The ASN.1 element to be decoded.
437 *
438 * @return The decoded ASN.1 long element.
439 *
440 * @throws ASN1Exception If the provided element cannot be decoded as a long
441 * element.
442 */
443 public static ASN1Long decodeAsLong(final ASN1Element element)
444 throws ASN1Exception
445 {
446 long longValue;
447 final byte[] value = element.getValue();
448 switch (value.length)
449 {
450 case 1:
451 longValue = (value[0] & 0xFFL);
452 if ((value[0] & 0x80L) != 0x00L)
453 {
454 longValue |= 0xFFFFFFFFFFFFFF00L;
455 }
456 break;
457
458 case 2:
459 longValue = ((value[0] & 0xFFL) << 8) | (value[1] & 0xFFL);
460 if ((value[0] & 0x80L) != 0x00L)
461 {
462 longValue |= 0xFFFFFFFFFFFF0000L;
463 }
464 break;
465
466 case 3:
467 longValue = ((value[0] & 0xFFL) << 16) | ((value[1] & 0xFFL) << 8) |
468 (value[2] & 0xFFL);
469 if ((value[0] & 0x80L) != 0x00L)
470 {
471 longValue |= 0xFFFFFFFFFF000000L;
472 }
473 break;
474
475 case 4:
476 longValue = ((value[0] & 0xFFL) << 24) | ((value[1] & 0xFFL) << 16) |
477 ((value[2] & 0xFFL) << 8) | (value[3] & 0xFFL);
478 if ((value[0] & 0x80L) != 0x00L)
479 {
480 longValue |= 0xFFFFFFFF00000000L;
481 }
482 break;
483
484 case 5:
485 longValue = ((value[0] & 0xFFL) << 32) | ((value[1] & 0xFFL) << 24) |
486 ((value[2] & 0xFFL) << 16) | ((value[3] & 0xFFL) << 8) |
487 (value[4] & 0xFFL);
488 if ((value[0] & 0x80L) != 0x00L)
489 {
490 longValue |= 0xFFFFFF0000000000L;
491 }
492 break;
493
494 case 6:
495 longValue = ((value[0] & 0xFFL) << 40) | ((value[1] & 0xFFL) << 32) |
496 ((value[2] & 0xFFL) << 24) | ((value[3] & 0xFFL) << 16) |
497 ((value[4] & 0xFFL) << 8) | (value[5] & 0xFFL);
498 if ((value[0] & 0x80L) != 0x00L)
499 {
500 longValue |= 0xFFFF000000000000L;
501 }
502 break;
503
504 case 7:
505 longValue = ((value[0] & 0xFFL) << 48) | ((value[1] & 0xFFL) << 40) |
506 ((value[2] & 0xFFL) << 32) | ((value[3] & 0xFFL) << 24) |
507 ((value[4] & 0xFFL) << 16) | ((value[5] & 0xFFL) << 8) |
508 (value[6] & 0xFFL);
509 if ((value[0] & 0x80L) != 0x00L)
510 {
511 longValue |= 0xFF00000000000000L;
512 }
513 break;
514
515 case 8:
516 longValue = ((value[0] & 0xFFL) << 56) | ((value[1] & 0xFFL) << 48) |
517 ((value[2] & 0xFFL) << 40) | ((value[3] & 0xFFL) << 32) |
518 ((value[4] & 0xFFL) << 24) | ((value[5] & 0xFFL) << 16) |
519 ((value[6] & 0xFFL) << 8) | (value[7] & 0xFFL);
520 break;
521
522 default:
523 throw new ASN1Exception(ERR_LONG_INVALID_LENGTH.get(value.length));
524 }
525
526 return new ASN1Long(element.getType(), longValue, value);
527 }
528
529
530
531 /**
532 * Appends a string representation of this ASN.1 element to the provided
533 * buffer.
534 *
535 * @param buffer The buffer to which to append the information.
536 */
537 @Override()
538 public void toString(final StringBuilder buffer)
539 {
540 buffer.append(longValue);
541 }
542 }