Package co.nstant.in.cbor.encoder

Source Code of co.nstant.in.cbor.encoder.MapEncoder

package co.nstant.in.cbor.encoder;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Comparator;
import java.util.TreeMap;

import co.nstant.in.cbor.CborEncoder;
import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.MajorType;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.SimpleValue;

public class MapEncoder extends AbstractEncoder<Map> {

  public MapEncoder(CborEncoder encoder, OutputStream outputStream) {
    super(encoder, outputStream);
  }

  @Override
  public void encode(Map map) throws CborException {
    Collection<DataItem> keys = map.getKeys();

    if (map.isChunked()) {
      encodeTypeChunked(MajorType.MAP);
    } else {
      encodeTypeAndLength(MajorType.MAP, keys.size());
    }

    if (keys.isEmpty()) {
      return;
    }

    if (map.isChunked()) {
      for (DataItem key : keys) {
        encoder.encode(key);
        encoder.encode(map.get(key));
      }
      encoder.encode(SimpleValue.BREAK);
      return;
    }

    /**
     * The keys in every map must be sorted lowest value to highest. Sorting
     * is performed on the bytes of the representation of the key data items
     * without paying attention to the 3/5 bit splitting for major types.
     * (Note that this rule allows maps that have keys of different types,
     * even though that is probably a bad practice that could lead to errors
     * in some canonicalization implementations.) The sorting rules are:
     *
     * If two keys have different lengths, the shorter one sorts earlier;
     *
     * If two keys have the same length, the one with the lower value in
     * (byte-wise) lexical order sorts earlier.
     */

    TreeMap<byte[], byte[]> sortedMap = new TreeMap<>(new Comparator<byte[]>() {

      @Override
      public int compare(byte[] o1, byte[] o2) {
        if (o1.length < o2.length) {
          return -1;
        }
        if (o1.length > o2.length) {
          return 1;
        }
        for (int i = 0; i < o1.length; i++) {
          if (o1[i] < o2[i]) {
            return -1;
          }
          if (o1[i] > o2[i]) {
            return 1;
          }
        }
        return 0;
      }

    });
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    CborEncoder e = new CborEncoder(byteArrayOutputStream);
    for (DataItem key : keys) {
      // Key
      e.encode(key);
      byte[] keyBytes = byteArrayOutputStream.toByteArray();
      byteArrayOutputStream.reset();
      // Value
      e.encode(map.get(key));
      byte[] valueBytes = byteArrayOutputStream.toByteArray();
      byteArrayOutputStream.reset();
      sortedMap.put(keyBytes, valueBytes);
    }
    for (java.util.Map.Entry<byte[], byte[]> entry : sortedMap.entrySet()) {
      write(entry.getKey());
      write(entry.getValue());
    }
  }

}
TOP

Related Classes of co.nstant.in.cbor.encoder.MapEncoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.