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