001    /*
002     * Copyright 2009-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2015 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    import com.unboundid.util.Mutable;
026    import com.unboundid.util.ThreadSafety;
027    import com.unboundid.util.ThreadSafetyLevel;
028    
029    import static com.unboundid.asn1.ASN1Messages.*;
030    
031    
032    
033    /**
034     * This class provides a data structure which is used in the course of reading
035     * an ASN.1 sequence from an ASN.1 stream reader.  It provides access to the
036     * BER type and the total number of bytes in the encoded representations of all
037     * of the embedded values, and provides a method to determine when the end of
038     * the sequence has been reached.
039     */
040    @Mutable()
041    @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
042    public final class ASN1StreamReaderSequence
043    {
044      // The ASN.1 stream reader associated with this object.
045      private final ASN1StreamReader reader;
046    
047      // The BER type for this ASN.1 sequence.
048      private final byte type;
049    
050      // The number of bytes contained in the encoded representations of all of the
051      // embedded values.
052      private final int length;
053    
054      // The value for the total number of bytes read from the associated reader at
055      // which the end of the sequence should be encountered.
056      private final long endBytesRead;
057    
058    
059    
060      /**
061       * Creates a new instance of this class with the provided information.
062       *
063       * @param  reader  The ASN.1 stream reader with which this object will be
064       *                 associated.
065       * @param  type    The BER type for this ASN.1 sequence.
066       * @param  length  The number of bytes contained in the encoded
067       *                 representations of all the embedded values.
068       */
069      ASN1StreamReaderSequence(final ASN1StreamReader reader, final byte type,
070                               final int length)
071      {
072        this.reader = reader;
073        this.type   = type;
074        this.length = length;
075    
076        endBytesRead = reader.getTotalBytesRead() + length;
077      }
078    
079    
080    
081      /**
082       * Retrieves the BER type for this ASN.1 sequence.
083       *
084       * @return  The BER type for this ASN.1 sequence.
085       */
086      public byte getType()
087      {
088        return type;
089      }
090    
091    
092    
093      /**
094       * Retrieves the number of bytes contained in the encoded representations of
095       * all the embedded values.
096       *
097       * @return  The number of bytes contained in the encoded representations of
098       *          all the embedded values.
099       */
100      public int getLength()
101      {
102        return length;
103      }
104    
105    
106    
107      /**
108       * Indicates whether there are more elements in this sequence to be read from
109       * the associated ASN.1 stream reader.
110       *
111       * @return  {@code true} if there are more elements in this sequence to be
112       *          read from the associated ASN.1 stream reader or false if the end
113       *          of the sequence has been reached.
114       *
115       * @throws  ASN1Exception  If the associated ASN.1 stream reader has already
116       *                         read beyond the end of the sequence.
117       */
118      public boolean hasMoreElements()
119             throws ASN1Exception
120      {
121        final long currentBytesRead = reader.getTotalBytesRead();
122        if (currentBytesRead == endBytesRead)
123        {
124          return false;
125        }
126        else if (currentBytesRead < endBytesRead)
127        {
128          return true;
129        }
130    
131        throw new ASN1Exception(ERR_STREAM_READER_SEQUENCE_READ_PAST_END.get(
132             length, endBytesRead, currentBytesRead));
133      }
134    }