Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.location.cts.asn1.base;
     18 
     19 import static android.location.cts.asn1.base.PerAlignedUtils.SIXTYFOUR_K;
     20 
     21 import com.google.common.base.Preconditions;
     22 import com.google.common.collect.ImmutableList;
     23 
     24 import java.nio.ByteBuffer;
     25 import java.util.Collection;
     26 
     27 /**
     28  * A general string is any ISO 646 related 8-bit encoding, presumably agreed on
     29  *
     30  * Implements ASN.1 functionality.
     31  *
     32  */
     33 public class Asn1GeneralString extends Asn1Object {
     34   private static final Collection<Asn1Tag> possibleFirstTags =
     35       ImmutableList.of(Asn1Tag.GENERAL_STRING);
     36 
     37   private byte[] value;
     38   private int minimumSize = 0;
     39   private Integer maximumSize = null; // Null == unconstrained.
     40 
     41   public static Collection<Asn1Tag> getPossibleFirstTags() {
     42     return possibleFirstTags;
     43   }
     44 
     45   @Override Asn1Tag getDefaultTag() {
     46     return Asn1Tag.GENERAL_STRING;
     47   }
     48 
     49   @Override int getBerValueLength() {
     50     throw new UnsupportedOperationException();
     51   }
     52 
     53   @Override void encodeBerValue(ByteBuffer buf) {
     54     throw new UnsupportedOperationException();
     55   }
     56 
     57   @Override void decodeBerValue(ByteBuffer buf) {
     58     throw new UnsupportedOperationException();
     59   }
     60 
     61   protected void setMinSize(int min) {
     62     minimumSize = min;
     63   }
     64 
     65   protected void setMaxSize(int max) {
     66     maximumSize = max;
     67   }
     68 
     69   public byte[] getValue() {
     70     return value;
     71   }
     72 
     73   public void setValue(byte[] value) {
     74     this.value = value;
     75   }
     76 
     77   private Iterable<BitStream> encodePerImpl(boolean aligned) {
     78     Preconditions.checkNotNull(value, "No value set.");
     79     Preconditions.checkState(value.length >= minimumSize, "Value too short.");
     80     Preconditions.checkState(maximumSize == null || value.length <= maximumSize,
     81                              "Value too long.");
     82     int characterBitCount = 8;
     83     if (maximumSize == null) {
     84       throw new UnsupportedOperationException("unconstrained unimplemented");
     85     }
     86 
     87     BitStream result = new BitStream();
     88     for (byte b : value) {
     89       result.appendByte(b);
     90     }
     91     if (aligned && maximumSize * characterBitCount > 16) {
     92       result.setBeginByteAligned();
     93     }
     94 
     95     if (minimumSize == maximumSize
     96         && maximumSize < SIXTYFOUR_K) {
     97       return ImmutableList.of(result);
     98     }
     99 
    100     if (maximumSize >= SIXTYFOUR_K) {
    101       throw new UnsupportedOperationException("large string unimplemented");
    102     }
    103 
    104     // A little oddity when maximumSize != minimumSize.
    105     if (aligned && maximumSize * characterBitCount == 16) {
    106       result.setBeginByteAligned();
    107     }
    108 
    109     // Must be preceded by a count. The count and the bit field may be
    110     // independently aligned.
    111     BitStream count = null;
    112     if (aligned) {
    113       count = PerAlignedUtils.encodeSmallConstrainedWholeNumber(
    114           value.length, minimumSize, maximumSize);
    115     } else {
    116       count = PerUnalignedUtils.encodeConstrainedWholeNumber(
    117           value.length, minimumSize, maximumSize);
    118     }
    119     return ImmutableList.of(count, result);
    120   }
    121 
    122   @Override public Iterable<BitStream> encodePerUnaligned() {
    123     return encodePerImpl(false);
    124   }
    125 
    126   @Override public Iterable<BitStream> encodePerAligned() {
    127     return encodePerImpl(true);
    128   }
    129 
    130   private void decodePerImpl(BitStreamReader reader, boolean aligned) {
    131     int characterBitCount = 8;
    132     if (maximumSize == null) {
    133       throw new UnsupportedOperationException("unconstrained unimplemented");
    134     }
    135 
    136     if (minimumSize == maximumSize
    137         && maximumSize < SIXTYFOUR_K) {
    138       if (aligned && maximumSize * characterBitCount > 16) {
    139         reader.spoolToByteBoundary();
    140       }
    141       value = new byte[maximumSize];
    142       for (int i = 0; i < maximumSize; i++) {
    143         value[i] = reader.readByte();
    144       }
    145       return;
    146     }
    147 
    148     if (maximumSize >= SIXTYFOUR_K) {
    149       throw new UnsupportedOperationException("large string unimplemented");
    150     }
    151 
    152     // Value is preceded by a count.
    153     int count = 0;
    154     if (aligned) {
    155       count = PerAlignedUtils.decodeSmallConstrainedWholeNumber(
    156           reader, minimumSize, maximumSize);
    157     } else {
    158       count = PerUnalignedUtils.decodeConstrainedWholeNumber(
    159           reader, minimumSize, maximumSize);
    160     }
    161 
    162     if (aligned && maximumSize * characterBitCount >= 16) {
    163       reader.spoolToByteBoundary();
    164     }
    165 
    166     value = new byte[count];
    167     for (int i = 0; i < count; i++) {
    168       value[i] = reader.readByte();
    169     }
    170   }
    171 
    172   @Override public void decodePerUnaligned(BitStreamReader reader) {
    173     decodePerImpl(reader, false);
    174   }
    175 
    176   @Override public void decodePerAligned(BitStreamReader reader) {
    177     decodePerImpl(reader, true);
    178   }
    179 }
    180