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 java.util.Collections;
     20 import java.util.Comparator;
     21 
     22 /**
     23  * Implements ASN.1 functionality. An asn1 set is a collection where order is
     24  * not significant, but it does not guarantee absence of duplicates.
     25  *
     26  */
     27 public abstract class Asn1SetOf<T extends Asn1Object>
     28     extends Asn1SequenceOf<T> {
     29 
     30   @Override Asn1Tag getDefaultTag() {
     31     return Asn1Tag.SET;
     32   }
     33 
     34   private Iterable<BitStream> encodePerImpl(final boolean aligned) {
     35     // Encode according to canonical PER, always works.
     36     Collections.sort(sequence,
     37                      new Comparator<T>() {
     38                        @Override
     39                        public int compare(T lhsT, T rhsT) {
     40                          PacketBuilder keyMaker = new PacketBuilder();
     41                          if (aligned) {
     42                            keyMaker.appendAll(lhsT.encodePerAligned());
     43                          } else {
     44                            keyMaker.appendAll(lhsT.encodePerUnaligned());
     45                          }
     46                          byte[] lhs = keyMaker.getPaddedBytes();
     47                          keyMaker = new PacketBuilder();
     48                          if (aligned) {
     49                            keyMaker.appendAll(rhsT.encodePerAligned());
     50                          } else {
     51                            keyMaker.appendAll(rhsT.encodePerUnaligned());
     52                          }
     53                          byte[] rhs = keyMaker.getPaddedBytes();
     54                          for (int i = 0; i < lhs.length && i < rhs.length;
     55                               ++i) {
     56                            if ((lhs[i] & 0xFF) < (rhs[i] & 0xFF)) {
     57                              return -1;
     58                            }
     59                            if ((lhs[i] & 0xFF) > (rhs[i] & 0xFF)) {
     60                              return 1;
     61                            }
     62                          }
     63                          if (lhs.length < rhs.length) {
     64                            return -1;
     65                          }
     66                          if (lhs.length > rhs.length) {
     67                            return 1;
     68                          }
     69                          return 0;
     70                        }
     71                      }
     72     );
     73 
     74     if (aligned) {
     75       return super.encodePerAligned();
     76     } else {
     77       return super.encodePerUnaligned();
     78     }
     79   }
     80 
     81   @Override public Iterable<BitStream> encodePerUnaligned() {
     82     return encodePerImpl(false);
     83   }
     84 
     85   @Override public Iterable<BitStream> encodePerAligned() {
     86     return encodePerImpl(true);
     87   }
     88 }
     89