content: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You under the Apache License, Version 2.0
   *  (the "License"); you may not use this file except in compliance with
   *  the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  /**
  * @author Vladimir N. Molotkov, Stepan M. Mishura
  */
  
  package android.org.apache.harmony.security.asn1;
  
  
  /**
   * Encodes ASN.1 types with BER (X.690)
   * 
   * @see http://asn1.elibel.tm.fr/en/standards/index.htm
   */
  
  public class BerOutputStream {
  
      /**
       *  Encoded byte array
       */
      public byte[] encoded;
  
      /**
       *  current offset
       */
      protected int offset;
  
      /**
       * Current encoded length
       */
      public int length;
  
      /**
       * Current encoded content
       */
      public Object content;
  
      public BerOutputStream() {
      }
  
      public final void encodeTag(int tag) {
  
          encoded[offset++] = (byte) tag; //FIXME long form?
  
          if (length > 127) { //long form
              int eLen = length >> 8;
              byte numOctets = 1;
              for (; eLen > 0; eLen = eLen >> 8) {
                  numOctets++;
              }
  
              encoded[offset] = (byte) (numOctets | 0x80);
              offset++;
  
              eLen = length;
              int numOffset = offset + numOctets - 1;
              for (int i = 0; i < numOctets; i++, eLen = eLen >> 8) {
                  encoded[numOffset - i] = (byte) eLen; //FIXME long value?
              }
              offset += numOctets;
          } else { //short form
              encoded[offset++] = (byte) length;
          }
      }
  
      public void encodeANY() {
          System.arraycopy(content, 0, encoded, offset, length);
          offset += length;
      }
  
      public void encodeBitString() {
          //FIXME check encoding
          BitString bStr = (BitString) content;
          encoded[offset] = (byte) bStr.unusedBits;
          System.arraycopy(bStr.bytes, 0, encoded, offset + 1, length - 1);
          offset += length;
      }
  
      public void encodeBoolean() {
          if (((Boolean) content).booleanValue()) {
              encoded[offset] = (byte) 0xFF;
          } else {
              encoded[offset] = 0x00;
          }
          offset++;
      }
  
      public void encodeChoice(ASN1Choice choice) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void encodeExplicit(ASN1Explicit explicit) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void encodeGeneralizedTime() {
          System.arraycopy(content, 0, encoded, offset, length);
          offset += length;
      }
  
      public void encodeUTCTime() {
          System.arraycopy(content, 0, encoded, offset, length);
          offset += length;
      }
  
      public void encodeInteger() {
          System.arraycopy(content, 0, encoded, offset, length);
          offset += length;
      }
  
      public void encodeOctetString() {
          System.arraycopy(content, 0, encoded, offset, length);
          offset += length;
      }
  
      public void encodeOID() {
  
          int[] oid = (int[]) content;
  
          int oidLen = length;
  
          // all subidentifiers except first
          int elem;
          for (int i = oid.length - 1; i > 1; i--, oidLen--) {
              elem = oid[i];
              if (elem > 127) {
                  encoded[offset + oidLen - 1] = (byte) (elem & 0x7F);
                  elem = elem >> 7;
                  for (; elem > 0;) {
                      oidLen--;
                      encoded[offset + oidLen - 1] = (byte) (elem | 0x80);
                      elem = elem >> 7;
                  }
              } else {
                  encoded[offset + oidLen - 1] = (byte) elem;
              }
          }
  
          // first subidentifier
          elem = oid[0] * 40 + oid[1];
          if (elem > 127) {
              encoded[offset + oidLen - 1] = (byte) (elem & 0x7F);
              elem = elem >> 7;
              for (; elem > 0;) {
                  oidLen--;
                  encoded[offset + oidLen - 1] = (byte) (elem | 0x80);
                  elem = elem >> 7;
              }
          } else {
              encoded[offset + oidLen - 1] = (byte) elem;
          }
  
          offset += length;
      }
  
      public void encodeSequence(ASN1Sequence sequence) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void encodeSequenceOf(ASN1SequenceOf sequenceOf) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void encodeSet(ASN1Set set) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void encodeSetOf(ASN1SetOf setOf) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void encodeString() {
          System.arraycopy(content, 0, encoded, offset, length);
          offset += length;
      }
  
      /*
       * LENGTH 
       */
  
      public void getChoiceLength(ASN1Choice choice) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void getExplicitLength(ASN1Explicit sequence) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void getSequenceLength(ASN1Sequence sequence) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void getSequenceOfLength(ASN1SequenceOf sequence) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void getSetLength(ASN1Set set) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public void getSetOfLength(ASN1SetOf setOf) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  
      public int getStringLength(Object object) {
          throw new RuntimeException("Is not implemented yet"); //FIXME
      }
  }