public String decodeString(boolean implicit) throws Asn1Exception {
        String retValue = null;

        //
        // There must be at least 2 bytes available
        //
        if (residualLength < 2)
            throw new Asn1Exception("Attempt to read past end of stream");

        //
        // Validate the tag for an explicit value
        //
        if (!implicit && stream[next] != ASN1_BMPSTRING)
            throw new Asn1Exception("Field at offset "+next+" is not a BMPSTRING");

        if ((stream[next]&ASN1_CONSTRUCTED) != 0)
            throw new Asn1Exception("BMPSTRING must not be a constructed field");

        next++;
        residualLength--;

        //
        // Decode the field length
        //
        int length = decodeLength();
        int stringLength = length/2;

        if ((length&1) != 0)
            throw new Asn1Exception("Value length "+length+" is not valid");

        if (length > residualLength)
            throw new Asn1Exception("Attempt to read past end of stream");

        //
        // Extract the character string
        //
        if (length != 0) {
            char[] charData = new char[stringLength];

            for (int i=0; i<stringLength; i++) {
                charData[i] = (char)
                        ((((int)stream[next]&0xff)<<8)|((int)stream[next+1]&0xff));
                next += 2;
                residualLength -= 2;
            }

            retValue = new String(charData);
        } else {
            retValue = new String();
        }

        return retValue;
    }