001    /*
002     * Copyright 2008-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2016 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    }